STM32用IIC读取ICM42688-P六轴数据和温度
STM32用IIC读取ICM42688-P六轴数据和温度
- 前言
- 效果图
- cubemx配置
- 代码
- github地址
- --End--
前言
以前都用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 /** * @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 * * © Copyright (c) 2025 STMicroelectronics. * All rights reserved.
* * 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