View previous topic :: View next topic |
Author |
Message |
stoyanoff
Joined: 20 Jul 2011 Posts: 375
|
How to set only 1 bit of a register? |
Posted: Tue Dec 04, 2012 2:23 am |
|
|
Hi! I want to know how to set only 1 bit from a register. For example if I want to set PIN_A0 to be an input I should set TRISA0 bit to 1. I don`t like this:
because it changes the other pins of PORT A.
How can I achieve this??
Thanks! |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Dec 04, 2012 3:48 am |
|
|
You use the CCS:-
Code: | value = input(PIN_A0) | The compiler takes care of the tris etc.
If your chosen pin can be analogue, that will have to be turned off.
It's all in the CCS manual.
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Tue Dec 04, 2012 9:07 am |
|
|
Or if you feel you must access TRIS separately, 'output_drive' sets a pin to output, and 'output_float' sets it as an input.
Best Wishes |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Dec 04, 2012 5:06 pm |
|
|
There are at least 4 OK CCS ways to do this:
The 3rd is to use get_ /set_tris with masking of one or more bits between the operations.
The 4th way is to avoid fixed/static IO and just do the input or output operation you wish on the pin, and let the compiler sort our the TRIS for you , which it can do rather well if you let it ( oh right Mike W already pointed you to that ).
|
|
|
stoyanoff
Joined: 20 Jul 2011 Posts: 375
|
|
Posted: Wed Dec 05, 2012 1:30 am |
|
|
I'm using 18F66J60 and the automatic setup from ccs doesn`t work.
I've seen this trick with the mask. It should be something like this:
Code: |
*0xF93=*0xF93 && 0x01;
|
I'll try this methods. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Wed Dec 05, 2012 2:08 am |
|
|
Seriously, avoid this.
Multiple reasons:
1) Avoid using hardwired register addresses like this. Reduces portability.
2) Takes a lot of time. This will involve reading the register, performing the masking operation, and writing it back.
0xF93, is not the TRISA register, which you asked about. It is TRISB.
Now, what do you mean 'the automatic setup from CCS doesn't work'. Just tried:
output_float(PIN_B0);
Which is the instruction to set the bottom TRIS bit for this register, and it correctly codes for your processor, to:
Code: |
.................... output_float(PIN_B0);
0020: BSF F93.0
|
Setting bit 0 in this register as required. Worked with 4.134, and .140 correctly.
If you must do it by register access, then code as:
Code: |
#byte TRISB=getenv("SFR:TRISB")
#bit TRISB0=TRISB.0
TRISB0=1;
//which again correctly generates:
0022: BSF F93.0
|
Compare with the bit code you show, and a version modified to use register names:
Code: |
#byte TRISB=getenv("SFR:TRISB")
.................... *0xF93=*0xF93 && 0x01;
0024: MOVF F93,F
0026: BNZ 002C
0028: MOVLW 00
002A: BRA 002E
002C: MOVLW 01
002E: MOVWF F93
....................
.................... TRISB=TRISB && 0x01;
0030: MOVF F93,F
0032: BNZ 0038
0034: MOVLW 00
0036: BRA 003A
0038: MOVLW 01
003A: MOVWF F93
//Or just use bit_set
.................... bit_set(TRISB,0);
003C: BSF F93.0
|
Note how much bulkier, slower, etc., the mask versions are....
Use the output_float, or bit_set with the register named as shown......
Best Wishes |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Dec 05, 2012 8:09 am |
|
|
Masking is of use when 2 or more pins are to be changed synchronously.
The key concept is if a synchronous state change is required for more than one pin at a time then mask. Otherwise one at a time is most code efficient. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Dec 06, 2012 1:53 am |
|
|
One last note: Code: | *0xF93=*0xF93 && 0x01; | This code will fail for other values than 0 or 1. '&&' is the 'logical AND' operator which can only return 0 or 1. What should have been used is the 'bit wise AND' operator '&': Code: | *0xF93=*0xF93 & 0x01; |
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Dec 07, 2012 3:46 am |
|
|
Couldn't help myself but tested the '&&' version against the correct '&' version: Code: | #byte TRISB=getenv("SFR:TRISB")
.................... *0xF93=*0xF93 & 0x01;
0026: MOVLW 01
0028: ANDWF TRISB,F
.................... TRISB=TRISB & 0x01;
002A: ANDWF TRISB,F
....................
.................... //Or just use bit_set
.................... bit_set(TRISB,0);
002C: BSF TRISB.TRISB0 | Now the mask version is reduced to only 2 instructions instead of 6.
Conclusion:
For just (re)setting a single bit the bit_set() function is fastest with 1 instruction, but for 2 or more bits the masked version is equal or faster. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Fri Dec 07, 2012 5:20 am |
|
|
Yes, if you think about it, the && version performs a logical test before the mask. That is the extra code.
I'd expect the mask code generally to be worse on a PIC16, with bank switching getting involved, so probably going up to four instructions instead.
Best Wishes |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Sat Dec 08, 2012 5:34 am |
|
|
Code: |
#BYTE TRISA = 0xF92 // for pic18F2520 and change this value accoding to your controller
#BIT TRIS_A0 = TRISA.0
#BIT TRIS_A1 = TRISA.1
#BIT TRIS_A2 = TRISA.2
#BIT TRIS_A3 = TRISA.3
#BIT TRIS_A4 = TRISA.4
#BIT TRIS_A5 = TRISA.5
#BIT TRIS_A6 = TRISA.6
#BIT TRIS_A7 = TRISA.7 |
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sat Dec 08, 2012 8:54 am |
|
|
ahh yes, the 4th way .....
as already pointed out:
let the compiler translate:
#byte TRISA=getenv("SFR:TRISA") |
|
|
|