CW32L012读取MPU6050姿态数据

描述

引言

随着物联网、可穿戴设备、工业倾角检测等场景的普及,低成本、低功耗的姿态检测方案成为嵌入式领域的研究热点。MPU6050 作为集成三轴加速度计和三轴陀螺仪的六轴传感器,凭借低成本、小体积的优势被广泛应用,但单一传感器存在明显缺陷:加速度计易受运动加速度干扰(动态精度差),陀螺仪存在零漂累积误差(静态精度差)。

CW32L012 是武汉芯源半导体推出的 32 位 ARM Cortex-M0 + 内核 MCU,具备超低功耗(睡眠模式电流 μA 级)、高性价比、丰富的外设接口(I2C、UART 等)的特点,非常适合边缘端低资源、低功耗的传感融合场景。

本文基于 CW32L012 主控,实现 MPU6050 的传感器数据读取、基础姿态解算,并通过卡尔曼滤波完成加速度计与陀螺仪的数据融合,最终输出高精度、高鲁棒性的姿态角。

意义

基于 CW32L012 的 MPU6050 数据读取、姿态解算与卡尔曼数据融合方案,一方面针对性破解了 MPU6050 单一传感器加速度计易受运动加速度干扰、陀螺仪存在零漂累积误差的精度短板,依托卡尔曼滤波实现的多源数据融合,在 CW32L012 μA 级低功耗与 96MHz 主频兼顾运算效率的硬件支撑下,在边缘端低资源、低功耗的约束中实现了姿态检测静态与动态精度的同步提升,完美适配物联网、可穿戴设备、工业倾角检测等场景对 “低成本 + 低功耗 + 高精度” 姿态检测的需求;

另一方面该方案以国产 CW32L012 为核心载体,验证了国产 Cortex-M0 + 内核 MCU 在传感数据处理、轻量化算法运算场景下的性能潜力,打破了低功耗传感融合领域对进口 MCU 的依赖,同时这套覆盖传感器读取、解算、融合全流程的轻量化方案,也为嵌入式开发者提供了可直接移植的参考模板,降低了中小厂商的研发门槛,助力国产嵌入式芯片在感知层细分领域的产业化落地。

CW32L012C8T6介绍

CW32L012 是武汉芯源半导体 (CW) 推出的 32 位低功耗 MCU,基于 ARM Cortex-M0 + 内核,主频高达 96MHz,集成64KB Flash8KB RAM,专为需要高性价比和低功耗的应用设计。

一、核心规格:

mcu

二、关键特性

高性能计算单元

扩展算术运算单元 (EAU):硬件加速除法和开方运算,大幅提升数学计算效率

CORDIC 硬件单元:支持三角函数、矢量旋转等复杂运算

双 12 位 ADC:最高 1M SPS 转换速度,内置 1.2V 基准电压,支持单端 / 差分模式

双 12 位 DAC:高精度模拟输出,支持 DMA 传输

丰富外设资源

模拟外设:4 路电压比较器、双路轨到轨运算放大器

通信接口:3 路 UART (支持 LIN)、2 路 I2C (支持 SMBus)、3 路 SPI (最高 24Mbps)

定时器阵列:高级定时器 (6 路 PWM)、4 个通用定时器、低功耗定时器、霍尔传感器专用定时器等

40 路 GPIO:全部支持中断和唤醒功能,推挽 / 开漏输出

超低功耗设计

多种低功耗模式:Sleep、DeepSleep

灵活时钟管理:可独立关断各外设时钟,降低功耗

低功耗定时器:支持低功耗模式下的定时唤醒

可编程 LVD:低电压检测,防止异常断电

三、应用场景

电机控制领域

无刷直流电机 (BLDC) 控制 (如智能水泵)

家电电机控制 (风扇、空调)

工业自动化设备

测量与监测设备

充电器控制

电池管理系统 (BMS)

智能插座、电表

消费电子

智能家居控制器

便携式设备 (MP3 播放器)

智能玩具 (如 "哈基汪" 智能小车)

MPU6050介绍与开发

一、MPU6050介绍

1.1MPU6050简介

MPU6050是一款高性能的六轴运动传感器,集成了三轴加速度计和三轴陀螺仪。它能够测量加速度和角速度,广泛应用于姿态测量、运动检测、机器人控制等领域。MPU6050的主要特性如下:

三轴加速度计:测量范围为±2g/±4g/±8g/±16g(可选 单位g为重力加速度)。

三轴陀螺仪:测量范围为±250°/s/±500°/s/±1000°/s/±2000°/s(可选)。

数字运动处理器(DMP):支持复杂的运动处理算法,如姿态解算。

IIC接口:支持标准IIC通信协议,易于与微控制器连接。

低功耗:适合电池供电的便携式设备。

高精度:能够提供高精度的加速度和角速度数据。

mcu

1.2 MPU6050的引脚定义

MPU6050模块通常具有以下引脚:

VCC:电源正极(3.3V或5V)。

GND:电源地。

SDA:IIC数据线。

SCL:IIC时钟线。

INT:中断输出引脚(可选)。

AD0:地址选择引脚,用于设置IIC设备地址。

1.3MPU6050寄存器解析

MPU6050通过IIC接口与微控制器通信,数据存储在内部寄存器中。下面将介绍我们完成功能所主要用寄存器:

PWR_MGMT_1:电源管理寄存器,用于设置传感器的工作模式。

SMPLRT_DIV:采样率分频寄存器,用于设置数据采样率。

CONFIG:配置寄存器,用于设置数字低通滤波器(DLPF)。

GYRO_CONFIG:陀螺仪配置寄存器,用于设置测量范围。

ACCEL_CONFIG:加速度计配置寄存器,用于设置测量范围。

ACCEL_XOUT_H/L、ACCEL_YOUT_H/L、ACCEL_ZOUT_H/L:加速度数据寄存器。

GYRO_XOUT_H/L、GYRO_YOUT_H/L、GYRO_ZOUT_H/L:陀螺仪数据寄存器

二、MPU6050驱动开发

2.1 寄存器描述

配置寄存器用于设置MPU6050的工作模式、采样率、滤波器等参数。以下是几个常用配置寄存器的详细说明:

mcu

PWR_MGMT_1(0x6B):

位7:设备复位位,写入0x80复位设备。

位0-2:时钟源选择,通常设置为0x00,使用内部时钟。

GYRO_CONFIG(0x1B):

位3-0:陀螺仪量程选择,可选范围为±250°/s、±500°/s、±1000°/s、±2000°/s。

ACCEL_CONFIG(0x1C):

位3-0:加速度计量程选择,可选范围为±2g、±4g、±8g、±16g。

SMPLRT_DIV(0x19):

位7-0:采样率分频值,设置为0时,采样率最高

为了方便,先在MPU6050_Reg.h里面宏定义常用的寄存器:

 

#define        MPU6050_SMPLRT_DIV          0x19
#define        MPU6050_CONFIG              0x1A
#define        MPU6050_GYRO_CONFIG         0x1B
#define        MPU6050_ACCEL_CONFIG        0x1C
#define        MPU6050_ACCEL_XOUT_H        0x3B
#define        MPU6050_ACCEL_XOUT_L        0x3C
#define        MPU6050_ACCEL_YOUT_H        0x3D
#define        MPU6050_ACCEL_YOUT_L        0x3E
#define        MPU6050_ACCEL_ZOUT_H        0x3F
#define        MPU6050_ACCEL_ZOUT_L        0x40
#define        MPU6050_TEMP_OUT_H          0x41
#define        MPU6050_TEMP_OUT_L          0x42
#define        MPU6050_GYRO_XOUT_H         0x43
#define        MPU6050_GYRO_XOUT_L         0x44
#define        MPU6050_GYRO_YOUT_H         0x45
#define        MPU6050_GYRO_YOUT_L         0x46
#define        MPU6050_GYRO_ZOUT_H         0x47
#define        MPU6050_GYRO_ZOUT_L         0x48
#define        MPU6050_PWR_MGMT_1          0x6B
#define        MPU6050_PWR_MGMT_2          0x6C
#define        MPU6050_WHO_AM_I            0x75

 

2.2 对MPU6050寄存器进行读写

2.2.1 写入寄存器

通过IIC接口向MPU6050的寄存器写入数据,可以配置传感器的工作模式、量程、采样率等参数。以下是写入寄存器的代码实现:

 

/**
  * 函    数:MPU6050写寄存器
  * 参    数:RegAddress 寄存器地址,范围:参考MPU6050手册的寄存器描述
  * 参    数:Data 要写入寄存器的数据,范围:0x00~0xFF
  * 返 回 值:无
  */
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
        MyI2C_Start();                                                //I2C起始
        MyI2C_SendByte(MPU6050_ADDRESS);        //发送从机地址,读写位为0,表示即将写入
        MyI2C_ReceiveAck();                                        //接收应答
        MyI2C_SendByte(RegAddress);                        //发送寄存器地址
        MyI2C_ReceiveAck();                                        //接收应答
        MyI2C_SendByte(Data);                                //发送要写入寄存器的数据
        MyI2C_ReceiveAck();                                        //接收应答
        MyI2C_Stop();                                                //I2C终止
}

 

2.2.2读取寄存器

通过IIC接口从MPU6050的寄存器读取数据,可以获取传感器的配置状态或测量数据。以下是读取寄存器的代码实现:

 

/**
  * 函    数:MPU6050读寄存器
  * 参    数:RegAddress 寄存器地址,范围:参考MPU6050手册的寄存器描述
  * 返 回 值:读取寄存器的数据,范围:0x00~0xFF
  */
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
        uint8_t Data;

        MyI2C_Start();                                                //I2C起始
        MyI2C_SendByte(MPU6050_ADDRESS);        //发送从机地址,读写位为0,表示即将写入
        MyI2C_ReceiveAck();                                        //接收应答
        MyI2C_SendByte(RegAddress);                        //发送寄存器地址
        MyI2C_ReceiveAck();                                        //接收应答

        MyI2C_Start();                                                //I2C重复起始
        MyI2C_SendByte(MPU6050_ADDRESS | 0x01);        //发送从机地址,读写位为1,表示即将读取
        MyI2C_ReceiveAck();                                        //接收应答
        Data = MyI2C_ReceiveByte();                        //接收指定寄存器的数据
        MyI2C_SendAck(1);                                        //发送应答,给从机非应答,终止从机的数据输出
        MyI2C_Stop();                                                //I2C终止

        return Data;
}

 

2.3 初始化MPU6050

根据上述的读/写寄存器函数,对6050的寄存器进行初始化配置:

 

/**
  * 函    数:MPU6050初始化
  * 参    数:无
  * 返 回 值:无
  */
void MPU6050_Init(void)
{
        MyI2C_Init();                                                                        //先初始化底层的I2C

        /*MPU6050寄存器初始化,需要对照MPU6050手册的寄存器描述配置,此处仅配置了部分重要的寄存器*/
        MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);                //电源管理寄存器1,取消睡眠模式,选择时钟源为X轴陀螺仪
        MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);                //电源管理寄存器2,保持默认值0,所有轴均不待机
        MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);                //采样率分频寄存器,配置采样率
        MPU6050_WriteReg(MPU6050_CONFIG, 0x06);                        //配置寄存器,配置DLPF
        MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);        //陀螺仪配置寄存器,选择满量程为±2000°/s
        MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);        //加速度计配置寄存器,选择满量程为±16g
}

 

2.4MPU6050数据读取

根据上述的读/写寄存器函数,将6050的数据从对应的寄存器读出来:

 

/**
  * 函    数:MPU6050获取数据
  * 参    数:AccX AccY AccZ 加速度计X、Y、Z轴的数据,使用输出参数的形式返回,范围:-32768~32767
  * 参    数:GyroX GyroY GyroZ 陀螺仪X、Y、Z轴的数据,使用输出参数的形式返回,范围:-32768~32767
  * 返 回 值:无
  */
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;                                                                //定义数据高8位和低8位的变量

        DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);                //读取加速度计X轴的高8位数据
        DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);                //读取加速度计X轴的低8位数据
        *AccX = (DataH < < 8) | DataL;                                                //数据拼接,通过输出参数返回

        DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);                //读取加速度计Y轴的高8位数据
        DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);                //读取加速度计Y轴的低8位数据
        *AccY = (DataH < < 8) | DataL;                                                //数据拼接,通过输出参数返回

        DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);                //读取加速度计Z轴的高8位数据
        DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);                //读取加速度计Z轴的低8位数据
        *AccZ = (DataH < < 8) | DataL;                                                //数据拼接,通过输出参数返回

        DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);                //读取陀螺仪X轴的高8位数据
        DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);                //读取陀螺仪X轴的低8位数据
        *GyroX = (DataH < < 8) | DataL;                                                //数据拼接,通过输出参数返回

        DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);                //读取陀螺仪Y轴的高8位数据
        DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);                //读取陀螺仪Y轴的低8位数据
        *GyroY = (DataH < < 8) | DataL;                                                //数据拼接,通过输出参数返回

        DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);                //读取陀螺仪Z轴的高8位数据
        DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);                //读取陀螺仪Z轴的低8位数据
        *GyroZ = (DataH < < 8) | DataL;                                                //数据拼接,通过输出参数返回
}

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分