2026-02-15 5:22 AM
I am using NUCLEO-U083RC with X-NUCLEO-IKS4A1. I read the data from LIS2DUXS12 which is on X-NUCLEO-IKS4A1. The accelerometer data is in 8 registers. OUT_X_L, OUT_X_H, OUT_Y_L, OUT_Y_H, OUT_Z_L, OUT_Z_H.
I am trying to understand the instructions in the document AN5909 page 23. The example shows:
Get the raw data from the sensor:
OUT_X_L: 61h
OUT_X_H: FDh
OUT_Y_L: 73h
OUT_Y_H: 00h
OUT_Z_L: F0h
OUT_Z_H: 42h
Do the register concatenation (useful data on 14 bits, last 2 bits must be ignored):
(OUT_X_H << 8) + (OUT_X_L & 11111100b) = FD60h [-672 in two’s complement]
(OUT_Y_H << 8) + (OUT_Y_L & 11111100b) = 0070h [+112 in two’s complement]
(OUT_Z_H << 8) + (OUT_Z_L & 11111100b) = 42F0h [+17136 in two’s complement]
Apply the sensitivity and obtain the value in mg (0.061 mg/LSB at full scale ±2 g):
X: -672 * 0.061 = -41 mg
Y: +112 * 0.061 = +7 mg
Z: +17136 * 0.061 = +1045 mg
I have the following question: why is the two's compliment for FD60h calculated to be -672? Isn't it positive 672?
In my code I read the registers for Z axis:
uint16_t OUT_Z_L = 0x2C;
uint16_t OUT_Z_H = 0x2D;
uint8_t accz_l, accz_h;
status = BSP_I2C1_ReadReg(LIS2DUXS12_ADDR, OUT_Z_L, &accz_l, 1);
status = BSP_I2C1_ReadReg(LIS2DUXS12_ADDR, OUT_Z_H, &accz_h, 1);
Then I concatenate values:
uint16_t Z = (accz_h << 8) + (accz_l & 0b11111100);
And finally compute two's compliment and apply the sensitivity multiplier:
z = (~Z + 1) * 0.488;
I get a strange value:
My accz_l is B0h, accz_h is 07h. Therefore for Z I get 07B0h. The value for z is -960.383972
The NUCLEO board is in the positive position. Should I have approximately 1000 mg?
Solved! Go to Solution.
2026-02-19 5:27 AM
Hi @suiunbek ,
You should not use (~Z + 1) for two’s complement conversion.
After reading the registers, do:
uint16_t Z_raw = (accz_h << 8) | (accz_l & 0xFC);
int16_t Z_14bit = Z_raw >> 2;
if (Z_14bit & 0x2000) Z_14bit -= 0x4000; // handle sign for 14 bits
float z_mg = Z_14bit * 0.061f; // for ±2g
This will give you the correct signed value.
Your current method inverts the bits incorrectly and gives wrong results.
2026-02-19 5:27 AM
Hi @suiunbek ,
You should not use (~Z + 1) for two’s complement conversion.
After reading the registers, do:
uint16_t Z_raw = (accz_h << 8) | (accz_l & 0xFC);
int16_t Z_14bit = Z_raw >> 2;
if (Z_14bit & 0x2000) Z_14bit -= 0x4000; // handle sign for 14 bits
float z_mg = Z_14bit * 0.061f; // for ±2g
This will give you the correct signed value.
Your current method inverts the bits incorrectly and gives wrong results.