前言
本篇我们接收对MPU6050的基本使用,获取ID,通过IIC协议获取寄存器的值,至于高级滤波算法,比如卡尔曼滤波,或者上面的,后面再更新
基本配置
最好选择PA0和PA1,5V开漏


然后给上代码
MPU6050.c
cpp
#include "MPU6050.h"
#include "delay.h"
// I2C通信相关的静态函数定义
// 设置 SCL 引脚电平,并添加延时
static void IIC_SCL_(uint8_t state)
{
if (state)
DL_GPIO_setPins(SOFT_IIC_SCL_PORT, SOFT_IIC_SCL_PIN);
else
DL_GPIO_clearPins(SOFT_IIC_SCL_PORT, SOFT_IIC_SCL_PIN);
delay_us(5);
}
// 设置 SDA 引脚电平,并添加延时
static void IIC_SDA_(uint8_t state)
{
DL_GPIO_initDigitalOutput(MPU6050_SDA_IOMUX);
if (state)
DL_GPIO_setPins(SOFT_IIC_SDA_PORT, SOFT_IIC_SDA_PIN);
else
DL_GPIO_clearPins(SOFT_IIC_SDA_PORT, SOFT_IIC_SDA_PIN);
delay_us(5);
}
// 读取 SDA 引脚电平
static uint8_t IIC_SDA_Read(void)
{
DL_GPIO_initDigitalInputFeatures(MPU6050_SDA_input,
DL_GPIO_INVERSION_DISABLE, DL_GPIO_RESISTOR_NONE,
DL_GPIO_HYSTERESIS_DISABLE, DL_GPIO_WAKEUP_DISABLE);
return DL_GPIO_readPins(SOFT_IIC_SDA_PORT, SOFT_IIC_SDA_PIN);
}
// I2C 初始化
static void IIC_Init(void)
{
// 初始状态:SCL 和 SDA 都为高电平
IIC_SCL_(1);
IIC_SDA_(1);
}
// 发送起始信号
static void IIC_Start(void)
{
IIC_SDA_(1);
IIC_SCL_(1);
IIC_SDA_(0);
IIC_SCL_(0);
}
// 发送停止信号
static void IIC_Stop(void)
{
IIC_SCL_(0);
IIC_SDA_(0);
IIC_SCL_(1);
IIC_SDA_(1);
}
// 发送一个字节
static void IIC_SendByte(uint8_t data)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
IIC_SDA_((data & 0x80) >> 7);
data <<= 1;
IIC_SCL_(1);
IIC_SCL_(0);
}
}
// 接收一个字节
static uint8_t IIC_ReceiveByte(uint8_t ack)
{
uint8_t i, data = 0;
IIC_SDA_(1); // 释放 SDA 线
for (i = 0; i < 8; i++)
{
IIC_SCL_(1);
data <<= 1;
if (IIC_SDA_Read())
data |= 0x01;
IIC_SCL_(0);
}
if (ack)
IIC_SDA_(0); // 发送应答
else
IIC_SDA_(1); // 发送非应答
IIC_SCL_(1);
IIC_SCL_(0);
return data;
}
// 等待应答信号
static uint8_t IIC_WaitAck(void)
{
uint8_t ack;
IIC_SDA_(1);
IIC_SCL_(1);
ack = IIC_SDA_Read();
IIC_SCL_(0);
return ack;
}
// 向 MPU6050 写入一个字节数据
static void IIC_Write_REG(uint8_t addr, uint8_t reg, uint8_t data)
{
IIC_Start();
IIC_SendByte((addr << 1) | 0); // 发送写地址
IIC_WaitAck();
IIC_SendByte(reg); // 发送寄存器地址
IIC_WaitAck();
IIC_SendByte(data); // 发送数据
IIC_WaitAck();
IIC_Stop();
}
// 从 MPU6050 读取一个字节数据
static uint8_t IIC_Read_REG(uint8_t Address, uint8_t regaddress)
{
uint8_t data;
IIC_Start(); // 发送起始信号
IIC_SendByte(Address << 1 | 0); // 发送设备地址和写操作
IIC_WaitAck(); // 等待 ACK
IIC_SendByte(regaddress); // 发送寄存器地址
IIC_WaitAck(); // 等待 ACK
IIC_Start(); // 发送起始信号
IIC_SendByte(Address << 1 | 1); // 发送设备地址和读操作
IIC_WaitAck(); // 等待 ACK
data = IIC_ReceiveByte(0); // 读取数据
IIC_Stop(); // 发送停止信号
return data; // 返回读取的数据
}
// MPU6050 初始化函数
uint8_t MPU6050_Init(void)
{
IIC_Init(); // 初始化 I2C 总线
// 唤醒 MPU6050
IIC_Write_REG(MPU6050_ADDR_AD0_LOW, PWR_MGMT_1, 0x00);
delay_ms(100); // 等待唤醒
// 设置采样率分频
IIC_Write_REG(MPU6050_ADDR_AD0_LOW, SMPLRT_DIV, 0x07);
// 设置低通滤波器
IIC_Write_REG(MPU6050_ADDR_AD0_LOW, CONFIG, 0x06);
// 设置陀螺仪量程 ±250°/s
IIC_Write_REG(MPU6050_ADDR_AD0_LOW, GYRO_CONFIG, 0x00);
// 设置加速度计量程 ±2g
IIC_Write_REG(MPU6050_ADDR_AD0_LOW, ACCEL_CONFIG, 0x00);
delay_ms(100); // 等待唤醒
return 0;
}
// 读取 MPU6050 的设备 ID
uint8_t MPU6050_GetDeviceID(void)
{
uint8_t data;
data = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, WHO_AM_I); // 读取设备 ID 寄存器
return data; // 返回设备 ID
}
float MPU6050_GET_Tempure(void)
{
int16_t temp; // 用于存储温度传感器数据
uint8_t H, L; // 用于存储高字节和低字节的数据
H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, TEMP_OUT_H); // 读取温度传感器高字节
L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, TEMP_OUT_L); // 读取温度传感器低字节
temp = (H << 8) | L; // 将高字节和低字节合并为一个 16 位数据
return (float)temp / 340.0 + 36.53 - 200; // 计算温度值并返回
}
float MPU6050_GetAccelX(void)
{
int16_t accel; // 用于存储加速度传感器数据
uint8_t H, L; // 用于存储高字节和低字节的数据
H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, ACCEL_XOUT_H); // 读取加速度传感器 X 轴高字节
L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, ACCEL_XOUT_L); // 读取加速度传感器 X 轴低字节
accel = (H << 8) | L; // 将高字节和低字节合并为一个 16 位数据
return ((float)accel / 16384.0 + 1) * 90 - 90; // 直接返回角度
}
float MPU6050_GetAccelY(void)
{
int16_t accel; // 用于存储加速度传感器数据
uint8_t H, L; // 用于存储高字节和低字节的数据
H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, ACCEL_YOUT_H); // 读取加速度传感器 Y 轴高字节
L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, ACCEL_YOUT_L); // 读取加速度传感器 Y 轴低字节
accel = (H << 8) | L; // 将高字节和低字节合并为一个 16 位数据
return ((float)accel / 16384.0 + 1) * 90 - 90; // 直接返回角度
}
float MPU6050_GetAccelZ(void)
{
int16_t accel; // 用于存储加速度传感器数据
uint8_t H, L; // 用于存储高字节和低字节的数据
H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, ACCEL_ZOUT_H); // 读取加速度传感器 Z 轴高字节
L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, ACCEL_ZOUT_L); // 读取加速度传感器 Z 轴低字节
accel = (H << 8) | L; // 将高字节和低字节合并为一个 16 位数据
return ((float)accel / 16384.0 + 1) * 90 - 90; // 直接返回角度
}
float MPU6050_GetAngleX(void)
{
int16_t gyro; // 用于存储陀螺仪数据
uint8_t H, L; // 用于存储高字节和低字节的数据
H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, GYRO_XOUT_H); // 读取陀螺仪 X 轴高字节
L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, GYRO_XOUT_L); // 读取陀螺仪 X 轴低字节
gyro = (H << 8) | L; // 将高字节和低字节合并为一个 16 位数据
return (float)gyro / 131.0; // 计算角速度值并返回
}
float MPU6050_GetAngleY(void)
{
int16_t gyro; // 用于存储陀螺仪数据
uint8_t H, L; // 用于存储高字节和低字节的数据
H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, GYRO_YOUT_H); // 读取陀螺仪 Y 轴高字节
L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, GYRO_YOUT_L); // 读取陀螺仪 Y 轴低字节
gyro = (H << 8) | L; // 将高字节和低字节合并为一个 16 位数据
return (float)gyro / 131.0; // 计算角速度值并返回
}
float MPU6050_GetAngleZ(void)
{
int16_t gyro; // 用于存储陀螺仪数据
uint8_t H, L; // 用于存储高字节和低字节的数据
H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, GYRO_ZOUT_H); // 读取陀螺仪 Z 轴高字节
L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, GYRO_ZOUT_L); // 读取陀螺仪 Z 轴低字节
gyro = (H << 8) | L; // 将高字节和低字节合并为一个 16 位数据
return (float)gyro / 131.0; // 计算角速度值并返回
}
MPU6050.h
cpp
#ifndef __MPU6050_H
#define __MPU6050_H
#include "ti_msp_dl_config.h"
// I2C引脚定义
#define SOFT_IIC_SCL_PORT GPIOA // SCL端口
#define SOFT_IIC_SCL_PIN DL_GPIO_PIN_1 // SCL引脚
#define SOFT_IIC_SDA_PORT GPIOA // SDA端口
#define SOFT_IIC_SDA_PIN DL_GPIO_PIN_0 // SDA引脚
#define MPU6050_SDA_input IOMUX_PINCM1 // SDA引脚IOMUX配置
// MPU6050寄存器地址定义
#define M_PI 3.14
#define SMPLRT_DIV 0x19 // 采样率分频,典型值:0x07(125Hz) */
#define CONFIG 0x1A // 低通滤波频率,典型值:0x06(5Hz) */
#define GYRO_CONFIG 0x1B // 陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s) */
#define ACCEL_CONFIG 0x1C // 加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz) */
#define ACCEL_XOUT_H 0x3B // 存储最近的X轴、Y轴、Z轴加速度感应器的测量值 */
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H 0x41 // 存储的最近温度传感器的测量值 */
#define TEMP_OUT_L 0x42
#define GYRO_XOUT_H 0x43 // 存储最近的X轴、Y轴、Z轴陀螺仪感应器的测量值 */
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48
#define PWR_MGMT_1 0x6B // 电源管理,典型值:0x00(正常启用) */
#define PWR_MGMT_2 0x6C // 电源管理,典型值:0x00(正常启用) */
#define WHO_AM_I 0x75 // IIC地址寄存器(默认数值0x68,只读) */
// HAL库的读写只需要使用7位地址
#define MPU6050_ADDR_AD0_LOW 0x68 // AD0低电平时7位地址为0X68 iic写时时发送0XD0
#define MPU6050_ADDR_AD0_HIGH 0x69
// 函数声明
uint8_t MPU6050_Init(void);
uint8_t MPU6050_GetDeviceID(void);
float MPU6050_GET_Tempure(void);
float MPU6050_GetAccelX(void);
float MPU6050_GetAccelY(void);
float MPU6050_GetAccelZ(void);
float MPU6050_GetAngleX(void);
float MPU6050_GetAngleY(void);
float MPU6050_GetAngleZ(void);
#endif /* __MPU6050_H */
主函数测试
cpp
uart_init();
uart_send_string("=== MPU6050 Test Program ===\r\n");
char buf[100];
MPU6050_Init();
uint8_t id = MPU6050_GetDeviceID();
sprintf(buf, "MPU6050 ID: %x\r\n", id);
uart_send_string(buf);
while (1)
{
//sprintf(buf, "Acc: %.2f, %.2f, %.2f,\r\n", MPU6050_GetAccelX(), MPU6050_GetAccelY(), MPU6050_GetAccelZ());
// uart_send_string(buf);
sprintf(buf, "Gyro: %.2f, %.2f, %.2f,\r\n",MPU6050_GetAngleX(), MPU6050_GetAngleY(), MPU6050_GetAngleZ());
uart_send_string(buf);
delay_ms(100);
}
