32位二进制到24位有符号转换

时间:2018-12-25 04:01:47

标签: c++ arduino binary integer

我在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的幂),所以我有点卡住了。如果有人快要完成我的项目,这将是最后几步之一。

3 个答案:

答案 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;
}