CCS-MSPM0G3507-7-模块篇-MPU6050的基本使用

前言

本篇我们接收对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);
    }
相关推荐
胡耀超25 分钟前
Umi-OCR 的 Docker安装(win制作镜像,Linux(Ubuntu Server 22.04)离线部署)
linux·深度学习·ubuntu·docker·容器·nlp·ocr
诗人不说梦^27 分钟前
[BUUCTF 2018]Online Tool
linux·运维·服务器
wa的一声哭了41 分钟前
python基础知识pip配置pip.conf文件
java·服务器·开发语言·python·pip·risc-v·os
别枫了44 分钟前
TCP的连接
服务器·网络·tcp/ip
晚风_END2 小时前
Linux|服务器|二进制部署nacos(不是集群,单实例)(2025了,不允许还有人不会部署nacos)
linux·运维·服务器·数据库·编辑器·个人开发
阿沁QWQ2 小时前
应用层协议和JSON的使用
运维·服务器·网络
运维开发王义杰2 小时前
不止于监控:深入剖析OpenTelemetry的可观察性生态体系
运维
LCG元2 小时前
基于MCP的CI/CD流水线:自动化部署到云平台的实践
运维·ci/cd·自动化
I'mSQL3 小时前
C#与FX5U进行Socket通信
运维·服务器·自动化·wpf
Gene_20223 小时前
[TOOL] ubuntu 使用 ffmpeg 操作 gif、mp4
linux·ubuntu·ffmpeg