STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息

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

文章目录

  • 一、资料准备
  • 二、STM32Cube配置
    • 2.1 基础配置
    • 2.2 IIC配置
    • 2.3 HAL库IIC初始化BUG修改(重点,不修改初始化不了)
  • 三、代码移植
    • 3.1 添加文件到工程中并添加头文件路径
    • 3.2 开始调教代码
  • 四、演示

一、资料准备

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

二、STM32Cube配置

2.1 基础配置

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

博客链接:基础工程搭建

2.2 IIC配置

STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第1张图片

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

STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第2张图片

三、代码移植

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

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

STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第3张图片

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

STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第4张图片

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

STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第5张图片

3.2 开始调教代码

  1. 编译
    STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第6张图片

1.注释掉缺少的头文件
2.冲突的头文件在inv_mpu.h,注释掉stm32f10x.h
STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第7张图片

  1. 再编译
    STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第8张图片

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

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

STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第9张图片

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

  1. 头文件删干净再编译

delay_ms非法声明
STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第10张图片

STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第11张图片

换成HAL_Delay
STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第12张图片

  1. 再编译
    STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第13张图片

因为我们不是用标准库,所以没有这些函数,将下面的代码复制替换掉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. 再编译
    STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第14张图片

没定义MPU_READ和MPU_WRITE,这个只需要取消mpu6050.h中的注释就好了
STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第15张图片

  1. 再编译

STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第16张图片

注释掉inv_mpu.c中的这一行
STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第17张图片

不出意外的话,大功告成!!!!!
STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第18张图片

四、演示

在main中包含头文件

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

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

STM32Cubemx:基于HAL库实现MPU6050 DMA获取姿态信息_第19张图片

你可能感兴趣的:(硬件模块,STM32Cubemx,STM32,stm32,驱动开发,嵌入式硬件)