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);
    }
相关推荐
taxunjishu42 分钟前
ProfiNet 转 Ethernet/IP基于西门子 S7 - 1500 与罗克韦尔 PLC 的汽车零部件加工线协同案例
运维·人工智能·物联网·自动化·区块链
用户51681661458411 小时前
[VMware 无法检测此光盘中映像中的操作系统] VMware创建虚拟机无法检测操作系统iso镜像文件
linux·前端
MacroZheng1 小时前
斩获 7.8K star!一款堪称开源监控新标杆的项目,牛皮!
java·linux·后端
YC运维1 小时前
Ansible模块
java·服务器·前端
博语小屋1 小时前
程序(进程)地址空间(1)
linux
yunyi1 小时前
使用acme.sh来实现自动化申请和续订TLS证书
linux·nginx·docker
包达叔2 小时前
docker国内镜像源
运维·docker·容器
未来可期LJ2 小时前
【Linux 小实战】自定义 Shell 的编写
linux·服务器
wanhengidc3 小时前
云手机的未来发展怎么样?
运维·安全·游戏·智能手机
_君落羽_3 小时前
Linux操作系统——TCP服务端并发模型
linux·服务器·c++