Converting two’s complement hex values to binary

accelerometerhexi2c

I'm reading x-axis accelerometer data from an IC via the I2C bus using I2C-Tools ( specifically i2cget ) in Linux. Here is the code that is reading these values:

$OUT_X_L_A = shell_exec( 'i2cget -y 1 0x19 0x28' ) ... eg. returns 0x20
$OUT_X_H_A = shell_exec( 'i2cget -y 1 0x19 0x29' ) ... eg. returns 0xfc

The documentation for this accelerometer states that these values ( 0x20 and 0xfc ) are expressed in 2's compliment. This accelerometer has 16 bit resolution.

From another application I'm running that is reading this data in C, I believe that these values, when converted to a decimal value, should equal ~65,475 ( essentially no acceleration as the device is sitting on my desk ). Some other documentation I've found suggests that $OUT_X_L_A is the Least Significant Register and $OUT_X_H_A is the Most Significant Register.

I've done some research, but am generally unfamiliar with Two's Complement and LSB and MSB. How do I calculate the full decimal value ( 16 bit resolution ) from the two hex values returned by the device? How am I supposed to tell from the documentation which register is the most significant?

Best Answer

The number 1234 (decimal) has 1 as it's "most significant" digit and 4 as its "least significant" digit. That's what the MS and LS stand for in numbers and applies to any base (I expect someone will point out that a certain base doesn't or maybe modulo arithmatic doesn't have such concepts!!)

Hexadecimal is the same and so is binary. I'm assuming that the full value in hex when the two bytes are interpreted as 1 byte is 20FC (or maybe FC20). I can't tell you which way but the data sheet should say.

Anyway, in decimal 20FC is (2 x 4096) + (0 x 256) + (F x 16) + C and for hex F=15 and C=12. Plug-in the decimal numbers and you get 8192+256+240+12 = 8700. If you were expecting a different number in decimal then maybe it's the other combination 61440+3072+32+0 = 64554.

As for the value 65475 you quote, I cannot see either of the numbers I've come up with as matching - 64554 is the closest but only you can tell me the reason for this. I've just done some simple maths in different bases and I may have made a number error somewhere but the important thing hopefully to you is that you can now convert hexadecimal to decimal. A=10, B=11, C=12, D=13, E=14 and F=15.

Converting from hex to binary is more straightforward if you remember the first 16 binary numbers 0000, 0001..... 1111 - these equate to decimal 0 to 15, so if you have the hex number FC20, its binary equivalent is 1111 1100 0010 0000. The left digit is the MSb i.e. most significant bit and the right digit is the LSb.

Hope this helps a bit and here's a link about two's compliment http://en.wikipedia.org/wiki/Two's_complement

Basically it's a number format for dealing with negative numbers in binary