STM32用IIC读取ICM42688-P六轴数据和温度

前言

以前都用MPU6050,想尝试一下ICM42688,本文用STM32F103C8T6读取六轴数据和温度数据。
通信用IIC的方式。
配置用Cubemx。
代码让deepseek写的。

效果图

串口调试助手实时显示的图形
在这里插入图片描述

cubemx配置

1、IIC使用PB8,PB9;
2、串口用PA9,PA10;
3、LED用PC13;
4、其它IO控制,PB12-15;
在这里插入图片描述

ICM42688实际接线图:
1、AP_AD0接到PB15,这里采用低电平,让IIC地址为0x68;所以直接接地也行。
2、SDA,SCL是IIC线,要上拉电阻。
3、CS接PB14,这里要用高电平,即使用IIC;所以直接接VDD也行。
4、INT1和INT2暂时没用。
5、滤波电容也就是个参考。

另外就是芯片非常小,2*3mm面积有14个引脚,烙铁头要非常尖,焊接难于上青天。
在这里插入图片描述
在这里插入图片描述

代码

icm42688.h

#ifndef __ICM42688_H
#define __ICM42688_H

#include "stm32f1xx_hal.h"

// ICM-42688-P I2C地址 (AD0引脚低电平)
#define ICM42688_ADDRESS         0x68

// 寄存器地址 (Bank 0)
#define REG_BANK_SEL            0x76
#define WHO_AM_I                0x75
#define PWR_MGMT0               0x4E
#define GYRO_CONFIG0            0x4F
#define ACCEL_CONFIG0           0x50
#define DEVICE_CONFIG           0x11
#define INT_CONFIG              0x14
#define ACCEL_DATA_X1           0x1F
#define GYRO_DATA_X1            0x25
#define TEMP_DATA1              0x1D

// 错误代码
#define ICM42688_OK             0
#define ICM42688_ERR_INIT       1
#define ICM42688_ERR_COMM       2

// 函数声明
uint8_t ICM42688_Init(I2C_HandleTypeDef *hi2c);
uint8_t ICM42688_WhoAmI(I2C_HandleTypeDef *hi2c);
void ICM42688_Reset(I2C_HandleTypeDef *hi2c);
HAL_StatusTypeDef ICM42688_WriteReg(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t value);
HAL_StatusTypeDef ICM42688_ReadReg(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t *data, uint16_t len);
HAL_StatusTypeDef ICM42688_ReadAccel(I2C_HandleTypeDef *hi2c, int16_t accel[3]);
HAL_StatusTypeDef ICM42688_ReadGyro(I2C_HandleTypeDef *hi2c, int16_t gyro[3]);
float ICM42688_ReadTemperature(I2C_HandleTypeDef *hi2c);

#endif /* __ICM42688_H */

icm42688.c

#include "icm42688.h"
#include "main.h"
#include <math.h>

/**
  * @brief  ICM42688初始化
  * @param  hi2c: I2C句柄指针
  * @retval 初始化状态 (0:成功, 其他:错误代码)
  */
uint8_t ICM42688_Init(I2C_HandleTypeDef *hi2c)
{
    // 1. 重置设备
//    ICM42688_Reset(hi2c);
//    HAL_Delay(2); // 等待2ms确保重置完成

    // 2. 验证设备ID
    if(ICM42688_WhoAmI(hi2c) != 0x47)
    {
        return ICM42688_ERR_INIT; // 设备ID不匹配
    }

    // 3. 配置电源管理
    // 陀螺仪和加速度计都进入低噪声模式
    if(ICM42688_WriteReg(hi2c, PWR_MGMT0, 0x0F) != HAL_OK)
    {
        return ICM42688_ERR_COMM;
    }
    HAL_Delay(50); // 等待50ms

    // 4. 配置陀螺仪 ±2000dps, ODR=1kHz
    if(ICM42688_WriteReg(hi2c, GYRO_CONFIG0, 0x06) != HAL_OK)
    {
        return ICM42688_ERR_COMM;
    }

    // 5. 配置加速度计 ±16g, ODR=1kHz
    if(ICM42688_WriteReg(hi2c, ACCEL_CONFIG0, 0x06) != HAL_OK)
    {
        return ICM42688_ERR_COMM;
    }

    // 6. 配置中断 (推挽输出,高电平有效)
    if(ICM42688_WriteReg(hi2c, INT_CONFIG, 0x08) != HAL_OK)
    {
        return ICM42688_ERR_COMM;
    }

    return ICM42688_OK;
}

/**
  * @brief  读取设备ID
  * @param  hi2c: I2C句柄指针
  * @retval 设备ID (正常应为0x47)
  */
uint8_t ICM42688_WhoAmI(I2C_HandleTypeDef *hi2c)
{
    uint8_t whoami = 0;
    ICM42688_ReadReg(hi2c, WHO_AM_I, &whoami, 1);
    return whoami;
}

/**
  * @brief  重置设备
  * @param  hi2c: I2C句柄指针
  */
void ICM42688_Reset(I2C_HandleTypeDef *hi2c)
{
    ICM42688_WriteReg(hi2c, DEVICE_CONFIG, 0x01); // 软件重置
}

/**
  * @brief  写入寄存器
  * @param  hi2c: I2C句柄指针
  * @param  reg: 寄存器地址
  * @param  value: 要写入的值
  * @retval HAL状态
  */
HAL_StatusTypeDef ICM42688_WriteReg(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t value)
{
    uint8_t data[2] = {reg, value};
    return HAL_I2C_Master_Transmit(hi2c, ICM42688_ADDRESS << 1, data, 2, 100);
}

/**
  * @brief  读取寄存器
  * @param  hi2c: I2C句柄指针
  * @param  reg: 寄存器地址
  * @param  data: 存储数据的缓冲区
  * @param  len: 要读取的长度
  * @retval HAL状态
  */
HAL_StatusTypeDef ICM42688_ReadReg(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t *data, uint16_t len)
{
    // 先发送寄存器地址
    HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hi2c, ICM42688_ADDRESS << 1, &reg, 1, 100);
    if(status != HAL_OK)
    {
        return status;
    }

    // 然后读取数据
    return HAL_I2C_Master_Receive(hi2c, ICM42688_ADDRESS << 1, data, len, 100);
}

/**
  * @brief  读取加速度计数据 (原始值)
  * @param  hi2c: I2C句柄指针
  * @param  accel: 存储数据的数组(x,y,z)
  * @retval HAL状态
  */
HAL_StatusTypeDef ICM42688_ReadAccel(I2C_HandleTypeDef *hi2c, int16_t accel[3])
{
    uint8_t data[6];
    HAL_StatusTypeDef status;

    status = ICM42688_ReadReg(hi2c, ACCEL_DATA_X1, data, 6);
    if(status != HAL_OK)
    {
        return status;
    }

    accel[0] = (int16_t)((data[0] << 8) | data[1]); // X轴
    accel[1] = (int16_t)((data[2] << 8) | data[3]); // Y轴
    accel[2] = (int16_t)((data[4] << 8) | data[5]); // Z轴

    return HAL_OK;
}

/**
  * @brief  读取陀螺仪数据 (原始值)
  * @param  hi2c: I2C句柄指针
  * @param  gyro: 存储数据的数组(x,y,z)
  * @retval HAL状态
  */
HAL_StatusTypeDef ICM42688_ReadGyro(I2C_HandleTypeDef *hi2c, int16_t gyro[3])
{
    uint8_t data[6];
    HAL_StatusTypeDef status;

    status = ICM42688_ReadReg(hi2c, GYRO_DATA_X1, data, 6);
    if(status != HAL_OK)
    {
        return status;
    }

    gyro[0] = (int16_t)((data[0] << 8) | data[1]); // X轴
    gyro[1] = (int16_t)((data[2] << 8) | data[3]); // Y轴
    gyro[2] = (int16_t)((data[4] << 8) | data[5]); // Z轴

    return HAL_OK;
}

/**
  * @brief  读取温度数据 (摄氏度)
  * @param  hi2c: I2C句柄指针
  * @retval 温度值(℃)
  */
float ICM42688_ReadTemperature(I2C_HandleTypeDef *hi2c)
{
    uint8_t data[2];
    int16_t temp_raw;

    if(ICM42688_ReadReg(hi2c, TEMP_DATA1, data, 2) == HAL_OK)
    {
        temp_raw = (int16_t)((data[0] << 8) | data[1]);
        return (temp_raw / 132.48f) + 25.0f; // 根据数据手册公式转换
    }

    return -273.15f; // 读取失败返回绝对零度
}

main.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "icm42688.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
//这段代码用来让串口可以使用printf
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
PUTCHAR_PROTOTYPE
{
    HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);
    return ch;
}
#endif
/* USER CODE END 0 */
//这段代码用来获取全局US级时间戳
static uint32_t GetTimeStampUS()
{
    // get ms
    uint32_t m = HAL_GetTick();
    // get tick reload value
    const uint32_t tms = SysTick->LOAD + 1;
    // get tick value
    __IO uint32_t u = tms - SysTick->VAL;
    // return value
    return(m*1000+(u*1000)/tms);
}
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */


/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint64_t timestamp=0;
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  HAL_Delay(1);

    HAL_GPIO_WritePin(AD0_GPIO_Port,AD0_Pin,0);  // AD0==0 : IIC_add 0x68; AD0==1: IIC_add 0x69
    HAL_GPIO_WritePin(CS_GPIO_Port,CS_Pin,1);  // CS==1: IIC
    HAL_Delay(100);

//    // 扫描I2C总线上的设备
//    for(uint8_t addr = 0x08; addr < 0x78; addr++)
//    {
//        if(HAL_I2C_IsDeviceReady(&hi2c1, addr << 1, 3, 100) == HAL_OK) {
//            while(1)
//            {
//                if (GetTimeStampUS() > timestamp + 50000) {
//                    timestamp = GetTimeStampUS();
//                    HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
//                }
//            }
//        }
//    }

    // 初始化ICM42688
    uint8_t status = ICM42688_Init(&hi2c1);
    if(status != ICM42688_OK)
    {
        while(1)
        {
            if(GetTimeStampUS()>timestamp+50000)//失败狂闪灯
            {
                timestamp = GetTimeStampUS();
                HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
            }
        }
    }

    int16_t accel[3], gyro[3];

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      // 读取加速度计数据
      if(ICM42688_ReadAccel(&hi2c1, accel) == HAL_OK)
      {
          printf("AX=%6d, AY=%6d, AZ=%6d\r\n", accel[0], accel[1], accel[2]);
      }

      // 读取陀螺仪数据
      if(ICM42688_ReadGyro(&hi2c1, gyro) == HAL_OK)
      {
          printf("GX=%6d, GY=%6d, GZ=%6d\r\n", gyro[0], gyro[1], gyro[2]);
      }
      // 读取温度
      float temp = ICM42688_ReadTemperature(&hi2c1);
      printf("T=%.2f\r\n", temp);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    if(GetTimeStampUS()>timestamp+500000)//正常慢闪灯
    {
        timestamp = GetTimeStampUS();
        HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
    }

  }
  /* USER CODE END 3 */
}

github地址

ICM42688-P_FlyControl

–End–

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐