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