4

我有一个传感器,它以三个字节提供输出。我是这样读的:

unsigned char byte0,byte1,byte2;

byte0=readRegister(0x25);
byte1=readRegister(0x26);
byte2=readRegister(0x27);

现在我想将这三个字节合并为一个数字:

int value;
value=byte0 + (byte1 << 8) + (byte2 << 16);

它给了我从 0 到 16,777,215 的值,但我期望值从 -8,388,608 到 8,388,607。我虽然int已经签署了它的实施。即使我尝试定义它,signed int value;它仍然只给我正数。所以我想我的问题是如何将 int 转换为它的二进制补码?

谢谢!

4

2 回答 2

7

您需要执行的操作称为符号扩展。您有 24 个有效位,但需要 32 个有效位(请注意,您假设int为 32 位宽,这并不总是正确的;您最好使用int32_t中定义的类型stdint.h)。缺少 8 个最高位应该是正值全零或负数全一。它由 24 位值的最高有效位定义。

int32_t value;
uint8_t extension = byte2 & 0x80 ? 0xff:00; /* checks bit 7 */
value = (int32_t)byte0 | ((int32_t)byte1 << 8) | ((int32_t)byte2 << 16) | ((int32_t)extension << 24);

编辑:请注意,您不能将 8 位值移动 8 位或更多位,这是未定义的行为。您必须先将其转换为更广泛的类型。

于 2018-04-11T08:48:50.873 回答
2
#include <stdint.h>
uint8_t byte0,byte1,byte2;
int32_t answer;

// assuming reg 0x25 is the signed MSB of the number 
// but you need to read unsigned for some reason
byte0=readRegister(0x25);
byte1=readRegister(0x26);
byte2=readRegister(0x27);

// so the trick is you need to get the byte to sign extend to 32 bits
// so force it signed then cast it up
answer = (int32_t)((int8_t)byte0); // this should sign extend the number
answer <<= 8;
answer |= (int32_t)byte1; // this should just make 8 bit field, not extended
answer <<= 8;
answer |= (int32_t)byte2;

这也应该有效

answer = (((int32_t)((int8_t)byte0))<<16) + (((int32_t)byte1)<< 8) + byte2;

我可能对括号过于咄咄逼人,但我从不相信自己对班次运算符:)

于 2018-04-16T14:30:25.643 回答