系列文章目录

一、看图解析

系统结构图:
在这里插入图片描述
MPU-60X0 是全球首例9 轴运动处理传感器。它集成了3 轴MEMS 陀螺仪,3
轴MEMS加速度计,以及一个可扩展的数字运动处理器DMP(Digital Motion
Processor),可用I2C接口连接一个第三方的数字传感器,比如磁力计。扩展之后就可以通过其I2C 或SPI 接口输出一个9轴的信号(SPI 接口仅在MPU-6000 可用)。MPU-60X0 也可以通过其I2C 接口连接非惯性的数字传感器,比如压力传感器。

SCL和 SDA是连接MCU的 IIC接口,MCU通过这个IIC 接口来控制MPU6050,另外还有一个 IIC 接口:AUX_CL和AUX_DA ,这个接口可用来连外部从设备比如磁力计,这样就可以组成一个九轴传感器
AD0是从IIC 接口(接 MCU)的地址控制引脚,该引脚控制的是IIC 地址的最低位。

二、MPU6050相关寄存器

1.陀螺仪配置寄存器

在这里插入图片描述
该寄存器我们只关心FS_SEL[1:0]这两个位,用于设置陀螺仪的满量程范围:0,±250°/s;1,±500°/s;2,±1000°/s;3,±2000°/s;
我们一般设置为3,即±2000°/S,因为陀螺仪的ADC为16位分辨率,所以得到灵敏度为:65536/4000=16.4LSB/(°/S)。
总之,陀螺仪配置寄存器就是配置陀螺仪满量程范围,设置最大

2.陀螺仪测量值寄存器

在这里插入图片描述
陀螺仪数据输出寄存器总共由6个寄存器组成,输出X/Y/Z三个轴的陀螺仪传感器数据,高字节在前,低字节在后。
总之,陀螺仪数据输出寄存器就是把陀螺仪测量到的数据输出出来。

3.加速度计配置寄存器


该寄存器我们只关心AFS_SEL[1:0]这两个位,用于设置加速度传感器的满量程范围:0,±2g;1,±4g;2,±8g;3,±16g;我们一般设置为0,即±2g,因为加速度传感器的ADC也是16位,所以得到灵敏度为:65536/4=16384LSB/g。
总之,加速度传感器配置寄存器就是配置加速度传感器满量程范围,不宜过大

4. 加速度计测量值寄存器

在这里插入图片描述
加速度传感器数据输出寄存器总共由6个寄存器组成,输出X/Y/Z三个轴的加速度传感器值,高字节在前,低字节在后。
ACCEL_XOUT : 由 2部分组成的 16位数值存储最近X 轴加速度计的测量值。 ACCEL_YOUT : 由 2部分组成的 16位数值存储最近Y
轴加速度计的测量值。 ACCEL_ZOUT :由 2部分组成的 16位数值存储最近Z 轴加速度计的测量值。

5.FIFO使能寄存器

在这里插入图片描述
该寄存器用于控制FIFO使能,在简单读取传感器数据的时候,可以不用FIFO,设置对应位为:0,即可禁止FIFO,设置为1,则使能FIFO。加速度传感器的三个轴,全由一个位(ACCEL_FIFO_EN)控制,只要该位为1,则加速度传感器三个通道都开启FIFO;但是陀螺仪传感器的三个轴需要一个一个设置,即XYZ轴分别配置。
总之,FIFO使能寄存器用于控制使能FIFO(First Input First Output)

6.陀螺仪采样分频寄存器

在这里插入图片描述
该寄存器用于设置MPU6050的陀螺仪采样频率,计算公式为:采样频率 = 陀螺仪输出频率 /
(1+SMPLRT_DIV)。这里陀螺仪的输出频率,是1Khz或者8Khz,与数字低通滤波器(DLPF)的设置有关,当DLPF_CFG=0或7的时候,频率为8Khz,其他情况是1Khz。而且DLPF滤波频率一般设置为采样率的一半。采样率,我们假定设置为50Hz,那么:SMPLRT_DIV=1000/50-1=19。
总之,陀螺仪采样率分频寄存器就是用于设置陀螺仪的采样频率,如果采样频率为50Hz,那么采样周期就为1/50=20ms,即20ms采集一次陀螺仪的数据。

7.配置寄存器

在这里插入图片描述
观察数字低通滤波器( DLPF)的设置位,即: DLPF_CFG[2:0],加速 度计和陀螺仪,都是根据这三个位的配置进行过滤的。
DLPF_CFG 不同配置对应的过滤情况如下表
在这里插入图片描述
总之,配置寄存器就是设置数字低通滤波器的DLPF_CFG位来结合陀螺仪采样分频寄存器来共同设置采样周期。

8.电源管理寄存器1

在这里插入图片描述
DEVICE_RESE=1,复位MPU6050,复位完成后,自动清零。SLEEP=1,进入睡眠模式;SLEEP=0,正常工作模式。TEMP_DIS,用于设置是否使能温度传感器,设置为0,则使能CLKSEL[2:0],用于选择系统时钟源,如下所示:
在这里插入图片描述
总之,电源管理寄存器就是复位MPU6050

9.电源管理寄存器2

在这里插入图片描述
该寄存器的LP_WAKE_CTRL用于控制低功耗时的唤醒频率,用不到。剩下的6位,分别控制加速度和陀螺仪的x/y/z轴是否进入待机模式,这里我们全部都不进入待机模式,所以全部设置为:0 ,即可。 总之,电源管理寄存器2就是用于设置加速度传感器和陀螺仪的X/Y/Z轴是进入休眠还是正常工作。

10.温度传感器数据输出寄存器

在这里插入图片描述

通过读取0X41(高8位)和0X42(低8位)寄存器得到,温度换算公式为: Temperature = 36.53 +
regval/340。其中,Temperature为计算得到的温度值,单位为℃,regval为从0X41和0X42读到的温度传感器值。
总之,温度传感器数据输出寄存器就是把温度寄存器测量到的数据处处出来。

三、数字运动处理器(DMP)

嵌入式数字运动处理器(DMP)位于MPU-60X0内部,可从主机处理器中卸载运动处理算法的运算。
DMP从加速度计,陀螺仪以及其他第三方传感器(如磁力计)获取数据,并处理数据。结果数据可以从DMP的寄存器中读取,或者可以在FIFO中缓冲。
DMP可以访问其中的一个MPU的外部引脚,可用于产生中断。
DMP的目的是卸载主机处理器的时序要求和处理能力。通常,运动处理算法应该以高速运行,通常在200Hz左右,以提供低延迟的精确结果。即使应用程序以更低的速率更新,这也是必需的。例如,一个低功率的用户界面可能会以5Hz的速度更新,但运动处理仍然应该以200Hz运行。
DMP可以作为一种工具使用,以最大限度地降低功耗,简化定时,简化软件架构,并在主机处理器上节省宝贵的MIPS,以便在应用中使用。

四、代码

1.定义

//#define MPU_ACCEL_OFFS_REG		0X06	//accel_offs寄存器,可读取版本号,寄存器手册未提到
//#define MPU_PROD_ID_REG			0X0C	//prod id寄存器,在寄存器手册未提到
#define MPU_SELF_TESTX_REG		0X0D	//自检寄存器X
#define MPU_SELF_TESTY_REG		0X0E	//自检寄存器Y
#define MPU_SELF_TESTZ_REG		0X0F	//自检寄存器Z
#define MPU_SELF_TESTA_REG		0X10	//自检寄存器A
#define MPU_SAMPLE_RATE_REG		0X19	//采样频率分频器
#define MPU_CFG_REG				0X1A	//配置寄存器
#define MPU_GYRO_CFG_REG		0X1B	//陀螺仪配置寄存器
#define MPU_ACCEL_CFG_REG		0X1C	//加速度计配置寄存器
#define MPU_MOTION_DET_REG		0X1F	//运动检测阀值设置寄存器
#define MPU_FIFO_EN_REG			0X23	//FIFO使能寄存器
#define MPU_I2CMST_CTRL_REG		0X24	//IIC主机控制寄存器
#define MPU_I2CSLV0_ADDR_REG	0X25	//IIC从机0器件地址寄存器
#define MPU_I2CSLV0_REG			0X26	//IIC从机0数据地址寄存器
#define MPU_I2CSLV0_CTRL_REG	0X27	//IIC从机0控制寄存器
#define MPU_I2CSLV1_ADDR_REG	0X28	//IIC从机1器件地址寄存器
#define MPU_I2CSLV1_REG			0X29	//IIC从机1数据地址寄存器
#define MPU_I2CSLV1_CTRL_REG	0X2A	//IIC从机1控制寄存器
#define MPU_I2CSLV2_ADDR_REG	0X2B	//IIC从机2器件地址寄存器
#define MPU_I2CSLV2_REG			0X2C	//IIC从机2数据地址寄存器
#define MPU_I2CSLV2_CTRL_REG	0X2D	//IIC从机2控制寄存器
#define MPU_I2CSLV3_ADDR_REG	0X2E	//IIC从机3器件地址寄存器
#define MPU_I2CSLV3_REG			0X2F	//IIC从机3数据地址寄存器
#define MPU_I2CSLV3_CTRL_REG	0X30	//IIC从机3控制寄存器
#define MPU_I2CSLV4_ADDR_REG	0X31	//IIC从机4器件地址寄存器
#define MPU_I2CSLV4_REG			0X32	//IIC从机4数据地址寄存器
#define MPU_I2CSLV4_DO_REG		0X33	//IIC从机4写数据寄存器
#define MPU_I2CSLV4_CTRL_REG	0X34	//IIC从机4控制寄存器
#define MPU_I2CSLV4_DI_REG		0X35	//IIC从机4读数据寄存器

#define MPU_I2CMST_STA_REG		0X36	//IIC主机状态寄存器
#define MPU_INTBP_CFG_REG		0X37	//中断/旁路设置寄存器
#define MPU_INT_EN_REG			0X38	//中断使能寄存器
#define MPU_INT_STA_REG			0X3A	//中断状态寄存器

#define MPU_ACCEL_XOUTH_REG		0X3B	//加速度值,X轴高8位寄存器
#define MPU_ACCEL_XOUTL_REG		0X3C	//加速度值,X轴低8位寄存器
#define MPU_ACCEL_YOUTH_REG		0X3D	//加速度值,Y轴高8位寄存器
#define MPU_ACCEL_YOUTL_REG		0X3E	//加速度值,Y轴低8位寄存器
#define MPU_ACCEL_ZOUTH_REG		0X3F	//加速度值,Z轴高8位寄存器
#define MPU_ACCEL_ZOUTL_REG		0X40	//加速度值,Z轴低8位寄存器

#define MPU_TEMP_OUTH_REG		0X41	//温度值高八位寄存器
#define MPU_TEMP_OUTL_REG		0X42	//温度值低8位寄存器

#define MPU_GYRO_XOUTH_REG		0X43	//陀螺仪值,X轴高8位寄存器
#define MPU_GYRO_XOUTL_REG		0X44	//陀螺仪值,X轴低8位寄存器
#define MPU_GYRO_YOUTH_REG		0X45	//陀螺仪值,Y轴高8位寄存器
#define MPU_GYRO_YOUTL_REG		0X46	//陀螺仪值,Y轴低8位寄存器
#define MPU_GYRO_ZOUTH_REG		0X47	//陀螺仪值,Z轴高8位寄存器
#define MPU_GYRO_ZOUTL_REG		0X48	//陀螺仪值,Z轴低8位寄存器

#define MPU_I2CSLV0_DO_REG		0X63	//IIC从机0数据寄存器
#define MPU_I2CSLV1_DO_REG		0X64	//IIC从机1数据寄存器
#define MPU_I2CSLV2_DO_REG		0X65	//IIC从机2数据寄存器
#define MPU_I2CSLV3_DO_REG		0X66	//IIC从机3数据寄存器

#define MPU_I2CMST_DELAY_REG	0X67	//IIC主机延时管理寄存器
#define MPU_SIGPATH_RST_REG		0X68	//信号通道复位寄存器
#define MPU_MDETECT_CTRL_REG	0X69	//运动检测控制寄存器
#define MPU_USER_CTRL_REG		0X6A	//用户控制寄存器
#define MPU_PWR_MGMT1_REG		0X6B	//电源管理寄存器1
#define MPU_PWR_MGMT2_REG		0X6C	//电源管理寄存器2 
#define MPU_FIFO_CNTH_REG		0X72	//FIFO计数寄存器高八位
#define MPU_FIFO_CNTL_REG		0X73	//FIFO计数寄存器低八位
#define MPU_FIFO_RW_REG			0X74	//FIFO读写寄存器
#define MPU_DEVICE_ID_REG		0X75	//器件ID寄存器
 
//如果AD0脚(9脚)接地,IIC地址为0X68(不包含最低位).
//如果接V3.3,则IIC地址为0X69(不包含最低位).
#define MPU_ADDR				0X68

2.初始化MPU6050

u8 MPU_Init(void)
{ 
	u8 res;
	IIC_Init();//初始化IIC总线
	MPU6050_WriteByte(MPU_PWR_MGMT1_REG,0X80);	//复位MPU6050
    delay_ms(100);
	MPU6050_WriteByte(MPU_PWR_MGMT1_REG,0X00);	//唤醒MPU6050 
	MPU_Set_Gyro_Fsr(3);					//陀螺仪传感器,±2000dps
	MPU_Set_Accel_Fsr(0);					//加速度传感器,±2g
	MPU_Set_Rate(50);						//设置采样率50Hz
	MPU6050_WriteByte(MPU_INT_EN_REG,0X00);	//关闭所有中断
	MPU6050_WriteByte(MPU_USER_CTRL_REG,0X00);	//I2C主模式关闭
	MPU6050_WriteByte(MPU_FIFO_EN_REG,0X00);	//关闭FIFO
	MPU6050_WriteByte(MPU_INTBP_CFG_REG,0X80);	//INT引脚低电平有效	
	res=MPU6050_ReadByte(MPU_DEVICE_ID_REG);
	if(res== MPU_ADDR)//器件ID正确  0x68 <<1 | w/r  011010 00   (w/r)
	{
		MPU6050_WriteByte(MPU_PWR_MGMT1_REG,0X01);	//设置CLKSEL,PLL X轴为参考
		MPU6050_WriteByte(MPU_PWR_MGMT2_REG,0X00);	//加速度与陀螺仪都工作
		MPU_Set_Rate(50);						//设置采样率为50Hz
 	}else return 1;
	return 0;
}

3.设置MPU6050陀螺仪传感器满量程范围

//fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
//返回值:0,设置成功
//    其他,设置失败 
u8 MPU_Set_Gyro_Fsr(u8 fsr)
{
	return MPU6050_WriteByte(MPU_GYRO_CFG_REG,fsr<<3);//设置陀螺仪满量程范围  
}

4.设置MPU6050加速度传感器满量程范围

//fsr:0,±2g;1,±4g;2,±8g;3,±16g
//返回值:0,设置成功
//    其他,设置失败 
u8 MPU_Set_Accel_Fsr(u8 fsr)
{
	return MPU6050_WriteByte(MPU_ACCEL_CFG_REG,fsr<<3);//设置加速度传感器满量程范围  
}

5.设置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 MPU6050_WriteByte(MPU_CFG_REG,data);//设置数字低通滤波器  
}

6.设置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=MPU6050_WriteByte(MPU_SAMPLE_RATE_REG,data);	//设置数字低通滤波器
 	return MPU_Set_LPF(rate/2);	//自动设置LPF为采样率的一半
}

7.得到陀螺仪值(原始值)

//gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
//返回值:0,成功
//其他,错误代码
u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz)
{
    u8 buf[6],res;  
	res=MPU6050_Read_Len(0x68,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;;
}

8.得到加速度值(原始值)

//gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
//返回值:0,成功
//其他,错误代码
u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
{
    u8 buf[6],res;  
	res=MPU6050_Read_Len(0x68,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;;
}

9.得到温度值

//返回值:温度值(扩大了100倍)
short MPU_Get_Temperature(void)
{
    u8 buf[2]; 
    short raw;
	float temp;
	
	MPU6050_Read_Len(0x68,MPU_TEMP_OUTH_REG,2,buf); 
    
	raw=((u16)buf[0]<<8)|buf[1];  
	
    temp=36.53+((double)raw)/340;  
    return temp*100;
}

总结

因为用的是IIC通信方式嘛,这部分的代码需要先学会IIC通信,我就不传上了,太多了,看起来就烦人。如果需要源码,可以评论下我发你。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐