0

我正在从微控制器读取两个寄存器。一个有 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 位)。*/

4

3 回答 3

2

如果你知道你的机器的字节序,你可以x像这样直接读取字节:

ReadRegister(Register01, (UINT8*)&x + 1);
ReadRegister(Register02, (UINT8*)&x);
x &= 0xfff;

请注意,这不是可移植的,性能增益(如果有的话)可能很小。

于 2012-06-04T09:06:49.843 回答
0

由于RegValue & 0x00FFRegValue 已经是 8 位,因此不需要掩码。

将其分解为三个语句可能有助于清晰,但这个表达式可能很简单,可以在一个语句中实现:

x = ((RegValue1 & 0x0Fu) << 8u) | RegValue ;

使用无符号文字 (0x0Fu) 几乎没有区别,但强调我们正在处理无符号 8 位数据。它实际上是一个unsigned int只有两位数字的偶数,但这可能再次向读者强调我们只处理 8 位,并且纯粹是风格而不是语义。在 C 中没有 8 位文字常量类型(尽管在 C++'\x0f'中有 type char)。您可以强制执行更好的类型协议,如下所示:

#define LS4BITMASK ((UINT8)0x0fu)

x = ((RegValue1 & LS4BITMASK) << 8u) | RegValue ;

宏只是避免表达式中的重复和混乱。

就性能或实际生成的代码而言,以上任何一项都不一定比您的原始代码“更好”,并且很大程度上取决于偏好或本地编码标准或实践。

于 2012-06-04T10:04:16.483 回答
0

如果寄存器彼此相邻,则它们很可能在目标字节序方面也处于正确的顺序。在这种情况下,它们可以作为单个 16 位寄存器读取并相应地屏蔽,假设这Register01是较低的地址值:

ReadRegister16(Register01, &x ) ;
x &= 0x0fffu ;

当然我在这里发明了这个ReadRegister16()函数,但是如果寄存器是内存映射的,并且Register01只是一个地址,那么这可能只是:

UINT16 x = *Register01 ;
x &= 0x0fffu ;
于 2012-06-04T10:12:03.687 回答