I am using the SPI to access a couple of 20 & 24 bit A/D converters which have some digital status bits preceding the reading. I already have some C code written (for another CPU) that defines the incoming data structure as a unsigned long. The Keil compiler, however, says I must use char or integer size bit fields. Is there an easy way around this without having to hand code the byte manipulation code manually?
I'm not sure I properly understand this question. If I do, a union in which one member is an unsigned long, and the other is a struct containing unsigned chars and bit fields may solve your problem. I never use bit fields for this sort of thing, because the way bit fields map onto bytes is implementation-dependent, and may even change from one version of a compiler to the next, or with different compiler option settings. -- Gary Culp
Here is a simplified example.
typedef struct { unsigned long det_in :4, /*compliance & short detection bits */ Brd_rev :4, /* board / pal revision */ nu :4, /* not used as of 8/2000 */ AD_data :20; /* 0=-max, 0x80000=0v, fffff=+max */ } Bridge_brd_Rx_Type; /* for each bridge card */
{ long reading; char revision; reading = Brdg1.AD_data; revision = Brdg1.Brd_rev; ... }
ISO C says the bit fields must support up to size of int, not long. On 32-bit platforms they are usually one in the same. C51 implements int's as 16-bits so that's as big as your bit-fields can be. Sorry. - Mark
Here are some C51 declarations for a pair of cascaded (obsolete) MC14489 LED display drivers. In an external FPGA is an SPI interface that the CPU writes to in 8-bit (unsigned char) chunks, using the unions to get the bytes. This is implemetation dependent. // // LED Display // #define LED_DATA ((unsigned char volatile xdata *)0xe080) // LED data register (WR) #define LED_ENABLE_OFF ((unsigned char volatile xdata *)0xe081) // negate SPI ENABLE signal (any data) (WR) typedef struct { unsigned char leds_enable :1; unsigned char leds_not_hex_1 :1; unsigned char leds_not_hex_2 :1; unsigned char leds_not_hex_3 :1; unsigned char leds_not_hex_4 :1; unsigned char leds_not_hex_5 :1; unsigned char leds_special_123 :1; unsigned char leds_special_45 :1; unsigned char not_used_1 :8; unsigned char not_used_2 :8; unsigned char digs_enable :1; unsigned char digs_not_hex_1 :1; unsigned char digs_not_hex_2 :1; unsigned char digs_not_hex_3 :1; unsigned char digs_not_hex_4 :1; unsigned char digs_not_hex_5 :1; unsigned char digs_special_123 :1; unsigned char digs_special_45 :1; } led_ctrl_struct; typedef struct { unsigned char low_pwr :1; // first four bits are bank 5 nibble for leds unsigned char hi_pwr :1; unsigned char not_used_1 :2; unsigned char leds_dp_pos :3; // next four bits are decimal point/brightness control for leds unsigned char leds_bright :1; unsigned char ready :1; // next four bits are bank 3 nibble for leds unsigned char at_power :1; unsigned char not_used_2 :2; unsigned char spare_1 :1; // next four bits are bank 4 nibble for leds unsigned char spare_2 :1; unsigned char not_used_3 :2; unsigned char not_used_4 :4; // next four bits are bank 1 nibble for leds (not used) unsigned char remote_on :1; // next four bits are bank 2 nibble for leds unsigned char arc :1; unsigned char not_used_5 :2; unsigned char digit_4 :4; // next four bits are bank 5 for digits unsigned char digs_dp_pos :3; // next four bits are decimal point/brightness for digits unsigned char digs_bright :1; unsigned char digit_2 :4; // next four bits are bank 3 for digits unsigned char digit_3 :4; // next four bits are bank 4 for digits unsigned char not_used_6 :4; // next four bits are bank 1 for digits (not used) unsigned char digit_1 :4; // last four bits are bank 2 for digits } led_data_struct; typedef union { unsigned char ledc[4]; led_ctrl_struct ledcs; } led_ctrl_union; typedef union { unsigned char ledd[6]; led_data_struct ledds; } led_data_union;