STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息(附工程文件)

不同于移植官方DMP库,在别人标准库基础上移植会更加简单,只要按我的步骤一步一步来,基本不会错,本移植过程适用于F1和F4系列。
MPU6050在电赛和制作平衡小车中很常用,所以我记录下来,方便后来者使用,移植过程有什么问题欢迎在评论区留言,我会看的。

一、资料准备

本次实验代码基于Github上一个项目进行,该项目是基于标准库移植的MPU6050代码,所以我们的任务就是将标准库换到HAL库上,非常简单!!!!!!!!!!!
https://github.com/dyfcalid/STM32-car-MPU6050-Bluetooth-Ultrasonic

二、STM32Cube配置

2.1 基础配置

不再赘述,可以看我之前写的博客,这里着重将I2C的配置。

博客链接:基础工程搭建

2.2 IIC配置

在这里插入图片描述

2.3 HAL库IIC初始化BUG修改(重点,不修改初始化不了)

在这里插入图片描述

三、代码移植

3.1 添加文件到工程中并添加头文件路径

将github上的代码下载后,提取下列的这几个文件到自己的工程中。

在这里插入图片描述

文件保存在 Hardware->MPU6050中,这个看你们的习惯

在这里插入图片描述

打开工程,添加这些文件到项目中

在这里插入图片描述

3.2 开始调教代码

  1. 编译
    在这里插入图片描述

1.注释掉缺少的头文件
2.冲突的头文件在inv_mpu.h,注释掉stm32f10x.h
在这里插入图片描述

  1. 再编译
    在这里插入图片描述

利用宏定义解决,在inv_mpu.hmpu6050.h两个头文件中添加以下代码

#include "stm32f1xx_hal.h"
#define u8 uint8_t
#define u16 uint16_t
#define u32 uint32_t
  1. 再编译

在这里插入图片描述

没用的头文件没删干净,注释掉再编译

  1. 头文件删干净再编译

delay_ms非法声明
在这里插入图片描述

在这里插入图片描述

换成HAL_Delay
在这里插入图片描述

  1. 再编译
    在这里插入图片描述

因为我们不是用标准库,所以没有这些函数,将下面的代码复制替换掉mpu6050.c中的代码。

#include "mpu6050.h"
//#include "sys.h"
//#include "delay.h"
//#include "usart.h"   

#include "i2c.h"
//初始化MPU6050
//返回值:0,成功
//    其他,错误代码
u8 MPU_Init(void)
{ 
	u8 res; 
//	MPU_IIC_Init();//初始化IIC总线
	MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80);	//复位MPU6050
    HAL_Delay(100);
	MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00);	//唤醒MPU6050 
	MPU_Set_Gyro_Fsr(3);					//陀螺仪传感器,±2000dps
	MPU_Set_Accel_Fsr(0);					//加速度传感器,±2g
	MPU_Set_Rate(50);						//设置采样率50Hz
	MPU_Write_Byte(MPU_INT_EN_REG,0X00);	//关闭所有中断
	MPU_Write_Byte(MPU_USER_CTRL_REG,0X00);	//I2C主模式关闭
	MPU_Write_Byte(MPU_FIFO_EN_REG,0X00);	//关闭FIFO
	MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80);	//INT引脚低电平有效
	res=MPU_Read_Byte(MPU_DEVICE_ID_REG); 
	if(res==MPU_ADDR)//器件ID正确
	{
		MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);	//设置CLKSEL,PLL X轴为参考
		MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00);	//加速度与陀螺仪都工作
		MPU_Set_Rate(50);						//设置采样率为50Hz
 	}else return 1;
	return 0;
}
//设置MPU6050陀螺仪传感器满量程范围
//fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
//返回值:0,设置成功
//    其他,设置失败 
u8 MPU_Set_Gyro_Fsr(u8 fsr)
{
	return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);//设置陀螺仪满量程范围  
}
//设置MPU6050加速度传感器满量程范围
//fsr:0,±2g;1,±4g;2,±8g;3,±16g
//返回值:0,设置成功
//    其他,设置失败 
u8 MPU_Set_Accel_Fsr(u8 fsr)
{
	return MPU_Write_Byte(MPU_ACCEL_CFG_REG,fsr<<3);//设置加速度传感器满量程范围  
}
//设置MPU6050的数字低通滤波器
//lpf:数字低通滤波频率(Hz)
//返回值:0,设置成功
//    其他,设置失败 
u8 MPU_Set_LPF(u16 lpf)
{
	u8 data=0;
	if(lpf>=188)data=1;
	else if(lpf>=98)data=2;
	else if(lpf>=42)data=3;
	else if(lpf>=20)data=4;
	else if(lpf>=10)data=5;
	else data=6; 
	return MPU_Write_Byte(MPU_CFG_REG,data);//设置数字低通滤波器  
}
//设置MPU6050的采样率(假定Fs=1KHz)
//rate:4~1000(Hz)
//返回值:0,设置成功
//    其他,设置失败 
u8 MPU_Set_Rate(u16 rate)
{
	u8 data;
	if(rate>1000)rate=1000;
	if(rate<4)rate=4;
	data=1000/rate-1;
	data=MPU_Write_Byte(MPU_SAMPLE_RATE_REG,data);	//设置数字低通滤波器
 	return MPU_Set_LPF(rate/2);	//自动设置LPF为采样率的一半
}

//得到温度值
//返回值:温度值(扩大了100倍)
short MPU_Get_Temperature(void)
{
    u8 buf[2]; 
    short raw;
	float temp;
	MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf); 
    raw=((u16)buf[0]<<8)|buf[1];  
    temp=36.53+((double)raw)/340;  
    return temp*100;;
}
//得到陀螺仪值(原始值)
//gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
//返回值: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;;
}
//得到加速度值(原始值)
//gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
//返回值:0,成功
//    其他,错误代码
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;;
}
//IIC连续写
//addr:器件地址 
//reg:寄存器地址
//len:写入长度
//buf:数据区
//返回值:0,正常
//    其他,错误代码
uint8_t MPU_Write_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf)
{
    return HAL_I2C_Mem_Write(&hi2c1,MPU_WRITE,reg,I2C_MEMADD_SIZE_8BIT,buf,len,0xffff);
} 
//IIC连续读
//addr:器件地址
//reg:要读取的寄存器地址
//len:要读取的长度
//buf:读取到的数据存储区
//返回值:0,正常
//    其他,错误代码
uint8_t MPU_Read_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf)
{ 
    return HAL_I2C_Mem_Read(&hi2c1,MPU_READ,reg,I2C_MEMADD_SIZE_8BIT,buf,len,0xffff);
}
//IIC写一个字节 
//reg:寄存器地址
//data:数据
//返回值:0,正常
//    其他,错误代码
uint8_t MPU_Write_Byte(uint8_t reg,uint8_t data) 				 
{ 
    return HAL_I2C_Mem_Write(&hi2c1,MPU_WRITE,reg,I2C_MEMADD_SIZE_8BIT,&data,1,0xffff);
}
//IIC读一个字节 
//reg:寄存器地址 
//返回值:读到的数据
uint8_t MPU_Read_Byte(uint8_t reg)
{
    uint8_t data;
    HAL_I2C_Mem_Read(&hi2c1,MPU_READ,reg,I2C_MEMADD_SIZE_8BIT,&data,1,0xffff);   
    return data;    
}
  1. 再编译
    在这里插入图片描述

没定义MPU_READ和MPU_WRITE,这个只需要取消mpu6050.h中的注释就好了
在这里插入图片描述

  1. 再编译

在这里插入图片描述

注释掉inv_mpu.c中的这一行
在这里插入图片描述

不出意外的话,大功告成!!!!!
在这里插入图片描述

四、工程文件与演示

4.1 工程文件百度网盘链接

链接:https://pan.baidu.com/s/1LfGSR1HMAAw_gVhCtuUqgg?pwd=1111
提取码:1111

4.2 使用示例

在main中包含头文件

#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"
#include "mpu6050.h"

记得要调用MPU_Init和mpu_dmp_init,一个用来初始化MPU6050,一个初始化DMP

在这里插入图片描述
在这里插入图片描述

五、初始化不成功怎么办?(2024.4.8更新)

看到评论区有人留言说初始化不成功我就自己试了一下看代码是否正常,测试结果是正常的。
在这里插入图片描述

如果初始化不成功,可以从以下几方面考虑:

  1. 模块坏了,mpu6050很容易坏,的时候就碰到一个坏的,换了一个就好了。
  2. 部分MPU6050需要平放才能初始化成功,这个我目前还没有碰到过。
  3. 接线问题,我发的工程中SCL接PB6,SDA接PB7。
  4. 我的芯片型号为STM32F103ZET6,请确保你的芯片型号与我的一致。

如果还是不行,可以尝试debug看一下在初始化哪一部分出现了问题(必要时可以用逻辑分析仪)

  • 24
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值