基于 Keil5+STM32CubeMX 四轴无人机六轴原始数据读取代码详解
前言
- 本文目标:从零完成 MPU6050/ICM20608 六轴原始加速度、陀螺仪数据读取;
- 开发环境:STM32CubeMX、Keil MDK5、HAL 库、I2C 通信;
- 阅读说明:正文只贴核心功能代码,CubeMX 自动生成的底层初始化代码省略,完整工程仓库链接放文末。
1. 硬件准备(表格最简)
表格
| 器件 | 用途 |
|---|---|
| STM32F407VET6 主控 | 飞控核心 |
| ICM20608 六轴传感器 | 获取原始六轴数据 |
| USB-TTL | 串口打印调试数据 |
2. STM32CubeMX配置
- 打开stm32CubeMX,创建新项目:

2. 选择芯片STM32F407VET6:

3. 手动配置RCC,选择Crystal/Ceramic Resonator:

4. 手动配置I2C1,选择I2C:

5. 手动配置USART1,选择Asynchronous:

6. 进入右侧的System view界面,点击下方的GPIO,找到弹出窗口中的PB6,PB7手动设置为高电平Pull-up

7. 手动设置外部晶振Input frequency 为 8MHz,PLL Source Mux 调为HES,HCKLK调为168MHz,最后点击回车键完成自动配置

8. 进入Project Manager界面,找到Toolchain /IDE 手动设置为 MDK-ARM,然后输入项目名称,点击右上方的GENERATE CODE

9. 弹窗选择Open Project,随后系统会自动打开keil,生成对应配置的代码

3,keil相应配置
1. 点击左上方魔法棒

2. 选择ARM Compiler型号:version 6,勾选Use MicroLIB,点击OK,配置完成,打开main.c工程文件

4,源码分段解析
1. 传感器寄存器宏定义
#define ICM20608_ADDR 0x68 // ICM20608 7位I2C地址
#define ICM20608_PWR_MGMT_1 0x6B // 电源管理寄存器1(唤醒传感器)
#define ICM20608_WHO_AM_I 0x75 // 设备ID寄存器,用于校验硬件是否存在
#define DEV_ID_ICM20608 0x74 // ICM20608固定设备识别ID
#define ACCEL_XOUT_H 0x3B // X轴加速度高字节
#define ACCEL_YOUT_H 0x3D // Y轴加速度高字节
#define ACCEL_ZOUT_H 0x3F // Z轴加速度高字节
#define GYRO_XOUT_H 0x43 // X轴陀螺仪高字节
#define GYRO_YOUT_H 0x45 // Y轴陀螺仪高字节
#define GYRO_ZOUT_H 0x47 // Z轴陀螺仪高字节
解析要点:
- I2C 通信时设备地址需要左移 1 位,即 ICM20608_ADDR << 1原理:I2C 传输一字节中高 7 位为设备地址,最低 1 位读写标志位(0 写 / 1 读),HAL 库要求传入移位后的 8 位完整地址。
- 传感器硬件特性:读取高字节后会自动锁存对应低字节,必须一次性连续读取 2 字节,否则高低字节采样不同步,数据剧烈跳变;
- 0x6B 上电默认休眠,写入 0x00 即可唤醒传感器,同时切换内部 8M 晶振作为时钟;未唤醒时读取所有寄存器均为 0;
- 读取 WHO_AM_I 的数值与 0x74 对比,可判断传感器接线、地址是否正常;
- AD0 引脚逻辑:引脚接地 / 悬空地址 0x68,拉高 3.3V 地址切换为 0x69;
- 0x3B 起始连续 6 个寄存器,依次存放三轴加速度、三轴陀螺仪 16 位原始数据。
2. I2C 读写底层驱动
单字节寄存器读取(带重试抗干扰)
//单字节寄存器读取 ICM20608_ReadReg
uint8_t ICM20608_ReadReg(uint8_t reg)
{
uint8_t val = 0;
uint8_t retry = 3;
HAL_StatusTypeDef ret;
while(retry--)
{
ret = HAL_I2C_Mem_Read(&hi2c1, ICM20608_ADDR << 1, reg,
I2C_MEMADD_SIZE_8BIT, &val, 1, 1000);
if(ret == HAL_OK) break;
HAL_Delay(10);
}
return val;
}
功能说明:读取传感器单个 8 位寄存器;增加 3 次重试机制,解决 I2C 总线干扰、上电时序不稳问题,是飞控硬件基础抗干扰写法;读取成功直接退出循环,失败延时 10ms 重试。
读取 16 位高低字节合并数据
//16 位传感器数据读取 MPU_Read_Data
int16_t ICM_Read_Data(uint8_t reg)
{
uint8_t buf[2];
HAL_I2C_Mem_Read(&hi2c1, ICM20608_ADDR << 1, reg,
I2C_MEMADD_SIZE_8BIT, buf, 2, 1000);
return (int16_t)((buf[0] << 8) | buf[1]);
}
功能说明:一次性读取一组高低字节,拼接为 16 位有符号原始数据;buf [0] 高 8 位,buf [1] 低 8 位;高字节左移 8 位后与低字节按位或,组合完整数值;强制转换 int16_t 有符号短整型:加速度、陀螺仪存在正负方向,无符号 uint16_t 会造成负数数据溢出错乱。
单字节寄存器写入函数
//单字节寄存器写入 ICM20608_WriteReg
void ICM20608_WriteReg(uint8_t reg, uint8_t data)
{
HAL_I2C_Mem_Write(&hi2c1, ICM20608_ADDR << 1, reg,
I2C_MEMADD_SIZE_8BIT, (uint8_t*)&data, 1, 500);
}
HAL 库 I2C 寄存器写入接口,向指定寄存器写入 1 字节配置数据。
寄存器 0x6B 写入0x00除了唤醒,还会选择内部8M振荡器作为传感器时钟;如果不唤醒,所有寄存器读取全部返回0,识别不到设备。
注意:
HAL_I2C_Mem_Write(&hi2c1, ICM20608_ADDR << 1, reg,
I2C_MEMADD_SIZE_8BIT, (uint8_t*)&data, 1, 500)
-
函数参数逐位解释:
- &hi2c1:指定使用 I2C1 外设总线;
ICM20608_ADDR << 1:移位后的 8 位设备通信地址;reg:目标操作的传感器内部寄存器编号;I2C_MEMADD_SIZE_8BIT:传感器寄存器为 8 位地址;(uint8_t*)&data:数据缓存区,写入接口存放待发送数据;1:单次传输字节长度;500:通信超时时间,单位 ms,超时直接退出防止程序卡死。
3.main 主循环采集打印逻辑
int main(void)
{
// CubeMX自动生成初始化代码省略
MPU6050_Init();
uint8_t whoami = ICM20608_ReadReg(ICM20608_WHO_AM_I);
printf("WHO_AM_I = 0x%02X\r\n", whoami);
if(whoami == DEV_ID_ICM20608)
{
printf("ICM20608 Device Detect SUCCESS!\r\n");
}
else{
printf("Device Detect ERROR!\r\n");
}
while (1)
{
int16_t ax, ay, az;
int16_t gx, gy, gz;
ax = ICM_Read_Data(ACCEL_XOUT_H);
ay = ICM_Read_Data(ACCEL_YOUT_H);
az = ICM_Read_Data(ACCEL_ZOUT_H);
gx = ICM_Read_Data(GYRO_XOUT_H);
gy = ICM_Read_Data(GYRO_YOUT_H);
gz = ICM_Read_Data(GYRO_ZOUT_H);
printf("ACC: %d %d %d | GYRO: %d %d %d\r\n", ax, ay, az, gx, gy, gz);
HAL_Delay(200);
}
}
循环定时读取传感器数据,通过串口打印方便调试观察
5,结尾总结
文实现了 STM32F407 搭配 ICM20608 读取六轴原始数据完整流程,覆盖 CubeMX 引脚时钟配置、Keil 工程设置、I2C 驱动封装、传感器 ID 校验、实时数据打印全套内容,同时梳理了 AD0 地址切换、寄存器读写、数据拼接等高频踩坑点。
原始六轴数据是四轴飞控开发最基础的前置步骤,拿到原始数值后,后续可延伸数据滤波、欧拉角 / 四元数姿态解算、PID 姿态控制等核心飞控内容。我后续会更新姿态解算相关实操文章,感兴趣可以收藏持续关注。
调试过程遇到读不到传感器、数据乱跳、串口无输出等问题,都可以在评论区留言交流。
完整 CubeMX 工程、全部驱动源码已整理,仓库地址:https://gitee.com/iiddoo/flight-control-embedded-system,下载后打开.ioc 文件重新生成工程即可直接编译运行。
更多推荐

所有评论(0)