ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
21 ноября
92874 Топик полностью
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>