STM32用IIC读取ICM42688-P六轴数据和温度
本文介绍了使用STM32F103C8T6通过I2C通信读取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, ®, 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>© 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地址
–End–
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)