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

Construct a byte from bits

Hello everybody,

I am very new to C language. In my project I get data serially from a port pin. I want to save the first 8 bits to one variable, another to second & so on. In all I want to save 32 bits in 4 bytes. Can you suggest C code.

I know it in assembly by using RRC or RLC, but how to achieve it in C?

Thanks

  • You can try a "bit" array:

    
    #ifndef BIT_ARRAY_H
    #define BIT_ARRAY_H
    
    #include <limits.h>
    
    #define CHAR_BIT 8
    
    #define BITMASK(b)      (1 << ((b) % CHAR_BIT))
    #define BITSLOT(b)      ((b) / CHAR_BIT)
    #define BITSET(a, b)    ((a)[BITSLOT(b)] |= BITMASK(b))
    #define BITCLEAR(a, b)  ((a)[BITSLOT(b)] &= ~BITMASK(b))
    #define BITTEST(a, b)   ((a)[BITSLOT(b)] & BITMASK(b))
    #define BITNSLOTS(nb)   ((nb + CHAR_BIT - 1) / CHAR_BIT)
    
    #endif
    

    usage:

    
    BITSET(g_nand_flash_defective_physical_blocks, l_logical_block ) ;
    
    if (BITTEST(g_nand_flash_defective_physical_blocks, l_logical_block ) )
    {
    }
    

  • Array definition:

    uint8_t   g_nand_flash_defective_physical_blocks[BITNSLOTS(NANDFLASH_BLOCKNUM)] ;
    

  • this structure is a 4 bytes where each bit can be accessed by name.

    
    
    typedef struct {
                    unsigned int ACK_ARM:1;      // bit 0.
                    unsigned int ACK_DSP:1;          // bit one.
    
                    unsigned int RESEND:1;
                    unsigned int INVALID_COMMAND:1;
    
                    unsigned int STRING:1;
                    unsigned int DIAGNOSTIC:1;
    
                    unsigned int ACK_CAL:1;
                    unsigned int READY:1;
    
                    unsigned int TEST_1:1;
                    unsigned int TEST_2:1;
    
                    unsigned int TEST_3:1;
                    unsigned int TEST_4:1;
    
                    unsigned int DATA_AVAILABLE:1;   // bit 12.
    
                    unsigned int SD_CARD_PRESENT:1;
                    unsigned int RESERVED_14:1;
                    unsigned int RESERVED_15:1;
    
                    unsigned int RESERVED_16:1;
                    unsigned int RESERVED_17:1;
                    unsigned int RESERVED_18:1;
                    unsigned int RESERVED_19:1;
    
                    unsigned int RESERVED_20:1;
                    unsigned int RESERVED_21:1;
                    unsigned int RESERVED_22:1;
                    unsigned int RESERVED_23:1;
    
                    unsigned int RESERVED_24:1;
                    unsigned int RESERVED_25:1;
                    unsigned int RESERVED_26:1;
                    unsigned int RESERVED_27:1;
    
                    unsigned int RESERVED_28:1;
                    unsigned int RESERVED_29:1;
                    unsigned int RESERVED_30:1;
                    unsigned int RESERVED_31:1;
    
        } status_bits_type;
    
    

  • and you access it as:

    status_bits.SD_CARD_PRESENT = 1;

  • Thanks. What I understand from these replies is:

    The routine suggested by christian crosa is to define a structure for storing 32 bits data, so that individual bits can be accessed. I got it, this will be very useful to me in future.

    The routine suggested by Tamir Michael is to manipulate bits (what I think). This code is not too much clear to me.

    My exact problem is that, the micro-controller is receiving 32 bits of data serially by two pins CLOCK & DATA. INT0 is connected to CLOCK whereas P3.3 is for DATA input. Now in the interrupt routine I want to shift the input data bits into an 8bit variable. Then next 8 bits in another variable & so on.

    So I need a way to rotate the variable bits left or right through DATA bit. I know there are operators such as << & >> to rotate bits, but they does rotate through carry or another bit.

  • This code is not too much clear to me.

    LOL. Well put. Comments are probably a foreign concept to him.

    Look at something like:

      Bit = CpuDataPin;
      ByteAccumulator = (ByteAccumulator<<1) | Bit;
    

  • It shouldn't be too complicated. Something is the lines of:

    BOOL data_full;
    BYTE bits_received;
    insigned int data_received;
    
    // initialise global variables;
    data_full = __FALSE;
    bits_received = 0;
    data_received = 0;
    
    
    interrupt_handler()
    {
    
    
       if(DATA)
            {
            data_received =| ( 1 << bits_received );
            }
       bits_received++;
    
       if(bits_received == 32)
          {
            bits_received = 0;
            data_full = __TRUE;
            // do something with data_received.
          }
    
    }
    

  • Do not mix rotate and shift. Two completely different things that can be done at the bit level.

    Note that if efficiency isn't important, you can defined an unsigned 32-bit integer and shift in bits one-by-one:

    #include <stdiint.h>
    
    uint32_t n = 0;
    
    ...
    
    n <= 1;
    if (bit) n |= 1;
    

    Or potentially (if you want reversed order of the bits):

    n >>= 1;
    if (bit) n |= 0x80000000ul;
    

  • Thanks, that is exactly what I needed. The BOOL, BYTE, __FALSE & __TRUE keywords gave errors in compiling. So I replaced them with bit, unsigned char, 0 & 1 respectively. Now it compiles without errors.

    Though I have not tested my project, I will let you know as soon as I test it.

  • And you manage to fit 32 bits in the following variable?

    unsigned int data_received;
    

  • Good lord, why use this indentation

    if(DATA)
            {
            data_received =| ( 1 << bits_received );
            }
    

    when you can do this

    if(DATA)
    {
        data_received =| ( 1 << bits_received ) ; // I always add a trailing space
    }
    

    The horror, the horror...

  • I always add a trailing space

    Ohh. Very Noël Coward.

  • Yes, I think it should be

    unsigned long data_received;
    

    Also the statement

    data_received =| ( 1 << bits_received );
    


    gave me error. So I replaced it with

    data_received |= ( 1 << bits_received );
    

    What does |= mean? Anyway the code works perfectly, thanks!

    Now in main routine, I want to split up the 32bit int into four 8bit variables. Then using lookup table I want to convert them. Your help will be highly appreciated.

  • Actually, I prefer Jackson Pollock.

  • yes, sorry my mistake was ment to be:

    data_received |= ( 1 << bits_received );
    

    it is the same than:

    data_received = data_received | ( 1 << bits_received );
    

    to split just do a byte *** operation

    BYTE bo, b1, b2, b3;
    b0 = (data_received & 0x000000FF)
    b1 = (data_received & 0x0000FF00) >> 8;
    b2 = (data_received & 0x00FF0000) >> 16;
    b3 = (data_received & 0xFF000000) >> 24;
    

    may need a BYTE cast