GY-521 MPU6050

六轴传感器模块 · STM32F103C8T6 · HAL库开发

工作电压
5V
通信方式
I2C
I2C地址
0xD0

1. 传感器原理与功能

MPU6050 六轴运动追踪传感器工作原理与核心功能

1.1 工作原理

MPU6050 是 InvenSense 公司推出的六轴运动追踪传感器,内部集成了三轴加速度计和三轴陀螺仪,并通过单一的 I2C 接口输出全部六轴数据。


加速度计原理:利用 MEMS(微机电系统)技术,内部为悬臂梁结构的质量块。当外部施加加速度时,质量块产生位移,导致差分电容值变化,通过检测电容变化量计算出三轴加速度。可测量重力加速度方向,用于姿态检测。


陀螺仪原理:利用科里奥利效应(Coriolis Effect),当旋转角速度作用于振动质量块时,会产生与角速度成正比的科里奥利力,导致横向位移,通过电容检测将该位移转换为角速度数据。


数据融合:加速度计在静态下精度高但动态响应差,陀螺仪在动态下精度高但存在漂移。两者互补,可实现对物体姿态的精准追踪。MPU6050 内部还含有 DMP(数字运动处理器),可进行硬件级数据融合。

1.2 核心功能

📊

加速度测量

三轴加速度计测量 X/Y/Z 方向的线性加速度,量程可选 ±2g/±4g/±8g/±16g,本程序设置为 ±16g。

🔄

角速度测量

三轴陀螺仪测量 X/Y/Z 轴的旋转角速度,量程可选 ±250/±500/±1000/±2000°/s,本程序设置为 ±2000°/s。

📐

姿态角计算

利用加速度计 Y 轴数据计算倾角,通过分段线性映射将 AY 原始值转换为 -90°~+90° 的角度值。

🚶

计步检测

基于陀螺仪数据变化量判断最活跃轴,检测数据跨越中值的现象实现计步,支持 50ms 采样 + 300ms 汇总。

1.3 引脚定义

引脚号名称功能STM32连接
1VCC电源正极(3.3V~5V)5V
2GND电源地GND
3SCLI2C 时钟线PB12
4SDAI2C 数据线PB13
5XCL辅助 I2C 时钟(接扩展传感器)未连接
6XDA辅助 I2C 数据(接扩展传感器)未连接
7AD0I2C 地址选择(接GND=0xD0)GND
8INT中断输出(数据就绪触发)未连接

OLED 显示屏引脚连接:SCL → PB15,SDA → PB14(软件模拟 I2C)

2. 模块外观展示

GY-521 MPU6050 六轴传感器模块实物外观

模块正面
模块正面 — MPU6050芯片及外围电路
模块背面
模块背面 — 焊盘及引脚排针
模块尺寸
模块尺寸图

3. 原理图与PCB封装

电路原理图设计与PCB封装

原理图
PCB封装

4. 程序分析

STM32F103C8T6 HAL库源代码详解

4.1 主程序 (main.c)

初始化流程

main.c — 主函数与主循环
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();

    OLED_Init();                                    // 显示屏初始化
    MPU6050_Init();                              // MPU6050初始化

    while (1)
    {
        if(HAL_GetTick() - Time_Now >= 200)                        // 200ms更新一次
        {
            angle = angleGetLoop();                              // 获取角度

            OLED_Clear();                                                              // 清屏

            OLED_Printf(0, 0, OLED_8X16, "AX:%d", AX);
            OLED_Printf(0, 16, OLED_8X16, "AY:%d", AY);
            OLED_Printf(0, 32, OLED_8X16, "AZ:%d", AZ);
            OLED_Printf(64, 0, OLED_8X16, "GX:%d", GX);
            OLED_Printf(64, 16, OLED_8X16, "GY:%d", GY);
            OLED_Printf(64, 32, OLED_8X16, "GZ:%d", GZ);

            OLED_CenterPrintf(48, "%d°", angle);

            OLED_Update();                                                          // 更新显示

            Time_Now = HAL_GetTick();                                    // 更新系统时间戳
        }
    }
}

4.2 MPU6050初始化 (MPU6050.c)

寄存器配置参数

寄存器地址写入值说明
PWR_MGMT_10x6B0x01唤醒传感器,选择X轴陀螺作为时钟源
PWR_MGMT_20x6C0x00禁用待机,使能所有轴
SMPLRT_DIV0x190x09采样率=1000/(1+9)=100Hz
CONFIG0x1A0x06低通滤波带宽5Hz
GYRO_CONFIG0x1B0x18陀螺仪量程 ±2000°/s
ACCEL_CONFIG0x1C0x18加速度计量程 ±16g
MPU6050.c — 初始化与I2C引脚配置
void MPU6050_I2C_Init(void)
{
    if(MPU6050_I2C_SCL_GPIO_PORT == GPIOB) __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;  // 开漏输出模式(I2C标准)
    GPIO_InitStructure.Pin = MPU6050_I2C_SCL_GPIO_PIN | MPU6050_I2C_SDA_GPIO_PIN;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(MPU6050_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);

    HAL_GPIO_WritePin(MPU6050_I2C_SCL_GPIO_PORT, MPU6050_I2C_SCL_GPIO_PIN, GPIO_PIN_SET);
    HAL_GPIO_WritePin(MPU6050_I2C_SDA_GPIO_PORT, MPU6050_I2C_SDA_GPIO_PIN, GPIO_PIN_SET);
}

void MPU6050_Init(void)
{
    MPU6050_I2C_Init();

    MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);    // 唤醒,X轴陀螺时钟
    MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);    // 禁用待机,使能所有轴
    MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);    // 采样率=100Hz
    MPU6050_WriteReg(MPU6050_CONFIG, 0x06);        // 低通滤波5Hz
    MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);   // 陀螺仪±2000°/s
    MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);  // 加速度计±16g
}

4.3 I2C读写寄存器 (MPU6050.c)

MPU6050 采用软件模拟 I2C 通信,通过 GPIO 开漏输出模式控制 SCL(PB12)和 SDA(PB13)引脚电平。

设备地址为 0xD0(AD0 接 GND),每次读写操作包含:起始信号 → 设备地址 → 寄存器地址 → 数据 → 停止信号。

MPU6050.c — 寄存器读写函数
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
    MPU6050_I2C_Start();
    MPU6050_I2C_SendByte(MPU6050_ADDRESS);   // 设备写地址 0xD0
    MPU6050_I2C_ReceiveAck();
    MPU6050_I2C_SendByte(RegAddress);      // 寄存器地址
    MPU6050_I2C_ReceiveAck();
    MPU6050_I2C_SendByte(Data);              // 写入数据
    MPU6050_I2C_ReceiveAck();
    MPU6050_I2C_Stop();
}

uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
    uint8_t Data;
    MPU6050_I2C_Start();
    MPU6050_I2C_SendByte(MPU6050_ADDRESS);
    MPU6050_I2C_ReceiveAck();
    MPU6050_I2C_SendByte(RegAddress);
    MPU6050_I2C_ReceiveAck();

    MPU6050_I2C_Start();                           // 重复起始信号
    MPU6050_I2C_SendByte(MPU6050_ADDRESS | 0x01); // 设备读地址
    MPU6050_I2C_ReceiveAck();
    Data = MPU6050_I2C_ReceiveByte();
    MPU6050_I2C_SendAck(1);                      // 非应答
    MPU6050_I2C_Stop();
    return Data;
}

4.4 六轴数据读取 (MPU6050.c)

通过 I2C 依次读取 6 个寄存器对(高8位+低8位),拼接为 16 位有符号整数,分别对应加速度计 X/Y/Z 和陀螺仪 X/Y/Z 数据。

MPU6050.c — 六轴数据读取
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ,
                     int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ)
{
    uint8_t DataH, DataL;

    // 加速度计X轴 (0x3B高 + 0x3C低)
    DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);
    DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
    *AccX = (DataH << 8) | DataL;

    // 加速度计Y/Z轴、陀螺仪X/Y/Z轴读取方式相同...
    // 寄存器地址:AY(0x3D/0x3E) AZ(0x3F/0x40)
    //             GX(0x43/0x44) GY(0x45/0x46) GZ(0x47/0x48)
}

4.5 角度计算 (angleGetLoop)

角度计算公式

利用加速度计 Y 轴数据(AY)计算传感器倾角。AY 原始值范围为 [-2080, 2000],通过分段线性映射转换为角度值。


公式1(AY ≥ -65,正倾角方向):

angle = -90 × (AY - (-65)) / (2000 - (-65)) + 2


公式2(AY < -65,负倾角方向):

angle = 90 × (AY - (-65)) / (-2080 - (-65)) + 2


当 AY = -65 时为分界点(angle ≈ 2°),当 AY = 2000 时 angle ≈ -88°,当 AY = -2080 时 angle ≈ -88°。

MPU6050.c — 角度计算函数
int angleGetLoop(void)
{
    int angle;
    MPU6050_GetData(&AX, &AY, &AZ, &GX, &GY, &GZ);

    if(AY > 2000) AY = 2000;          // 上限钳位
    if(AY < -2080) AY = -2080;       // 下限钳位

    if (AY >= -65)
        angle = (-90 * (AY - (-65))) / (2000 - (-65)) + 2;
    else
        angle = (90 * (AY - (-65))) / (-2080 - (-65)) + 2;

    return angle;
}

4.6 数据寄存器映射表

数据项高字节寄存器低字节寄存器分辨率
加速度计 X (AX)0x3B0x3C±16g → 4096 LSB/g
加速度计 Y (AY)0x3D0x3E±16g → 4096 LSB/g
加速度计 Z (AZ)0x3F0x40±16g → 4096 LSB/g
陀螺仪 X (GX)0x430x44±2000°/s → 16.4 LSB/°/s
陀螺仪 Y (GY)0x450x46±2000°/s → 16.4 LSB/°/s
陀螺仪 Z (GZ)0x470x48±2000°/s → 16.4 LSB/°/s

5. 程序流程图

主程序执行流程

开始 HAL_Init() 初始化HAL库 SystemClock_Config() 72MHz MX_GPIO_Init() GPIO初始化 OLED_Init() 显示屏初始化 MPU6050_Init() 传感器初始化 while(1) 主循环 HAL_GetTick() - Time_Now ≥ 200? 否 是 angleGetLoop() 读取六轴数据并计算角度 OLED_Clear() 清屏 OLED_Printf 显示 AX/AY/AZ/GX/GY/GZ OLED_CenterPrintf 显示角度 OLED_Update() 更新显示 Time_Now = HAL_GetTick() 更新时间戳

6. 交互式动画演示

MPU6050 六轴传感器数据模拟与OLED显示

传感器姿态模拟

MPU6050
X Y Z
0°
倾角(基于AY计算)

OLED 显示屏 + 数据仪表

AX:0 GX:0
AY:0 GY:0
AZ:0 GZ:0
0°
AX
0
AY
0
AZ
0
GX
0
GY
0
GZ
0

动画说明

左侧为 MPU6050 传感器模块的 3D 姿态模拟,模块会随时间自动摆动,模拟实际运动中的姿态变化。X/Y/Z 轴标识对应加速度计和陀螺仪的三个测量轴。倾角根据 AY(加速度计Y轴)数据实时计算,采用与程序中相同的分段线性映射公式。


右侧上半部分模拟 0.96 寸 OLED 显示屏,以 200ms 间隔刷新六轴数据和角度值,与实际硬件显示效果一致。下半部分为六轴数据仪表,实时显示 AX/AY/AZ(加速度计)和 GX/GY/GZ(陀螺仪)的数值变化,进度条颜色对应不同轴。