Skip to main content
Associate II
February 15, 2026
Solved

Reading data from LIS2DUXS12 on X-NUCLEO-IKS4A1

  • February 15, 2026
  • 1 reply
  • 185 views

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?

Best answer by Federica Bossi

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.

1 reply

Federica Bossi
Federica BossiBest answer
Technical Moderator
February 19, 2026

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.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.