我正在尝试将1到32位长的值插入8字节(64位)的缓冲区中。
例如,我有12位值要插入7至18位。
我能想到的唯一方法是将12位值转换为64位值,对其进行移位,然后以这种方式设置缓冲区中的所有位,然后将64位值分成8个字节。 8字节帧中可能还有其他数据... 有更好的方法吗?
将在下面包含一些示例代码。
byte tx_msg[8] = {0};
uint32_t random_value = 77;
uint64_t buffer = 0;
// In this example, start point is bit 7, length is 12.
buffer = (uint64_t)random_value << (64 - 12 - 7);
for(int i = 0; i < 8; i++) {
tx_msg[7-i] = tx_msg[7-i] | buffer >> (i*8);
}
首先,您需要明确定义位的顺序。假设先按位排序LSB:
| Byte0 | Byte1 | ...
-----------------------
|01234567|01234567| ...
例如:
|00000001|10000000|
将是Byte0 == 0x80
和Byte1 == 0x08
(因为十六进制表示形式是MSB在先)。
然后,我建议一个更通用的界面:
void copyBits( uint8_t* dest, int offset, uint32_t bits, int length ) ;
length
中的bits
位(从LSB开始)将被复制到offset
中的dest
位。
一种简单的(但在性能方面不是最佳的方法是这样逐位复制:
#include <stdint.h>
#include <stdlib.h>
void copyBits( uint8_t* dest, int offset, uint32_t bits, int length )
{
for( int b = 0; b < length; b++ )
{
int source_bit = (bits & (0x01 << b)) == 0 ? 0 : 1 ;
div_t bit_dest = div( offset + b, 8 ) ;
if( source_bit == 0 )
{
dest[bit_dest.quot] &= ~(0x01 << bit_dest.rem) ;
}
else
{
dest[bit_dest.quot] |= (0x01 << bit_dest.rem) ;
}
}
}
这可以通过使用整个字节并在头部和尾部进行掩码来改善,但是它更加复杂,因此,除非性能至关重要或您要频繁复制很多位,否则我建议简单和通用就足够了。无论哪种方式,总的来说都是该功能的通用可重用性,而不是针对特定参数的硬编码。重要的是,它不仅限于64位目标缓冲区。它可以适应,因此不限于最大32位源字段。
示例用法:
uint8_t x[8] = {0};
insertBits( x, 7, 0x555, 12 ) ;
for( int i = 0; i < sizeof( x ); i++ )
{
printf( "%02X", x[i] ) ;
}
结果]
80AA020000000000
以LSB的第一位二进制形式的二进制是:
LSB --->
0000 0001 0101 0101 0100 0000 0000 ...
^-------------^
0x555 (12 bits) copied here