代码之家  ›  专栏  ›  技术社区  ›  OM222O

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

  •  1
  • OM222O  · 技术社区  · 6 年前

    我将24位I2c ADC与Arduino一起使用,没有3字节(24位)的数据类型,因此我使用了 uint32_t 这是一个32位无符号整数。但是,我的实际输出是一个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 回复  |  直到 6 年前
        1
  •  -2
  •   gre_gor    6 年前

    使用 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;
    }
    
        2
  •  2
  •   Eric Postpischil    6 年前

    问题是,在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中的24位twos补码值,并将其转换为(有符号的)int32。

        3
  •  1
  •   Eric Postpischil    6 年前

    从24位二进制补码转换为 uint32_t 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 二十四 (对于负数)。从中减去 t 生成所需的值。