I see a few potential issues:
1. The ADC output itself: it's two's-complement formatted, centered around 1/2Vref. That means that "0V" output value is
half your full-scale voltage (1/2Vref). So if you are using Vin- = 0V,
Ref- = 0V and Ref+ = 2V, applying the formula Vref = Ref+ - Ref-, you get a Vref of 2V, so the "0V" output value actually happens when Vin+ = 1/2Vref = 1V, so input voltages below 1V are output as negative values, and values above 1V are output as positive values.
Do not confuse the ADC conversion sign with the sign of the two's-complement (the MSB)! Note that this ADC's output is 16 bits
plus the sign. In c data types, we normally describe the size of the datatype
inclusive of the sign bit, so a 32-bit unsigned int is 32 value bits and no sign bit, and a 32-bit signed int has
31 value bits and one sign bit (the MSB). So when shifting things around, bear in mind that in the parlance of c data types, the ADC is actually outputting a "17-bit signed int" plus a
separate conversion sign bit. Because one sign bit is two's-complement and the other is not, the combination of those two bits can be used to determine when the measurement range is exceeded.
2. Your data processing:
The above tells us that you have a 17-bit signed int which you need to convert to a 32-bit signed int. That means shifting the smaller number to the right, but padding the left with the MSB of the smaller number. (E.g. 4-bit
0101 -> 8-bit
0000 0101, but 4-bit
1101 -> 8-bit
1111 1101. See
https://en.wikipedia.org/wiki/Sign_extension )
In C, bitwise shifting has some undefined behaviors (i.e. the behavior may vary by platform, compiler, etc), in particular regarding negative numbers.
To make sure we're on the same page, this is how I understand the data format as you're pulling it in:
byte 0: [bit 23: ADC conversion sign] [bit 22: MSB (i.e. two's complement sign)] [bits 21...16]
byte 1: [bits 15...08]
byte 2: [bit 07] [bit 06: LSB] [bits 05...00: zero padding]
What we want to end up with inside your variable
temp is:
[bits 31...16: MSB repeated] [bits 15...01] [bit 0: LSB]
Right now, your MSB starts off as bit 6 of byte 0 and gets shifted 10 to the left, so at bit 16. But you need it to be at bit 31.
I'm sure a better programmer than me can provide a cleaner/more efficient way to do this, but I think this is what fundamentally needs to happen:
1. Create a uint32_t (I'll call it "
rawbits").
2. OR byte 2 with
rawbits.
3. Cast byte 1 to a uint32_t, shift it left by 8 bits, then OR it with
rawbits.
4. Cast byte 0 to a uint32_t, shift it left by 16 bits, then OR it with
rawbits.
5. Shift
rawbits to the left by 9 bits.
6. OR
rawbits with
temp.
7. Shift
temp to the right by 15 bits. This should fill to the left with the MSB.