Converting two's complement hex values to binary?

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?

• Surely there is much written about 2s complement out there. – Olin Lathrop Mar 24 '13 at 21:33
• It is hard to tell what you are asking about. Is this about the basics of twos complement representation, how binary values are expressed in HEX, how to read registers on this accellerometer, which registers mean what, or how to assemble the accelleration value given the contents of some registers? Pick one. As it is now, this question is overly broad and it is difficult to tell what is being asked here. – Olin Lathrop Mar 24 '13 at 21:36
• I think that the OP doesn't really understand hex either so maybe two's compliment will be lost on him too no matter what sites he looks into. – Andy aka Mar 24 '13 at 21:37
• I just lost a day, 'cause the documentation for my obsolete chip has MSB & LSB swapped. So it -might- not be so trivial as '\$OUT_X_L_A is the LSB'. One clue is, the MSB will not change a lot with small changes in accel, the LSB will change more. – Bobbi Bennett Mar 24 '13 at 21:46

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

The documentation should tell you. Otherwise, you kind of have to rely on experience. MSB and LSB stand for Most Significant Byte and Least Significant Byte. Incrementing the LSB one count increments the result by one count, while incrementing the MSB raises the result by 256. Then, we have the registers themselves. The 'H' and 'L' in their names stand for 'high' and 'low', corresponding to MSB and LSB. And, finally, your statement about the sensor sitting on your desk suggests that the reading should be near zero. It's a little negative, presumably due to the effect of gravity. This lets us confirm that the register that's reading "FC" is the MSB. How? You have to understand two's complement to know this.

To get the reading, you put the MSB 8 bits above the LSB--that means you shift it left 8 places, getting FC00 and then adding the LSB (20) to get FC20. Huh? Well, we left it in hexadecimal, but when we go do it in decimal, know that inside the machine it still looks like the hex calculation.

FC is 252 in decimal. 20 is 32. Then, 252*256 + 32 = 64544.

I can't explain all of two's complement, but if you subtract 1 from zero you get 65535. This is 0xFFFF. And to get the value of this number, you subtract 65536 from it. So 65535-65536= -1. And, 64544-65536 = -992.

Mostly, the computer handles all the two's complement (and MSB/LSB stuff) for you internally, but it's good to know about it so you know if your answer is believable.

I believe that _H_ stands for "high" byte, and _L_ stands for "low" byte. The full value of the data would be 0xfc20, or 64554 (or -992 if interpreted as a negative number)

"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"

Which teacher taught you 256x0 = 256?

The Correct Decimal No. of 0x20FC = 8444

0x20FC = 213+27+26+25+24+23+22 = 8192+240+12 = 8444