STM32驱动MPU9250九轴姿态加速度模块

简介

MPU9250是一个OFN封装的复合芯片(MGM),它由2部分组成。一组是3轴加速度还有3轴陀螺仪,另一组则是AKM公司的AK8963轴磁力计。所以,MPU9250是一款9轴运动跟踪装置,他在小小的3X3X1m的封装中融合了3轴加速度,3轴陀螺仪以及数字运动处理器(DMP)并且兼容MPU6515。其完美的12 C方案,可直接输出9轴的全部数据。一体化的设计,运动性的融合,时钟校准功能,让开发者避开了繁琐复杂的芯片选择和外设成本,保证最佳的性能。MPU9250的具有三个16位加速度AD输出,三个16位陀螺位AD输出,三个16位磁力计AD输出。

在这里插入图片描述

电气特征

供电电源:3-5v(内部低压差稳压)
陀螺仪范围(可编程):±250、±500、±1000、±2000°/s
加速度范围(可编程):±2、±4、±8、±16g
磁场范围:±4800uT
通信方式:标准I2C/SPI通信协议(芯片内置16bit AD转换器,16位数据输出)
引脚间距:2.54mm产品尺寸:15mm*25mm 采用沉金PCB,机器焊接工艺保证质量

原理图

在这里插入图片描述

主要寄存器

陀螺仪和加速度

WHO_AM_I

地址:75
用于验证MPU-9250的设备ID,出厂默认 0x71,初始化时可用于验证传感器。

ACCEL_OUT

地址:3B-40
X、Y、Z轴加速度数据输出。
在这里插入图片描述

GYRO_OUT

地址:43-48
X、Y、Z轴陀螺仪数据输出。
在这里插入图片描述

磁力计

MPU-9250中内部集成了一个AK8963,I2C地址0x0C

Measurement data

地址:03-08
X、Y、Z轴磁力计数据输出。
在这里插入图片描述

这里只列举了几个获取原始数据的寄存器,其他更多的寄存器的使用说明可以参考芯片寄存器手册。

IIC通讯

(1)START(S)和STOP§条件
当主设备将 START条件(S)置于总线时,2C总线上的通信开始,这被定义为 SDA线从 HIGH 到LOW 的转换,而SCL线为 HIGH(见下图)。在主设备将STOP条件§置于总线之前,总线被认为是忙碌的,这被定义为 Sda 线从 LOW 到 HIGH 的转换,而 SCl为 HIGH(见下图)。此外,如果重复产生START(Sr)而不是STOP状态,则总线仍保持忙碌状态。

在这里插入图片描述
(2)数据格式:
IIC数据字节被定义为8位长。每个数据传输传输的字节数没有限制。传输的每个字节必须跟随一个确认(ACK)信号。确认信号的时钟由主设备生成,而接收器通过拉低SDA在确认时钟脉冲的 HIGH 部分期间保持低电平来生成实际的确认信号。
如果一个从属服务器很忙,并且在完成其他任务之前无法发送或接收另一个字节的数据,那么它可以保持SCL LOW从而迫使主服务器进入等待状态。当从机准备好后,恢复正常的数据传输,并释放时钟线(参见下图)。

在这里插入图片描述
(3)通信
在与 START 条件(S)开始通信后,主设备发送一个7位的从设备地址,然后是第8位,即读写位。读写位指示主设备是从还是从设备接收数据。然后,主设备释放SDA线,等待从设备发送确认信号(ACK)。传输的每个字节后面都必须跟着一个确认位。为了确认,从设备将SDA线拉低,并在SCL线的高电平时保持低电平。数据传输总是由主设备以STOP条件"P"终止,从而释放通信线路。但是,主设备可以生成重复的 START条件(Sr),并在不首先生成STOP条件"P"的情况下寻址另一个从设备。当 SCL为 HIGH时,SDA线上从低到高的转换定义了停止条件。除了启动和停止条件外,所有SDA 变化都应在 SCL为低时发生。

在这里插入图片描述
为了写内部的MPU-6500寄存器,主控发送开始条件(S),然后发送I’c地址和写位(0)。在9时钟周期(当时钟高时),MPU-6500确认传输。然后主机将寄存器地址(RA)放到总线上。在MPU-6500接收到寄存器地址后,主控将寄存器数据放到总线上。然后是ACK信号,数据传输可以通过停止条件§结束。为了在最后一个ACK信号之后写入多个字节,主机可以继续输出数据,而不发送停止信号。在这种情况下,MPU-6500自动增加寄存器地址,并将数据加载到适当的寄存器。下图显示了单字节和双字节写入序列。
单字节写序列
在这里插入图片描述

双字节写序列
在这里插入图片描述
为了读取 MPU-6500 的内部寄存器,主机发送一个起始条件,然后是 L2C地址和写位,然后是将要读取的寄存器地址。在接收到来自 MPU-6500的 ACK信号后,主机发送一个起始信号,然后是slave 地址和读位。结果,MPU-65000发送ACK信号和数据。通信以主机的非确认(NACK)信号和停止位结束。NACK条件定义为在 g”时钟周期时 SDA 线保持高电平。 下图显示了单字节和双字节读取序列。
单字节读取序列
在这里插入图片描述

双字节读取序列

在这里插入图片描述

接线

STM32MPU9250OLED
3.3V3.3V3.3V
GNDGNDGND
PB10SCL-
PB11SDA-
PA6-SCL
PA7-SDA

驱动代码

#include "main.h"
/**
  * @brief  主函数
  * @param  无
  * @retval 无
  */
int main(void)
{
	SYS_Init();                                      //系统初始化总函数
	while(1)                                         //主循环
	{
		MPU_Read();                                  //MPU6050数据读取
		DATA_Report();                               //MPU6050数据上报
	}
}
/**
  * @brief  系统初始化总函数
  * @param  无
  * @retval 无
  */
void SYS_Init(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组函数
	delay_init();								     //延时函数初始化
	uart_init(115200);	 	                         //串口初始化为115200 
	LED_Init();                                      //初始化与LED连接的硬件接口
	OLED_Init();                                     //OLED初始化
	if(MPU_Init() == 0)			                     //初始化MPU9250
		printf("ID读取正常\r\n");                    //ID读取正常
	else
		printf("ID读取不正常\r\n");                  //ID读取不正常
	while(1)                                       
	{
		error = mpu_dmp_init();                      //初始化mpu_dmp库
		printf("ERROR:%d\r\n",error);                //串口显示初始化错误值
		switch (error)                               //对不同错误值类型判断
		{
			case 0:printf("DMP库初始化正常\r\n");break;
			case 1:printf("设置传感器失败\r\n");break;
			case 2:printf("设置FIFO失败\r\n");break;
			case 3:printf("设置采样率失败\r\n");break;
			case 4:printf("加载dmp固件失败\r\n");break;
			case 5:printf("设置陀螺仪方向失败\r\n");break;
			case 6:printf("设置dmp功能失败\r\n");break;
			case 7:printf("设置DMP输出速率失败\r\n");break;
			case 8:printf("自检失败\r\n");break;
			case 9:printf("使能DMP失败\r\n");break;
			case 10:printf("初始化MPU6050失败\r\n");break;
			default :printf("未知错误\r\n");break;
		}
		if(error == 0)break;                        //如果没有错误直接退出循环
		delay_ms(200);                              //延时
		LED0 =! LED0;                               //LED0闪烁报错
		sprintf((char *)tmp_buf,"     ERROR:%d",error);//字符串格式化命令
		OLED_ShowString(0,0,(u8 *)tmp_buf,16);	    //OLED显示错误值		
		OLED_Refresh();							    //刷新显存
	} 
	delay_ms(999); 
	OLED_ShowString(0,0,(u8*)"     MPU9250",16);		    //OLED显示字符串
	OLED_Refresh();								    //刷新显存
}	
/**
  * @brief  MPU6050数据读取函数
  * @param  无
  * @retval 无
  */
void MPU_Read(void)
{
	
	if(mpu_dmp_get_data(&yaw,&pitch,&roll)==0)      //dmp处理得到数据,对返回值进行判断
	{ 
		printf("Pitch:%f    Roll:%f    Yaw:%f\r\n",pitch,roll,yaw);//串口输出三轴角度
		mpu9250.speed++;                            //显示速度自加
		if(mpu9250.speed == 1)						//显示速度阈值设置
		{
			mpu9250.flag = 1;						//采集成功标志位设置为有效
			mpu9250.speed = 0;						//显示速度归零
		}	
	}
	else 											//采集不成功										
	{
		mpu9250.flag = 0;							//采集成功标志位设置为无效
	}	
}
/**
  * @brief  MPU6050数据上报
  * @param  无
  * @retval 无
  */
void DATA_Report(void)
{
	if(mpu9250.flag == 1)						    //采集成功时
	{ 
		temp=pitch*100;							    //赋temp为pitch
		if(temp<0)								    //对数据正负判断,判断为负时
		{
			temp=-temp;						        //对负数据取反	
			sprintf((char *)tmp_buf," Pitch:-%.3d.%.2d",temp/100,temp%100);//字符串格式化命令
		}
		else                                        //判断为正时 
		{
			sprintf((char *)tmp_buf," Pitch: %.3d.%.2d",temp/100,temp%100);//字符串格式化命令
		}
		OLED_ShowString(0,16,(u8 *)tmp_buf,16);     //OLED显示字符串
		
		temp=roll*100;							    //赋temp为pitch
		if(temp<0)								    //对数据正负判断,判断为负时
		{
			temp=-temp;						        //对负数据取反	
			sprintf((char *)tmp_buf," Roll :-%.3d.%.2d",temp/100,temp%100);//字符串格式化命令
		}
		else                                        //判断为正时 
		{
			sprintf((char *)tmp_buf," Roll : %.3d.%.2d",temp/100,temp%100);//字符串格式化命令
		}
		OLED_ShowString(0,48,(u8 *)tmp_buf,16);     //OLED显示字符串
		
		temp=yaw*100;							    //赋temp为pitch
		if(temp<0)								    //对数据正负判断,判断为负时
		{
			temp=-temp;						        //对负数据取反	
			sprintf((char *)tmp_buf," Yaw  :-%.3d.%.2d",temp/100,temp%100);//字符串格式化命令
		}
		else                                        //判断为正时 
		{
			sprintf((char *)tmp_buf," Yaw  : %.3d.%.2d",temp/100,temp%100);//字符串格式化命令
		}
		OLED_ShowString(0,32,(u8 *)tmp_buf,16);     //OLED显示字符串
		OLED_Refresh();								//刷新显存
		LED1=!LED1;								 	//LED闪烁
		mpu9250.flag = 0;							//采集成功标志位设置为无效
	}
	else ;											//防卡死
}

结果

串口输出角度值:

在这里插入图片描述

OLED显示角度值:
在这里插入图片描述
需要程序文件的可以在评论留下邮箱获取!!!

评论 226
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值