我看过一些有类似背景的旧帖子,但答案是代码片段,而不是解释性的。而且我什至无法获得这些答案中提供的代码进行编译。
如果格式或解释不佳,我提前道歉,我是 C++ 新手,我不惜一切代价避免在论坛上提问,但这已成为我身边的真正刺。
我正在使用 C++ 访问加速度计的内存寄存器。该寄存器包含 twos complement 形式的 8 位数据。
加速度计的范围设置为 +/- 2 g,这意味着(参见第 10 页参考手册的第 1.5 节)
我的目标是获取此 twos complement 数据并将其作为已签名的 base-10 数据保存到文本文件中。
相关代码如下:
while(1)
{
int d = 0;
d= wiringPiI2CReadReg8(fd, DATA_X_H);
d = (int8_t)d;
d = d * EIGHTBITCONV;
std::cout << d << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
我已经通过将“d”硬编码为 01111111(127)来测试程序,并且程序返回“73”。但是将“d”硬编码为 10000001 (-127) 并且程序返回正确的“-127”。
所以程序只有在处理负数时才能正常运行。
发生这种情况是因为当将浮点“do”转换为 8 位整数时,它会截断正数的前导零?我将如何解决这个问题?
数据表链接:https://www.mouser.com/datasheet/2/348/KX132-1211-Technical-Reference-Manual-Rev-1.0-1652679.pdf
回答1
您不需要将 2 的补码转换为“有符号整数”,因为 2 的补码是有符号整数。
您只读取 8 位,但
int
(wiringPiI2CReadReg8
的返回类型)有更多。所以你需要一个符号扩展转换。比如:
int result = (int)(signed char)wiringPiI2CReadReg8(fd, DATA_X_H);
(int)
转换是隐式的,可以省略。在您的情况下,您正在转换为浮点数(转换再次是隐式的)。所以:
d = (signed char)wiringPiI2CReadReg8(fd, DATA_X_H);
实际上,您的解决方案(两次否定)也可以。更明确地说,它可以这样写(因为 1 是 int
):
d = -((int)(~(int8_t)d) + 1);
但这只是不必要的工作。可以简化为:
d = -(-(int8_t)d);
现在它显然简化为:
d = (int8_t)d;
和我之前写的一样。
回答2
好的,所以我认为我的很多困惑来自于我试图在我的程序中硬编码 values 而没有适当的知识。
如果我要进行硬编码作为测试逻辑的方法,我应该指定“d”的 values 是二进制的。
所以看起来我的原始代码虽然非常草率,但运行正常。