Search code examples
c++arduinobinaryinteger

32 bit binary to 24 bit signed conversion


I'm using a 24 bit I2C ADC with the Arduino and there is no 3 byte (24 bit) data type so I instead used the uint32_t which is a 32 bit unsigned int. My actual output however, is a 24 bit signed number as you can see below:

Also here is the code that I used to read the results if you're interested:

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

In order for this number to be useful, I need to convert it back to a 24 bit signed integer (I'm not sure how to do that or eve if it's possible because 24 is not a power of 2) so I'm a bit stuck. It would be great if somebody can help me as I'm almost finished with the project and this is one of the last few steps.


Solution

  • Conversion from 24-bit two’s complement in a uint32_t to int32_t can be done with:

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

    The x & 0xffffff ensures the number has no spurious bits above bit 23. If it is certain no such bits are set, then that line can be just int32_t t = x;.

    Then t >> 23 removes bits 0 to 22, leave just bit 23, which is the sign bit for a 24-bit integer. Then << 24 scales this, producing either 0 (for positive numbers) or 224 (for negative numbers). Subtracting that from t produces the desired value.