一、前言
在嵌入式开发中,MPU6050 六轴传感器因其集成加速度计和陀螺仪且成本低廉,广泛应用于平衡小车、飞控、姿态检测等场景。
本项目将通过 STM32 使用 软件模拟 I2C(Soft I²C),实现对 MPU6050 的读写操作,并在 OLED 上实时显示传感器数据。
二、项目硬件说明
-
主控芯片:STM32F103C8T6
-
传感器:MPU6050(I2C接口)
-
显示器件:0.96寸 OLED(I2C)
-
通信方式:软件模拟 I2C
-
开发工具:Keil MDK + ST-Link 下载器
三、MPU6050 驱动关键实现
1. MPU6050 初始化
cpp
void MPU6050_init(void){
MyI2C_Init(); // 初始化软件 I2C
MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01); // 使用陀螺仪X轴时钟
MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09); // 采样分频
MPU6050_WriteReg(MPU6050_CONFIG, 0x06); // DLPF 设置为最平滑
MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18); // 陀螺仪 ±2000°/s
MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);// 加速度 ±16g
}
2. 寄存器读写函数
写寄存器:
cpp
void MPU6050_WriteReg(uint8_t reg, uint8_t data){
MyI2C_Start();
MyI2C_SendByte(0xD0); // 写地址
MyI2C_ReceiveAck();
MyI2C_SendByte(reg);
MyI2C_ReceiveAck();
MyI2C_SendByte(data);
MyI2C_ReceiveAck();
MyI2C_Stop();
}
读寄存器:
cpp
uint8_t MPU6050_ReadReg(uint8_t reg){
uint8_t data;
MyI2C_Start();
MyI2C_SendByte(0xD0); // 写
MyI2C_ReceiveAck();
MyI2C_SendByte(reg);
MyI2C_ReceiveAck();
MyI2C_Start();
MyI2C_SendByte(0xD1); // 读
MyI2C_ReceiveAck();
data = MyI2C_ReceiveByte();
MyI2C_SendAck(1); // NACK
MyI2C_Stop();
return data;
}
3. 获取加速度与陀螺仪数据
cpp
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ,
int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ){
*AccX = (MPU6050_ReadReg(ACCEL_XOUT_H) << 8) | MPU6050_ReadReg(ACCEL_XOUT_L);
*AccY = (MPU6050_ReadReg(ACCEL_YOUT_H) << 8) | MPU6050_ReadReg(ACCEL_YOUT_L);
*AccZ = (MPU6050_ReadReg(ACCEL_ZOUT_H) << 8) | MPU6050_ReadReg(ACCEL_ZOUT_L);
*GyroX = (MPU6050_ReadReg(GYRO_XOUT_H) << 8) | MPU6050_ReadReg(GYRO_XOUT_L);
*GyroY = (MPU6050_ReadReg(GYRO_YOUT_H) << 8) | MPU6050_ReadReg(GYRO_YOUT_L);
*GyroZ = (MPU6050_ReadReg(GYRO_ZOUT_H) << 8) | MPU6050_ReadReg(GYRO_ZOUT_L);
}
四、主函数 main.c
cpp
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "MPU6050.h"
uint8_t ID;
int16_t AX,AY,AZ,GX,GY,GZ;
int main(){
OLED_Init();
MPU6050_init();
OLED_ShowString(1,1,"ID:");
ID=MPU6050_GetID();
OLED_ShowHexNum(1,4,ID,2);
while(1){
MPU6050_GetData(&AX,&AY,&AZ,&GX,&GY,&GZ);
OLED_ShowSignedNum(2,1,AX,5);
OLED_ShowSignedNum(3,1,AY,5);
OLED_ShowSignedNum(4,1,AZ,5);
OLED_ShowSignedNum(2,8,GX,5);
OLED_ShowSignedNum(3,8,GY,5);
OLED_ShowSignedNum(4,8,GZ,5);
}
}
五、现象
-
OLED 显示 MPU6050 ID(通常为
0x68
) -
第 2~4 行分别显示:加速度 X/Y/Z 和 陀螺仪 X/Y/Z 的数值
-
当你晃动模块时,数据显示实时变化
附:MPU6050 常用寄存器地址宏定义 MPU6050_Reg.h
cpp
#ifndef __MPU6050_REG_H
#define __MPU6050_REG_H
#define MPU6050_SMPLRT_DIV 0x19
#define MPU6050_CONFIG 0x1A
#define MPU6050_GYRO_CONFIG 0x1B
#define MPU6050_ACCEL_CONFIG 0x1C
#define MPU6050_ACCEL_XOUT_H 0x3B
#define MPU6050_ACCEL_XOUT_L 0x3C
#define MPU6050_ACCEL_YOUT_H 0x3D
#define MPU6050_ACCEL_YOUT_L 0x3E
#define MPU6050_ACCEL_ZOUT_H 0x3F
#define MPU6050_ACCEL_ZOUT_L 0x40
#define MPU6050_TEMP_OUT_H 0x41
#define MPU6050_TEMP_OUT_L 0x42
#define MPU6050_GYRO_XOUT_H 0x43
#define MPU6050_GYRO_XOUT_L 0x44
#define MPU6050_GYRO_YOUT_H 0x45
#define MPU6050_GYRO_YOUT_L 0x46
#define MPU6050_GYRO_ZOUT_H 0x47
#define MPU6050_GYRO_ZOUT_L 0x48
#define MPU6050_PWR_MGMT_1 0x6B
#define MPU6050_PWR_MGMT_2 0x6C
#define MPU6050_WHO_AM_I 0x75
#endif
六、总结
本项目展示了如何使用 STM32 软件模拟 I2C 成功与 MPU6050 进行通信,并实时获取六轴数据,是一个非常实用且适合入门传感器开发的例子。