Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

C Bit Assigning

Status
Not open for further replies.
PORTB.B2 = Temp & 0b00000010;
It will return 2 or 0. Some compilers when casting a byte to a bit simple use the bottom bit and so this will also be wrong.

This is exactly the thing that was puzzling me. I've never liked the "PORTB.2" notation because I don't know exactly how the compiler handles it.

Of course it would be easy to read the compiler specs.. or the generated assembly. But I think the code itself should be unambiguous.
 
Last edited:
Mike said:
I also just looked at the MicroC manual and it states it uses the lowest bits when casting.

Unextended c only knows how to cast between the built in types. It will not cast a byte to a bit.

ANSI c uses an enumerated type BOOLEAN for true and false but can not cast to it.

Have you fired up MikroC to find out if it can cast a byte to a bit ? If it can I would not expect that to effect the operation of if(expression).
 
Last edited:
...
Have you fired up MikroC to find out if it can cast a byte to a bit ? If it can I would not expect that to effect the operation of if(expression).

I had MikroC handy, so looked int he help file, there is nothing to indicate how PORTB.F1 would be assigned.

So I threw in some code and did an assembler dump;

Code:
unsigned char blah;
unsigned char bloo;

void main()
{
     blah = 0b00001000;
     PORTB.F1 = blah;
     
     blah = 0b01000000;
     bloo.F3 = blah;
}

and the assembler generated (for PIC 16F877A) was this;

Code:
;Led_Blinking.c,23 :: 		void main() {
;Led_Blinking.c,26 :: 		blah = 0b00001000;
$0004	$3008			MOVLW	8
$0005	$1303			BCF	STATUS, RP1
$0006	$1283			BCF	STATUS, RP0
$0007	$00A0			MOVWF	_blah
;Led_Blinking.c,27 :: 		PORTB.F1 = blah;
$0008	$3000			MOVLW	0
$0009	$1820			BTFSC	_blah, 0
$000A	$3002			MOVLW	2
$000B	$0606			XORWF	PORTB, 0
$000C	$3902			ANDLW	2
$000D	$0686			XORWF	PORTB, 1
;Led_Blinking.c,29 :: 		blah = 0b01000000;
$000E	$3040			MOVLW	64
$000F	$00A0			MOVWF	_blah
;Led_Blinking.c,30 :: 		bloo.F3 = blah;
$0010	$3000			MOVLW	0
$0011	$1820			BTFSC	_blah, 0
$0012	$3008			MOVLW	8
$0013	$0621			XORWF	_bloo, 0
$0014	$3908			ANDLW	8
$0015	$06A1			XORWF	_bloo, 1

I tested a port register and a 8bit ram variable, results were both the same. The MikroC compiler tests ONLY the bit0 of blah, and then sets or clears the specified bit of the receiving register.

That test was in MikroC. I tested in MikroC PRO (the newer and more optimised compiler) and on 18F452 it does the same test of bit0 of blah, but then uses BCF or BSF on the receiving register. Both systems use about the same number of cycles.
 
It seems to be universally accepted that when casting it is correct to discard the higher bits.

Just checked BoostC and this has two 1 bit variables, bit and bool. The bit type test bit 0 of the result and bool test the result for non zero.

Mike.
 
I am concerned that people will confuse bit casting with casting to a bool value.

Casting by keeping or extend the rightmost bits is called standard casting. If the cast is from a byte to a bool it does not hold, we need another flavor of casting. It would be better to cast any non zero byte to 1(true) in keeping with the c tradition that any non zero value is true.


Standard c does a correct cast to bool each time we use if(expression).
 
In MikroC it allows testing register bits in if() like this;

Code:
void main()
{
     blah = 0b00001000;
     if(blah.F3) bloo = 1;
}

;Becomes;
;Led_Blinking.c,25 :: 		if(blah.F3) bloo = 1;
$0008	$1DA0			BTFSS	_blah, 3
$0009	$280C			GOTO	L_main_0
$000A	$3001			MOVLW	1
$000B	$00A1			MOVWF	_bloo
$000C	$	L_main_0:

Which is pretty much what you would expect for if() testing a bit. Otherwise if() tests are evaluated for zero or non-zero as you said.
 
That is exactly why I added the !=0 in post 6, to force a cast to bool and why I was quite insistent that it was needed.
Code:
    PORTB.B3 = (Temp & 0b00000010);           //doesn't work
    PORTB.B3 = ((Temp & 0b00000010)!=0);      //does work

Mike.
 
I think we are all on the same page.

C18 does a nice job of handling bit fields in the SFR's by creating a sturct. It allows multiple views of the byte and allows for multi bit fields.

Code:
extern volatile near unsigned char       OSCCON;
extern volatile near union {
  struct {
    unsigned SCS:2;
    unsigned HFIOFS:1;
    unsigned OSTS:1;
    unsigned IRCF:3;
    unsigned IDLEN:1;
  };
  struct {
    unsigned SCS0:1;
    unsigned SCS1:1;
    unsigned IOFS:1;
    unsigned :1;
    unsigned IRCF0:1;
    unsigned IRCF1:1;
    unsigned IRCF2:1;
  };
} OSCCONbits;
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top