Gamma SPb (29.06.2007 15:53, просмотров: 1) ответил FDA на Я просто принимаю структуру через UART в виде байтов, запихиваю в этот union, а потом считываю информацию уже с полей!
все это лучше делать через явное приведение типа. Геморрой с union-ами страшный, начиная с лишних сущностей, заканчивая замусориванием исходника. то есть типа того:
<c>
typedef struct __MY_RECEIVER_CB
{
U08 feild_a;
U08 field_b;
struct
{
unsigned bit_a : 1;
unsigned : 6;
unsigned bit_b : 1;
} field_c;
} MY_RECEIVER_CB;
MY_RECEIVER_CB my_receiver;
void Receive (void * buff, U08 size)
{
while (size--)
{
*(U08*)buff++ = receive_byte(); /* байт тут приняли */
}
}
void Read_Received (MY_RECEIVER_CB *buff)
{
U08 field_a_r, field_b_r;
if (buff->field_c.bit_a)
{
field_a_r = buff->field_a;
field_b_r = buff->field_b;
}
}
</c>
Юнионы удобны, когда размер пакета фиксированный, а вариантов форматирования множество.
Но даже в этом случае ИМХО удобно использовать потоковое чтение, если по скорости не ограничен - вот кусок из MAD MP3 decoder:
<c>
/**
* Initialize bit pointer struct
*
* @param bitptr
* @param byte
*/
void mad_bit_init (MAD_BITPTR *bitptr, U08 *byte)
{
bitptr->byte = byte;
bitptr->cache = 0;
bitptr->left = CHAR_BIT;
}
/**
* Return number of bits between start and end points
*
* @param begin
* @param end
*
* @return U16
*/
U16 mad_bit_length (MAD_BITPTR *begin, MAD_BITPTR *end)
{
return begin->left + CHAR_BIT * (end->byte - (begin->byte + 1)) + (CHAR_BIT - end->left);
}
/**
* Return pointer to next unprocessed byte
*
* @param bitptr
*
* @return U08*
*/
U08 * mad_bit_nextbyte (MAD_BITPTR *bitptr)
{
return bitptr->left == CHAR_BIT ? bitptr->byte : bitptr->byte + 1;
}
/**
* Advance bit pointer
*
* @param bitptr
* @param len
*/
void mad_bit_skip (MAD_BITPTR *bitptr, U16 len)
{
bitptr->byte += len / CHAR_BIT;
bitptr->left -= len % CHAR_BIT;
if (bitptr->left > CHAR_BIT)
{
bitptr->byte++;
bitptr->left += CHAR_BIT;
}
if (bitptr->left < CHAR_BIT)
bitptr->cache = *bitptr->byte;
}
/**
* Read an arbitrary number of bits and return their UIMSBF value
*
* @param bitptr
* @param len
*
* @return U32
*/
U32 mad_bit_read (MAD_BITPTR *bitptr, U16 len)
{
register U32 value;
/* Если ни один бит в байте не прочитан (осталось восемь, bitptr->left = 8),
занесение в кэш указателя на байт */
if (bitptr->left == CHAR_BIT)
bitptr->cache = *bitptr->byte;
/* Если количество запрашиваемых битов меньше чем осталось в кэше - извлечение битов из
кэша и уменьшение счетчика оставшихся битов */
if (len < bitptr->left)
{
value = (bitptr->cache & ((1 << bitptr->left) - 1)) >> (bitptr->left - len);
bitptr->left -= len;
return (value);
}
/* Если количество запрашиваемых битов больше чем осталось в кэше, извлекаем, то что осталось.. */
value = bitptr->cache & ((1 << bitptr->left) - 1); /* Извлечение всех битов, оставшихся в кэше */
len -= bitptr->left; /* Уменьшение параметра на количество извлеченных битов */
bitptr->byte++; /* Инкремент указателя на байт */
bitptr->left = CHAR_BIT; /* Инициализация счетчика оставшихся в кэше битов */
/* Пока параметр больше чем количество битов в байте, извлекаем целыми байтами */
while (len >= CHAR_BIT)
{
value = bit_u32_sl8(value); /* *FAST* value = (value << CHAR_BIT); */
value |= *bitptr->byte++;
len -= CHAR_BIT;
}
/* Извлекаем дальше, но уже несколько бит */
if (len > 0)
{
bitptr->cache = *bitptr->byte; /* Следующий байт в кэш */
value = (value << len) | (bitptr->cache >> (CHAR_BIT - len)); /* Извлекаем */
bitptr->left -= len; /* Уменьшаем счетчик оставшихся */
}
return (value);
}
</c>