Use of RRC (Rotate right through carry) in Keil

The 8051 family of microcontrollers has a very useful assembly instruction RRC. This instruction rotates carry into the MSB of the given register, shifts that register right by 1, and carry becomes equal to what used to be the LSB of the register.

  bit NewCarry;
  unsigned char Data;

  NewCarry = Data & 0x01;
  Data = (Data >> 1);
  if (Carry){
    Data = (Data | 0x80);
  }
  Carry = NewCarry;
Basically it does the above, but all in one instruction. I was wondering what the easiest way to include this in my code was. What I want to do is to read a microcontroller pin into carry, shift it into a data byte, and then use the bit that shifts off as an exit condition. Is there an easy way to include a single assembly instruction in Keil? Perhaps a Intrinsic function?

Thanks

-Tom

Parents
  • The Keil library has intrinsic functions for rotating integers, but they do not include the carry bit.

    What I want to do is to read a microcontroller pin into carry, shift it into a data byte, and then use the bit that shifts off as an exit condition.

    Why read into carry? If you're programming in C, there is no "carry bit" available (just as there is no rotate operator). Just read straight into your data byte. Something like:

    do
        {
        done = saved & 1;
        saved >>= 1;
        saved |= (portPin) ? 0x80 : 0;
        }
    while (!done);
    

    If this routine really needs to be tweaked for performance, you might want to locate the variables in the bit-addressable memory. If you don't like the notion of explicitly saving done, you could shift a U16 and test the MSB of the next byte.

    If you're really obsessed with the performance, then you can just write an assembler function to do the rotate (or use in-line assembly and risk the code breaking whenever the code generator changes). In that case you might as well accumulate the whole data byte in your subroutine.

    I'm not sure exactly what your application is, but the code above will accumulate 8 bits in one byte until the first 1 shifts off the LSB. So you could just skip storing the "start bit" and count down from 8 instead. The 8051 also has a nifty DJNZ instruction which you might like almost as well as a RRC + JNC loop

Reply
  • The Keil library has intrinsic functions for rotating integers, but they do not include the carry bit.

    What I want to do is to read a microcontroller pin into carry, shift it into a data byte, and then use the bit that shifts off as an exit condition.

    Why read into carry? If you're programming in C, there is no "carry bit" available (just as there is no rotate operator). Just read straight into your data byte. Something like:

    do
        {
        done = saved & 1;
        saved >>= 1;
        saved |= (portPin) ? 0x80 : 0;
        }
    while (!done);
    

    If this routine really needs to be tweaked for performance, you might want to locate the variables in the bit-addressable memory. If you don't like the notion of explicitly saving done, you could shift a U16 and test the MSB of the next byte.

    If you're really obsessed with the performance, then you can just write an assembler function to do the rotate (or use in-line assembly and risk the code breaking whenever the code generator changes). In that case you might as well accumulate the whole data byte in your subroutine.

    I'm not sure exactly what your application is, but the code above will accumulate 8 bits in one byte until the first 1 shifts off the LSB. So you could just skip storing the "start bit" and count down from 8 instead. The 8051 also has a nifty DJNZ instruction which you might like almost as well as a RRC + JNC loop

Children
More questions in this forum