我在Arduino上使用24位I2C ADC,没有3字节(24位)数据类型,所以我改用uint32_t
,它是32位无符号int。但是,我的实际输出是一个24位带符号的数字,如下所示:
如果您对此感兴趣,这也是我用来读取结果的代码:
uint32_t readData(){
Wire.beginTransmission(address);
Wire.write(0x10);
Wire.endTransmission();
Wire.requestFrom(address,3);
byte dataMSB = Wire.read();
byte data = Wire.read();
byte dataLSB = Wire.read();
uint32_t data32 = dataMSB;
data32 <<= 8;
data32 |= data;
data32 <<= 8;
data32 |= dataLSB;
return data32;
}
为了使该数字有用,我需要将其转换回24位带符号整数(我不确定该怎么做,或者是否有可能平安夜,因为24不是2的幂),所以我有点卡住了。如果有人快要完成我的项目,这将是最后几步之一。
答案 0 :(得分:2)
问题在于,在C语言中没有安全且可移植的方式使用移位进行符号扩展-最好是由实现定义。因此,如果您想轻便地执行此操作,则需要将2s补码值手动转换为有符号整数。
int32_t cvt24bit(uint32_t val) {
val &= 0xffffff; // limit to 24 bits -- may not be necessary
if (val >= (UINT32_C(1) << 23))
return (int32_t)val - (INT32_C(1) << 24);
else
return val;
}
这会将您的24位二进制补码值存储在uint32_t中,并将其转换为(带符号的)int32_t。
答案 1 :(得分:1)
从uint32_t
中的24位二进制补码到int32_t
的转换可以通过以下方式完成:
int32_t Convert(uint32_t x)
{
int32_t t = x & 0xffffff;
return t - (t >> 23 << 24);
}
x & 0xffffff
确保该数字在第23位上方没有虚假位。如果确定没有设置此类位,则该语句可以仅为int32_t t = x;
。
然后t >> 23
删除位0到22,仅保留位23,它是24位整数的符号位。然后<< 24
对此进行缩放,产生0(对于正数)或2 24 (对于负数)。从t
中减去该值即可得出所需的值。
答案 2 :(得分:-2)
对于int32_t
,使用unit32_t
代替data32
。然后,在返回值之前,将其向左移动8,然后向右移动8以进行符号扩展。
所以这段代码:
uint32_t readData(){
Wire.beginTransmission(address);
Wire.write(0x10);
Wire.endTransmission();
Wire.requestFrom(address,3);
byte dataMSB = Wire.read();
byte data = Wire.read();
byte dataLSB = Wire.read();
int32_t data32 = dataMSB;
data32 <<= 8;
data32 |= data;
data32 <<= 8;
data32 |= dataLSB;
return (data32 << 8) >> 8;
}