2

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

4

3 回答 3

2

问题是在 C 中没有安全且可移植的方式来使用移位进行符号扩展——充其量是实现定义的。因此,如果您想以可移植的方式进行操作,则需要手动将 2s-complement 值转换为有符号整数。

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。

于 2018-12-25T06:24:04.150 回答
2

从 a 到 24 位二进制补码的uint32_t转换int32_t可以通过以下方式完成:

int32_t Convert(uint32_t x)
{
    int32_t t = x & 0xffffff;
    return t - (t >> 23 << 24);
}

确保该数字在第x & 0xffffff23 位以上没有虚假位。如果确定没有设置此类位,则该语句可以是int32_t t = x;.

然后t >> 23删除位 0 到 22,只留下位 23,这是 24 位整数的符号位。然后<< 24对其进行缩放,产生 0(对于正数)或 2 24(对于负数)。减去它t会产生所需的值。

于 2018-12-25T17:05:38.013 回答
-2

使用int32_t而不是unit32_tfor 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;
}
于 2018-12-25T04:09:49.190 回答