我正在从微控制器读取两个寄存器。一个具有4位MSB(前4位还有其他一些东西)和另一个8位LSB。我想将它转换为一个12位uint(准确地说是16位)。到目前为止,我做到了这样:
UINT16 x;
UINT8 RegValue = 0;
UINT8 RegValue1 = 0;
ReadRegister(Register01, &RegValue1);
ReadRegister(Register02, &RegValue2);
x = RegValue1 & 0x000F;
x = x << 8;
x = x | RegValue2 & 0x00FF;
还有更好的方法吗?
/ * 更准确一点ReadRegister是与另一个ADC的I2C通信。 Register01和Register02是不同的地址。 RegValue1是8位,但只需要4个LSB并连接到RegValue(RegValue1的4-LSB和RegValue的所有8位)。 * /
答案 0 :(得分:2)
如果您知道机器的字节序,则可以读取字节数
直接进入x
就像这样:
ReadRegister(Register01, (UINT8*)&x + 1);
ReadRegister(Register02, (UINT8*)&x);
x &= 0xfff;
请注意,这不是便携式的,性能提升(如果有的话)会 可能很小。
答案 1 :(得分:0)
RegValue & 0x00FF
掩码是不必要的,因为RegValue已经是8位。
将其分解为三个语句可能有利于清晰,但这个表达式可能很简单,可以在一个语句中实现:
x = ((RegValue1 & 0x0Fu) << 8u) | RegValue ;
使用无符号文字(0x0Fu)几乎没有区别,但强调我们正在处理无符号的8位数据。它实际上是一个unsigned int
,即使只有两位数,但这再次向读者强调我们只处理8位,而且纯粹是风格而不是语义。在C中,没有8位字面常量类型(尽管在C ++中'\x0f'
具有类型char
)。您可以按如下方式强制执行更好的类型协议:
#define LS4BITMASK ((UINT8)0x0fu)
x = ((RegValue1 & LS4BITMASK) << 8u) | RegValue ;
宏只是避免表达中的重复和混乱。
在性能或实际生成的代码方面,上述所有内容都不一定比原始代码“更好”,并且主要取决于偏好或本地编码标准或实践。
答案 2 :(得分:0)
如果寄存器彼此相邻,那么它们在目标字节序方面也可能是正确的顺序。在这种情况下,它们可以作为单个16位寄存器读取并相应地屏蔽,假设Register01
是较低的地址值:
ReadRegister16(Register01, &x ) ;
x &= 0x0fffu ;
当然我在这里发明了ReadRegister16()
函数,但如果寄存器是内存映射的,Register01
只是一个地址,那么这可能只是:
UINT16 x = *Register01 ;
x &= 0x0fffu ;