概述
用STM32实现MPU6050原始数据的读取
- 用STM32实现MPU6050原始数据的读取
- 了解MPU6050
- 接线
- IIC协议
- 软件模拟IIC
- 通过IIC读取MPU6050寄存器
- 实现传感器功能
- 传感器初始化
- 一些问题以及解决
- DMP
- 零偏问题
- 初始化失败问题
用STM32实现MPU6050原始数据的读取
最近项目组在做自主导航的小车,需要读取底盘的姿态,所以准备往上面加mpu6050,于是整理了这样的文档供以后学习,程序是在正点原子的库上更改的。
了解MPU6050
MPU-60x0 是全球首例 9 轴运动处理传感器。它集成了 3 轴MEMS陀螺仪,3 轴MEMS加速度计,以及一个可扩展的数字运动处理器 DMP(Digital Motion Processor)。 MPU-60x0 对陀螺仪和加速度计分别用了三个 16 位的 ADC,将其测量的模拟量转化为可输出的数字量。为了精确跟踪快速和慢速的运动,传感器的测量范围都是用户可控的,陀螺仪可测范围为 ±250,±500,±1000,±2000°/秒(dps),加速度计可测范围为 ±2,±4,±8,±16g。
简单总结的话,mpu6050使用陀螺仪传感器测角度,使用加速度传感器测加速度。
同时,mpu6050有自带的I2C接口连接非惯性的数字传感器,比如压力传感器。其内部也集成了温度传感器,以及一个dmp数字运动处理器,可以解算mpu6050获取的原始数据,进行片内处理。
接线
我们测试时使用的是战舰V3开发板,其中
- VCC→3.3V
- GND→GND
- SCL→PB10
- SDA→ PB11
注:PB10,PB11,是模拟I2C协议的引脚,可以随软件设置而更改。
IIC协议
MPU6050是一个 I2C 器件,里面有很多寄存器(但是我们用到的只有几个),我们通过读写寄存器来操作这个芯片。所以首要问题就是STM32 和 MPU6050 的 I2C 通信。
软件模拟IIC
首先初始化IIC
void MPU_IIC_Init(void)
{
GPIO_InitTypeDef
GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11);
}
其次要用软件模拟吃IIC的起始信号、停止信号、应答信号。这三个信号是IIC通信所要用到的信号,具体底层的原理就不在本文中仔细讲解,软件模拟时主要时要模拟出IIC通信信号的时许与对应电平
void MPU_IIC_Start(void);//产生IIC起始信号
void MPU_IIC_Stop(void);//产生IIC停止型号
u8 MPU_IIC_Wait_Ack(void);//等待响应
void MPU_IIC_Ack(void);//产生IIC响应信号
void MPU_IIC_NAck(void);//不响应
void MPU_IIC_Send_Byte(u8 txd);//发送数据
u8 MPU_IIC_Read_Byte(unsigned char ack);//读取数据
IIC模块都有其地址,MPU6050的地址时通过模块上AD0引脚设置的,AD0接地或者悬空,芯片地址为0x68,接3.3V时,芯片地址为0x69。
通过IIC读取MPU6050寄存器
读寄存器
1.发送起始信号
2.发送设备地址(写模式)
3.发送内部寄存器地址
4.写入寄存器数据(8 位数据宽度)
5.发送结束信号
写寄存器
1.发送起始信号
2.发送设备地址(写模式)
3.发送内部寄存器地址
4.发送重复起始信号
5.发送设备地址(读模式)
6.读取寄存器数据(8 位数据宽度)
7.发送结束信号
内部传感器的地址可以通过手册查询。
实现传感器功能
传感器初始化
u8 MPU_Init(void)//采用带返回值的函数,是因为采用杜邦线连接,干扰比较大,容易初始化失败,所以根据返回值判断是否初始化成功
{
u8 res;
GPIO_InitTypeDef
GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
MPU_AD0_CTRL=0;//AD0为低电平,地址为0x68
MPU_IIC_Init();
MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80);
delay_ms(100);
MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00);
MPU_Set_Gyro_Fsr(3); //设置陀螺仪量程
MPU_Set_Accel_Fsr(0); //设置加速度计量程
MPU_Set_Rate(50);
MPU_Write_Byte(MPU_INT_EN_REG,0X00); //关中断
MPU_Write_Byte(MPU_USER_CTRL_REG,0X00); //IIC主模式关闭
MPU_Write_Byte(MPU_FIFO_EN_REG,0X00)/; //清空FIFO
MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80); //INT低有效
MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);
res=MPU_Read_Byte(MPU_DEVICE_ID_REG);//都工作加速度计与陀螺仪都工作
MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00);
MPU_Set_Rate(50);
MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);
MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00);
MPU_Set_Rate(50);
if(res==MPU_ADDR)//判断模块地址正确(0x68)
{
MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);
MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00); //再次使能加速度计与陀螺仪
MPU_Set_Rate(50);
}else return 1;
return 0;
传感器初始化之后就可以读取数据了。
u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{
MPU_IIC_Start();
MPU_IIC_Send_Byte((addr<<1)|0);//发送地址+写命令
if(MPU_IIC_Wait_Ack()) //等待应答
{
MPU_IIC_Stop();
return 1;
}
MPU_IIC_Send_Byte(reg); //写寄存器地址
MPU_IIC_Wait_Ack();
//等待应答
MPU_IIC_Start();
MPU_IIC_Send_Byte((addr<<1)|1);//发送器件地址+读命令
MPU_IIC_Wait_Ack();
//等待应答
while(len)
{
if(len==1)*buf=MPU_IIC_Read_Byte(0);//读数据
else *buf=MPU_IIC_Read_Byte(1);
//发送应答信号
len--;
buf++;
}
MPU_IIC_Stop(); //发送停止信号
return 0;
}
通过读不同的地址,可以获取到加速度计和陀螺仪的原始数据。
u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz)//读陀螺仪
{
u8 buf[6],res;
res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf);
if(res==0)
{
*gx=((u16)buf[0]<<8)|buf[1];
*gy=((u16)buf[2]<<8)|buf[3];
*gz=((u16)buf[4]<<8)|buf[5];
}
return res;;
}
u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)//读加速度计
{
u8 buf[6],res;
res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);
if(res==0)
{
*ax=((u16)buf[0]<<8)|buf[1];
*ay=((u16)buf[2]<<8)|buf[3];
*az=((u16)buf[4]<<8)|buf[5];
}
return res;;
}
到此我们就读出了MPU6050的加速度计和陀螺仪的原始数据,可以对他做解算了,这个留到下一篇文章讲。
一些问题以及解决
DMP
我们没有用MPU6050内置的dmp功能。它内置的dmp功能非常强大,但是由于少了一个z轴的观测,所以不是特别好用,在后面的文章中将介绍如何用四元数融合算法,结合hmc5883,来解算出欧拉角。
零偏问题
每块芯片都有一定的零点漂移,要在放平时对芯片进行校准。在放平时,gx,gy,gz都是0;ax,ay为0,az应该为32768/2=16384。
初始化失败问题
用杜邦线连接的MPU6050很容易初始化失败,所以要编写一个while函数来判断,如果没有初始化成功,就继续初始化。如果模块直接插入焊好的IIC接口中,情况会好很多。
最后
以上就是背后眼睛为你收集整理的用STM32实现MPU6050原始数据的读取用STM32实现MPU6050原始数据的读取的全部内容,希望文章能够帮你解决用STM32实现MPU6050原始数据的读取用STM32实现MPU6050原始数据的读取所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复