CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

How to set only 1 bit of a register?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
stoyanoff



Joined: 20 Jul 2011
Posts: 375

View user's profile Send private message

How to set only 1 bit of a register?
PostPosted: Tue Dec 04, 2012 2:23 am     Reply with quote

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:
Code:

set_tris_a();

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

View user's profile Send private message

PostPosted: Tue Dec 04, 2012 3:48 am     Reply with quote

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: 19518

View user's profile Send private message

PostPosted: Tue Dec 04, 2012 9:07 am     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Tue Dec 04, 2012 5:06 pm     Reply with quote

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 ).
Very Happy Very Happy
stoyanoff



Joined: 20 Jul 2011
Posts: 375

View user's profile Send private message

PostPosted: Wed Dec 05, 2012 1:30 am     Reply with quote

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: 19518

View user's profile Send private message

PostPosted: Wed Dec 05, 2012 2:08 am     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Wed Dec 05, 2012 8:09 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Dec 06, 2012 1:53 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Dec 07, 2012 3:46 am     Reply with quote

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: 19518

View user's profile Send private message

PostPosted: Fri Dec 07, 2012 5:20 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Dec 08, 2012 5:34 am     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Sat Dec 08, 2012 8:54 am     Reply with quote

ahh yes, the 4th way .....
as already pointed out:
let the compiler translate:

#byte TRISA=getenv("SFR:TRISA")
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group