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

lnxxn5zx  于 2023-05-02  发布在  其他
关注(0)|答案(3)|浏览(146)

我在Arduino上使用24位I2C ADC,没有3字节(24位)数据类型,所以我使用了32位无符号整型的uint32_t。然而,我的实际输出是一个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的幂),所以我有点卡住了。这将是伟大的,如果有人可以帮助我,因为我几乎完成了该项目,这是最后几个步骤之一。

sczxawaw

sczxawaw1#

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(对于正数)或224(对于负数)。从t中减去该值即可得到所需的值。

sshcrbum

sshcrbum2#

问题是在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;
}

这将在uint32_t中获取24位二进制补码值,并将其转换为(有符号)int32_t。

a6b3iqyw

a6b3iqyw3#

使用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;
}

相关问题