STM32CubeMX-H7-12-IIC读写MPU6050模块(中)-MPU6050模块详解以及软件IIC驱动

前言

上一篇我们已经完成对IIC代码基本框架的编写,以及获取MPU6050的ID,接下来我们逐一分析这个模块的功能,并用IIC驱动

建议看完上一篇再来看这篇

MPU6050寄存器介绍

1.电源管理寄存器(PWR_MGMT_1,地址:0x6B)

         

     我们要对0x6b这个地址给0以唤醒

    IIC_Write_REG(MPU6050_ADDR_AD0_LOW, PWR_MGMT_1, 0x00);  // 唤醒 MPU6050

    2.陀螺仪配置寄存器(GYRO_CONFIG,地址:0x1B)

    IIC_Write_REG(MPU6050_ADDR_AD0_LOW, GYRO_CONFIG, 0x18);  // 设置陀螺仪自检及测量范围

    选择满量程为±2000°/s

    3.加速度计配置寄存器(ACCEL_CONFIG,地址:0x1C)

        IIC_Write_REG(MPU6050_ADDR_AD0_LOW, ACCEL_CONFIG, 0x18);  // 设置加速度计自检、测量范围及高通滤波频率
    

    加速度计配置寄存器,选择满量程为±16g

    4.加速度计数据寄存器

           等会获取加速度的时候会用,主要获取加速度

    5.陀螺仪数据寄存器

    等会获取角度的时候会用,主要获取角度

    6.中断使能寄存器(INT_ENABLE,地址:0x38)

            看情况使用

    7.采样率分频寄存器(SMPLRT_DIV,地址:0x19)

    IIC_Write_REG(MPU6050_ADDR_AD0_LOW, SMPLRT_DIV, 0x09);  // 设置采样率分频

    8.CONFIG 寄存器主要用于配置 MPU6050 的外部帧同步(FSYNC)引脚输入以及数字低通滤波器(DLPF),以此来改善传感器数据的噪声性能和采样延迟。

    名称 描述 配置效果
    7 - 3 保留 这些位为保留位,用户不应进行设置,一般默认置为 0。 -
    2 EXT_SYNC_SET[2:0] 用于配置外部帧同步(FSYNC)引脚输入。
    - 000:无 FSYNC 输入
    - 001:FSYNC 引脚输入同步加速度计采样
    - 010:FSYNC 引脚输入同步陀螺仪 X 轴采样
    - 011:FSYNC 引脚输入同步陀螺仪 Y 轴采样
    - 100:FSYNC 引脚输入同步陀螺仪 Z 轴采样
    - 101:FSYNC 引脚输入同步温度传感器采样
    - 110:保留
    - 111:保留
    可利用外部信号对特定传感器的采样进行同步,从而保证多个传感器采样时间的一致性。
    1 - 0 DLPF_CFG[1:0] 用于配置数字低通滤波器(DLPF)的设置。
    - 000:带宽 260Hz,延迟 0.98ms,陀螺仪输出率 8kHz
    - 001:带宽 184Hz,延迟 2.9ms,陀螺仪输出率 1kHz
    - 010:带宽 94Hz,延迟 3.9ms,陀螺仪输出率 1kHz
    - 011:带宽 44Hz,延迟 5.9ms,陀螺仪输出率 1kHz
    - 100:带宽 21Hz,延迟 9.9ms,陀螺仪输出率 1kHz
    - 101:带宽 10Hz,延迟 17.85ms,陀螺仪输出率 1kHz
    - 110:带宽 5Hz,延迟 33.48ms,陀螺仪输出率 1kHz
    - 111:保留
    通过选择不同的滤波器配置,可以在噪声抑制和数据延迟之间进行权衡。较高的带宽会减少延迟,但可能会引入更多噪声;较低的带宽则能有效抑制噪声,但会增加数据延迟。

    MPU6050模块功能指令使用-函数封装

    1.指令寄存器的宏定义

    #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	

    2.初始化的基本配置

            根据上面的自己配置下寄存器就好

    // MPU6050 初始化函数
    uint8_t MPU6050_Init(void) {
        IIC_Init();  // 初始化 I2C 总线
        // 唤醒 MPU6050
        IIC_Write_REG(MPU6050_ADDR_AD0_LOW, PWR_MGMT_1, 0x00); 
        HAL_Delay(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); 
    
        HAL_Delay(100);  // 等待传感器稳定
        return 0;
    }

    3.获取模块ID

    // 读取 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	
    }

    上篇文章提到过,返回设备ID

    4.获取温度

    float MPU6050_GET_Tempure(void)
    {
        uint16_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;  // 计算温度值并返回
    }

    手册上是没有-200的,但是我的温度都显示两百多,减去200后看起来正常,大家根据具体情况把这个-200修改,补偿值修改到正常

    5.获取X轴加速度

    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;  // 计算加速度值并返回
    }

    6.获取Y轴加速度

    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;  // 计算加速度值并返回	
    }

    7.获取z轴加速度

    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;  // 计算加速度值并返回
    }

    8.获取x的角度

    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;  // 计算角速度值并返回	
    }

    9.获取y的角度

    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;  // 计算角速度值并返回
    }

    10.获取z轴角度

    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;  // 计算角速度值并返回
    }

    完整代码

    .c

    #include "MPU6050.h"
    #include "math.h"
    #include "SOFT_IIC.h"
    #include <stdio.h>
    // MPU6050 初始化函数
    uint8_t MPU6050_Init(void) {
        IIC_Init();  // 初始化 I2C 总线
        // 唤醒 MPU6050
        IIC_Write_REG(MPU6050_ADDR_AD0_LOW, PWR_MGMT_1, 0x00); 
        HAL_Delay(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); 
    
        HAL_Delay(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;  // 计算加速度值并返回
    }
    
    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;  // 计算加速度值并返回	
    }
    
    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;  // 计算加速度值并返回
    }
    
    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;  // 计算角速度值并返回
    }

    .h

    #ifndef __MPU6050_H
    #define __MPU6050_H
    
    #include "main.h"
    #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