I have code to receive data from both the accelerometer and the gyroscope in X,Y Z axis. According to the datasheet, those are two's complement data. The data read by registers. Can you make sure that data are correct readings of accelerometer and gyroscope. I need to calculate yaw, roll, and pitch using all these data.

#include <ISM_330_DLC.h>
#include <main.h>
#include <stdio.h>
#include "math.h"
extern I2C_HandleTypeDef hi2c2;

#define ISM330DLC_I2C_ADDRESS 0x6B
#define FS_Gyro_250 0b00010000 //0b01000000 //0b00010000
#define FSAcc2G  0b01000000

#define CTRL2_G 0x11
#define CTRL1_XL 0x10

#define OUTX_L_G    0x22
#define OUTX_H_G    0x23
#define OUTY_L_G    0x24
#define OUTY_H_G    0x25
#define OUTZ_L_G    0x26
#define OUTZ_H_G    0x27

uint8_t Gy_x_L[1]={0};
uint8_t Gy_x_H[1]={0};

uint8_t Gy_y_L[1]={0};
uint8_t Gy_y_H[1]={0};

uint8_t Gy_z_L[1]={0};
uint8_t Gy_z_H[1]={0};

unsigned char Ax_x_L[1]={0};
unsigned char Ax_x_H[1]={0};

uint8_t Ax_y_L[1]={0};
uint8_t Ax_y_H[1]={0};

uint8_t Ax_z_L[1]={0};
uint8_t Ax_z_H[1]={0};

uint8_t high_bits_x_Ax;
uint8_t low_bits_x_Ax;
uint16_t conc_data_x_Ac;
uint16_t accel_x;

HAL_StatusTypeDef ret_dev = HAL_ERROR;
HAL_StatusTypeDef ret_conf_Gy = HAL_ERROR;
HAL_StatusTypeDef ret_conf_Ax = HAL_ERROR;

void ism330dlc_init() {
    ret_dev = HAL_I2C_IsDeviceReady(&hi2c2, ISM330DLC_I2C_ADDRESS<<1)+0, 1, 100);

    uint8_t CTRL2_G_Data = FS_Gyro_250;
    ret_conf_Gy = HAL_I2C_Mem_Write(&hi2c2, ISM330DLC_I2C_ADDRESS<<1)+0, CTRL2_G, 1, &CTRL2_G_Data, 1, 100);

    uint8_t CTRL1_XL_Data = FSAcc2G;
    ret_conf_Ax = HAL_I2C_Mem_Write(&hi2c2,(ISM330DLC_I2C_ADDRESS<<1)+0, CTRL1_XL, 1, &CTRL1_XL_Data, 1, 100);

void readGyro() {
    read_register(0x22, Gy_x_L);
    read_register(0x23, Gy_x_H);

    read_register(0x24, Gy_y_L);
    read_register(0x25, Gy_y_H);

    read_register(0x26, Gy_z_L);
    read_register(0x27, Gy_z_H);

void readAx(){
    read_register(0x28, Ax_x_L);
    read_register(0x29, Ax_x_H);

    read_register(0x2A, Ax_y_L);
    read_register(0x2B, Ax_y_H);

    read_register(0x2C, Ax_z_L);
    read_register(0x2D, Ax_z_H);

void CalcAcc() {
     high_bits_x_Ax = Ax_x_L[0];
     low_bits_x_Ax  = Ax_x_H[0];
     conc_data_x_Ac = ((high_bits_x_Ax << 8) | low_bits_x_Ax);
     accel_x = conc_data_x_Ac * 0.061 / 1000;
  • \$\begingroup\$ Please edit your question and fix the code formatting using the { } code formatting button. Select and apply. \$\endgroup\$
    – Transistor
    Nov 23, 2023 at 20:05

2 Answers 2


You can (and should) read multiple registers in one I²C transaction. This is not only more efficient, more readable and less code to write, it also ensures that the 12 bytes of gyro and accelerometer data are all from the same sample. If you declare the array as six int16_t values, you automatically get the data in the correct format (which means no ((high_bits_x_Ax << 8) | low_bits_x_Ax) shenanigans). Example:

// Read six int16_t values starting at register address 0x22
uint8_t reg_address = 0x22;
int16_t data[6];
HAL_I2C_Mem_Read(&hi2c2,ISM330DLC_I2C_ADDRESS<<1, &reg_address, 1, (uint8_t*)data, 12, 100);

For the ISM330 series you need to set some configuration registers to define the behaviour, most important are:

  • block data update
  • data rate
  • full scale
  • analog filters

After that, you can check via a status reg if new data is ready, or pull data chunks from the fifo.

For more detail refer to the ST Github page.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.