This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Bit operations

I need to shift data into serail input register bit-by-bit. It would be nice, if the compiler would support asm blocks in a C program.
1. Shifting a byte is done by rotatig accumulator left, whereby the msb is loaded into carry flag. The docs that are provided with C51 evalution demo don't inclute any descriptions of the supported language operations.
Will the operation ACC <<= 1 move the msb into CY?

2. After the ACC is shifted and CY flag is loaded with the bit that I need to submit to the input of the shift register via P0.3, I try to make use of C51 bit addressing.
The sbit declaration example I've copied from C51 User's Guide and inserted into my program, doesn't work. Dear Sir, have you checked the snippet of code below?

	int bdata ibase; /* Bit-addressable int */
	sbit mybit0 = ibase ^ 0; /* bit 0 of ibase */
My idea was to make P0.3 sbit alias and assert the CY shifted from ACC to it. But the compiler complains about synthax error near sbit.


May be there is a better technique in C world for such a useful operation as bit-by-bit shifting a byte to external pin?

Parents
  • The 8051 architecture makes the carry flag available just as with any bit in an SFR, so the Keil compiler will let you access it in C. However, the C language standard doesn't make any reference to a carry flag, so you can't count on any particular operation affecting or using the flag. So, you can inspect the assembly code generated for a C operation like a shift, and write code to take advantage of that fact. But such code will be brittle, highly dependent on the code generator, and thus is perhaps not the best way.

    You could just write a loop in nearly pure C to output the byte, something like:

    for (i = 0; i < 8; ++i)
        {
        P3_0 = (byte & 0x80) ? 1 : 0;
        byte <<= 1;
        }
    
    

    Or, you could use bdata and sbit declarations to allow you to unroll the loop and/or get a bit more efficiency on the test.

    If you're going to declare items larger than a byte and assign bits to them, be sure to read the manual carefully so that you don't get surprised by the bit ordering in a multi-byte integer.

    The two lines of code you post compile for me, incidentally.

    It's also fairly simple to write an assembler routine to do the work which you then call from C. That's probably what I would do if efficiency or precise timing of the routine was the concern.

Reply
  • The 8051 architecture makes the carry flag available just as with any bit in an SFR, so the Keil compiler will let you access it in C. However, the C language standard doesn't make any reference to a carry flag, so you can't count on any particular operation affecting or using the flag. So, you can inspect the assembly code generated for a C operation like a shift, and write code to take advantage of that fact. But such code will be brittle, highly dependent on the code generator, and thus is perhaps not the best way.

    You could just write a loop in nearly pure C to output the byte, something like:

    for (i = 0; i < 8; ++i)
        {
        P3_0 = (byte & 0x80) ? 1 : 0;
        byte <<= 1;
        }
    
    

    Or, you could use bdata and sbit declarations to allow you to unroll the loop and/or get a bit more efficiency on the test.

    If you're going to declare items larger than a byte and assign bits to them, be sure to read the manual carefully so that you don't get surprised by the bit ordering in a multi-byte integer.

    The two lines of code you post compile for me, incidentally.

    It's also fairly simple to write an assembler routine to do the work which you then call from C. That's probably what I would do if efficiency or precise timing of the routine was the concern.

Children
No data