上一次博客我们讲述了I2C协议的通信标准,有了I2C通信我们就可以实现指定地址写和指定地址读的操作了。这样即使各种外挂芯片的寄存器不在STM32内部,我们仍然可以通过通信协议实现读写外挂芯片寄存器的功能。这样就能完全掌控这个外挂芯片了,我们这次来学习一下MPU6050模块。
一.简介
1.了解一下

一个是PS产品说明书,另一个是RM寄存器映像。
产品说明书就是介绍芯片的功能描述,电气参数,引脚定义,硬件电路等等。
寄存器影像中有一个总表记录着信哦所有的寄存器以及他们的地址。

先看一下我们的简介再去查找芯片手册。
现在芯片是3轴加速度,3轴陀螺仪,如果再加一个3轴的磁场传感器,那么就叫做九轴的姿态传感器。通过这些数据进行融合就可以得到姿态角,也就是欧拉角。
以飞机为例

欧拉角就是飞机机身,相对于初始三个轴的夹角。

飞机机头下倾或上仰,这个轴的夹角叫俯仰Pitch

飞机机身左翻滚,右翻滚这个轴的夹角叫做滚转Roll。

飞机机身保持水平,机头向左转或右转,这个轴的夹角叫做偏航Yaw。
简单来说欧拉角就表示了,我们飞机此时的姿态,不论飞机发生什么变化,上扬,下倾,欧拉角都能清晰的表达出来。如果想做一个飞控算法,让飞机姿态表示平稳,那么得到一个精确而稳定的欧拉角,至关重要。

但是这两个传感器,任何一种都不能获得精确而稳定的欧拉角。要想获得精确而稳定的欧拉角,我们就需要进行数据融合,把这几种数据的传感器结合起来。综合多种传感器的数据,取长补短。这样才能获得精确而稳定的欧拉角。
常见的融合算法一般有互补滤波,卡尔曼滤波的方法。姿态传感器解算出姿态角之后,就常用于平衡车,飞行器等需要检测自身姿态的场景了。
平衡车的话,如果传感器检测到车身向前或向后倾斜了,程序就可以控制轮子进行调整,保持平衡车的平衡。飞行器的话需要检测的就多一些,一般至少要检测,俯仰角,滚转角。两个夹角,然后控制电机保持飞机的平衡。这就是这个MPU6050姿态传感器的作用。
2.3轴加速度计
一般简称accl或者acc或者a。测量X,Y,Z轴的加速度。

如图可以看到X,Y,Z轴就是一个三维的坐标系。其中横向的定义为X轴,纵向的定义为Y轴,垂直于芯片的定义为Z轴。再这个芯片的内部的X,Y,Z轴都分别布置了一个加速度计。

加速度计的结构图。水平的虚线是感应轴线。中间是有一个具有一定质量,可以左右滑动的小滑块然后左右各有一个弹簧顶着它。如果把这个东西拿在手上来回晃,中间的小滑块就会左右移动,去压缩和拉动两边的弹簧。当滑块移动时就会带动上面的电位器滑动,这个电位器实际上就是一个分压电阻,然后我们测量电位器的输出电压,就能得到小滑块所受到的的加速度值了。
起始可以发现这个加速度计,实际上就是一个弹簧测力计。根据牛顿第二定律F=ma。我们想测量这个加速度a,就可以找一个单位质量的物体。测量它所受的力F就行了。所以你听这个名字加速度计,感觉高大上难以理解,实际上就是一个测力计而已。那在这个芯片里面X,Y,Z三个轴都有一个这样的测力计。

可以画一个辅助模型来理解,想象,这个芯片内部,有6个测力的称,组成一个正方体。正方体内部,放一个大小正好的单位质量小球,这个小球压在哪个称面上,就会产生对应一个轴的数据输出

比如小球压在下面这个面,就是Z轴的正值。

比如小球压在上面这个面,就是Z轴的正值。
对象两个面为1组,那么正方体6个面所测得力就是3个轴的加速度值。这就是加速度计的一个直观理解。
比如把芯片静置水平放在地球上,那么只有地面测力计收到小球的压力,所以此时数据输出就是X和Y轴输出为0。Z轴输出一个G的加速度值,如果此时芯片处于自由落体,那么就是所有面都不受力,此时数输出就i是X,Y,Z轴都为0。
如果向左倾斜放置,那么地面和左面都受力

这时我们像这样求一个三角函数,就能得到向左的倾角a了。不过这个倾角只有再芯片静置时候才是正确的。因为加速度分为重力加速度和运动加速度。如果此时芯片运动起来了,那么这个三角函数求得的倾角,就会受运动加速度的影响。(比如说坐车当车加速时候,会感觉贴着靠背和座位,但是实际上受力相当于斜坡)所以仅仅使用加速度计求角度,只有再物体静止时候才可以,当物体运动起来,这个角度就会受运动加速度的影响而变得不准确,这就是加速度计的原理和特征。
总结一下就是,加速度计具有静态稳定性,不具有动态稳定性。
3.3轴陀螺仪传感器
简称Gyro,G。测量X,Y,Z轴的角速度。

这就是陀螺仪的机械模型,中间是一个有一定质量的旋转轮,外面是3个轴的平衡环。当中间的旋转轮高速旋转时候。根据角动量守恒的原理,这个旋转轮具有保持他原有角动量的趋势这个趋势可以保证旋转轴方向不变,当你外部物体的方向转动时,内部的旋转轴方向并不会转动。这就会在平衡环的连接处,产生角度偏差,如果我们再连接处放一个旋转电位器,测量电位器的电压就能得到旋转轴的角度了。
从这里分析陀螺仪因该是可以直接得到角度的,但是我们这个MPU6050的陀螺仪并不能直接测量角度。可能是结构的差异,或者工艺的限制。我们这个芯片内部的陀螺仪,实际上测量的是芯片的角速度,而不是角度。
陀螺仪测量X,Y,Z轴的角速度值,分别表示了此时,芯片绕X轴,Y轴,Z轴旋转的角速度。
如果想通过角速度得到角度的话,我们直接对角速度进行积分即可。角速度积分就是角度,和加速度计测角度一样,这个角速度积分得到的角度具有局限性,就是当物体静止时,角速度的值会因为噪声无法完全归零。然后经过积分的不断累积,这个小噪声就会导致算出来的角度产生缓慢的飘移,也就是角速度积分得到的角度经不起时间的考验。不过这个角度呢无论是运动还是静止,都是没有问题的,它不会受物体运动的影响。
所以总结一下就是陀螺仪具有动态稳定性,而不具有静态稳定性。
于是加速度计和陀螺仪传感器正好可以互补。所以我们取长补短,进行一下互补滤波,就能融合得到静态和动态都稳定的姿态角了。这就是姿态解算的大体思路,但是实际的姿态解算肯定会更复杂一些。
4.MPU6050参数

(1)量程选择
电子的传感器最终输出的时一个随姿态变化而变化的电压,要想量化这个电压信号,就离不开AD转换器了,所以这个芯片内部也是自带了AD转换器了。可以对各个模拟参量进行量化,这个ADC是16位的,那么量化输出的范围就是2^16,如果作为无符号数的话就是0--65535,这里因为传感器每个轴都有正负数据,所以这个输出结果是一个有符号数,量化范围是-32768--32767。
数据是16位的会分为两个字节储存,之后我们读取数据寄存器时候就可以看到了。
这个16位有符号数的范围,对应的物理参量的范围是多少呢。这里就需要定义一个满量程范围,这个满量程范围就相当于我们之前学习ADC的时候,哪个VREF参考电压一样,你的AD值达到最大时,你的对应电压是3.3V还是5V呢。需要有一个参考电压来指定。
这里也是一样,16位ADC值达到最大值时,对应的物理参量具体是多少,也是有由满量程范围决定的。在这里加速度计和陀螺仪的满量程范围,都有几个值可以选。
加速度计满量程可以选择:±2,±4,±8,±16单位是g也就是重力加速度。1g=9.8m/s^2。
陀螺仪满量程可以选择:±250,±500,±1000,±2000单位是度每秒,就是角速度的单位,每秒旋转了多少度。
这里呢如果你所测量的物体运动非常剧烈。就可以把满量程选的大一些,防止你的加速度,角速度超出了量程,如果你所测量的物体运动比较平缓,就可以选择比较小的量程,这样测量的分辨率就会更大。比如说你选择加速度计满量程±16g,当读取最大值,32768时,当然实际的最大值是32767,那就表示此时测量的加速度为满量程16g,AD值为32768的一半时,就表示加速度为8g,如果选择满量程为±2g的话,那么此时32768就对应2g的加速度。因为AD值说固定的,所以满量程选的越小,测量的值就会越细腻。另外加速度值和AD值是线性关系,一一对应的,由AD值求加速度,就是乘一个系数就可以了,这和我们之前学ADC的时候由AD值求电压是一个道理的。
陀螺仪的量程选择也是一个道理。
(2)可配置低通滤波器
在这个芯片里可以配置寄存器来选择对输出数据进行低通滤波,如果你觉得输出数据抖动的厉害,就可以加一点低通滤波,这样输出数据就会平坦一些。
(3)可配置时钟源和可配置采样分频
可配置时钟源和可配置采用分频,这两个参数是配合使用的,时钟源经过这个分频器的分频,可以为AD转换和内部电路提时钟,控制分频系数,就是控制AD转换的快慢了。可以配合DMA一起使用
(4)I2C从机地址
这个芯片进行I2C通信的从机地址这个可以在手册里查到

当AD0的值等于0时,地址为1101000,当AD0的值等于1时,地址为1101001。AD0就i是板子引出来的一个引脚,可任意调节I2C从机地址的最低位,这里地址是7位的,如果像这里用二进制表示的话,一般没有什么问题。如果再程序中用16进制表示的话,一般会有两种表示方式。以这个100100地址为例。
第一种:就是单纯的把这7位二进制数转换为16进制。这里110 1000这样分开,转换为16进制就是0x68。所以有的地方就说MPU6050的从机地址是0x68。就是这个意思。

我们看一下I2C通信的时序,这里第一个字节的高七位是从机地址。最低位是读写位,所以如果认为0x68是从机地址的话,需要把0x68左移一位,再按位或上读写位,读1写0。
第二种:把0x68左移一位的地址,当作MPU6050的从机地址。110 1000左移一位之后1101 0000然后变为16进制是0xD0,那么这样MPU6050的从机地址就是0xD0。这时在实际发送一个字符时,如果你要写,就直接把0xD0当作第一个字节。如果你要读就把0xD0或上0x01,即把0xD1当作第一个字节,这种表示方式就不需要进行左移的操作了。或者说这种表示方式是把读写位也融入到从机地址里面了,0xD0是写地址,0xD1是读地址,这样子表示的。
所以之后看到有的地方说0xD0是MOU6050的从机地址,那他就是融入了读写位的从机地址。如果看到有的地方说0x68是MPU6050的从机地址这也不奇怪,这种方式是直接把7位二进制转换为16进制的,在实际发送字节时,不要忘了左移一位,然后或上读写位,这就是两种从机地址的表示方式。当然不论哪种表示方式,得到的,第一个字节都是一样的,在实际中两种方式都是出现过,根据自己的喜好就行。
5.硬件电路


这时我们MPU6050的芯片,左下角是一个8针的排针

这个是我们LDO的低压差线性稳压器。

右边这个是MPU6050的芯片芯片本身的引脚是非常多的。包括时钟,I2C通信引脚,供电,帧同步等等。还有一些引脚是最小系统里的固定连接。


然后看我们印出来的引脚,VCC和GND是电源供电。SCL和SDA这两个是I2C通信的引脚

这里可以看到SCL和SDA都接了一个4.7K的上拉电阻,所以在我们接线时候,直接把SCL和SDL接在GPIO口就可以了,不需要再外接上拉电阻了。
接着还有XCL和XDA,这两个是芯片里面的主机I2C通信引脚,设计这两个引脚是为了拓展芯片功能,之前我们说明=果MPU6050是一个6轴传感器,但是只有加速度计和陀螺仪的6个轴,融合出来的姿态角是有缺陷的。这个缺陷就是绕Z轴的角度,也就是偏航角他的漂移无法通过加速度计进行修正,就像是让你坐在车里,不看任何窗户,短时间内分辨车的方向,短时间内可以通过陀螺仪感知方向的变化,从而确定变化后的行驶方向,但是时间一长,车子到出拐弯,你没有稳定的参考了,肯定会迷失方向。所以这时候就需要带个指南针在身边,提供长时间的稳定偏航角进行参考,来对陀螺仪感知的方向进行纠正。这就是9轴陀螺仪姿态传感器多出来的磁力计的作用,另外,如果你要制作无人机,需要定高飞行这时候还需要增加气压计。扩展为10轴,提供一个高度信息的稳定参考。
所以根据项目要求,6轴的传感器可能不够用,需要进行扩展,那么这个时候XCL和XDA就可以起作用了,XCL和XDA通常是外接磁力计或者气压计,当接上磁力计或者气压计之后,.PU6050的主机接口,可以直接访问这些扩展芯片的数据,把这些扩展芯片的数据直接读取到MPU6050里面。在MPU6050里面会有DMP单元进行数据融合和姿态解算。
当然如果你不需要MPU6050的解算功能的话,也可以把磁力计或者气压计,直接挂在SCL或者SDA这条总线上。因为I2C本来就可以挂在多设备
AD0从机地址的最低位接低电平七位从机地址就是1101 000,高电平的话七位从机地址就是1101 001。

这里可以看到,有个电阻默认若下拉到低电平,也就是说这个引脚悬空的话就是低电平。如果想接高电平直接把AD0引到VCC强上拉置高电平
INT中断输出引脚可以配置芯片内部的一些中断事件来触发中断引脚的输出,比如说数据准备好了,I2C主机错误等,另外芯片内部还内置了一些小功能,比如自由落体检测,运动检测,0运动检测等。这些信号都可以触发INT引脚电平跳变,需要的话可以进行中断信号的配置
手册中可以查到MPU6050VDD供电范围是2.375-3.46V,属于3.3V供电设备,不能直接接5V,所以右上角就加了一个3.3V的LDO稳压器,如果有3.3V稳电源就不需要供电了。如果没有的话可以使用这个电路。
6.模块框图
接下来看一下模块框图


左上角是时钟系统,有时钟输入角和输出1角,不过一般我们一般使用内部时钟。

硬件电路这里clockin直接接在了GND。

clockout没有引出。

这些就是芯片内部的传感器。其中包括X,Y,Z轴的加速度计,和X,Y,Z轴的陀螺仪计。

另外这个芯片还内置了一个温度传感器。这些传感器就相当于一个可变电阻分压后,通过分压后输出模拟电压,通过ADC进行模数转换,转换完成后这些传感器的数据统一都放到数据寄存器中。我们读取寄存器,就能得到传感器测量的值了。这个芯片内部的转换都是全自动进行的,就类似我们之前了解的AD连续转换+DMA搬运,每个ADC输出,对应16位的数据寄存器,不存在数据覆盖的问题,我们配置好转换频率之后,每个数据就自动以我们设置的频率,自动刷新到数据寄存器。
我们需要数据时候直接读取就行,还是非常方便的。

每个传感器都有一个自测单元,这部分是用来验证芯片好坏的,当启动自测后,芯片内部就会模拟一个外力施加在传感器上这个外力会让传感器比平时的数值大一些,
如何进行自测呢,我们可以先使能自测,然后读取数据,在失能自测读取数据,两个数据相减,得到的数据叫自测响应。这个自测响应手册中给出了一个范围,如果在自测响应在这个范围内,就说明芯片没有问题,如果不在就说明芯片可能损坏。

这个叫电荷泵或者叫充电泵,CPOUT引脚需要外接一个电容,电荷泵是一种升压电路,比如说有一个电池,电压是5V,再来个电容,首先电池和电容并联,电池给电容充电,充满后电容也相当于一个5V的电池。然后再修改电路的接发,把电池和电容串联,电容5V电池5V这样就是10V了,但是因为电容电荷很少所以就需要不断地并联充电,串联放电,并联充电,串联放电,再加个滤波电容就可以平稳的提供10V电压,因为芯片内部的陀螺仪是需要一个比较高的电压的。
7.寄存器和通讯接口


中断状态寄存器,可以控制内部那些事件到中断引脚的输出,

FIFO是先入先出寄存器,可以对数据流进行缓存,

配置寄存器,可以对内部的电路进行配置,

传感器寄存器也就是数据寄存器,存放了各个传感器的数据,

工厂校准,这个意思就是内部的传感器都进行了校准。

数字运动处理器简称DMP,是芯片内部自带的一个姿态解算的硬件算法,配合官方的DMP库可以进行姿态解算,因为姿态解算比较复杂,所以如果使用了内部的DMP进行姿态解算,就会方便一些。

帧同步。


最后上面这块就是通信接口部分,上面就是从机的I2C和SPI接口,用于和STM32单片机进行通信

下面是主机的通信接口,用于和MPU6050扩展的设备进行通信,

这里有一个接口旁路选择器,就是开关啊,如果拨到上面,辅助的I2C引脚就和正常的I2C引脚接在一起。这样两路总线就合在一起了。STM32可以控制所有的设备,这时STM32就是大哥,MPU50和扩展设备就是小弟。
如果拨到下面,辅助的I2C就由MPU6050控制,两条I2C总线独立分开,这时STM32是MPU6050的大哥,MPU6050是扩展设备的大哥。

供电部分,按照手册中的电压要求连接即可。
二.数据手册

首先是产品说明书,这个说明书是MPU6000和MPU6050共用的。
1.产品说明书

这3轴的MEMSgyro(陀螺仪)3轴MEMSacc(加速度计),其中MEMS是这个公司研发的微机电系统,可以用电子的方案进行测量。

接下来就是MPU6000和MPU6050之间的差距了。总结下来就是MPU6050有一个逻辑电源引脚,VLOGIC。可以支持供电和I/O口不一样的电平等级。二是MPU6000支持SPI和I2C,而MPU6050只支持I2C。

芯片的应用场景,比如图像稳定器,位置服务,游戏手柄,3D遥控器等等。

I2C的时序特征,这个芯片的I2C的SCL时钟频率最大支持400KHz。如果你的SCL时钟超过这个数值,那么这个芯片就跟不上了。

引脚定义。

参考电路。

系统时钟,这个芯片的时钟可以由上图的提供。
第一个是内部晶振,可以作为系统时钟,第二个是X,Y,Z轴的陀螺仪,他们也都会有一个晶振因为陀螺仪内部需要高精度的时钟支持,可以通过外部的CLOCKIN引脚输入32.768KHz的方波,或者19.2MHz的方波。

可选择的中断信号,可以配置当发生这些事件时候,INT引脚输出一个电平跳变,然后STM32可以用为外部中断来接收这个跳变

数据帧格式。指定地址写一个字节
S:开始,AD:地址,W:写,ACK:应答,RA:寄存器地址,DATA:数据,P:停止

指定地址读一个字节。
S:开始,AD:地址,W:写,ACK:应答,RA:寄存器地址,DATA:数据,P:停止,NACK:主机非应答
2.寄存器映像

真正要写程序,还得研究明白寄存器才行,因为STM32有库函数封装,所以对寄存器要求不高,但是这个MPU6050芯片的寄存器我们还要研究一下。

寄存器总表,我们不一定所有的都用的上,我们只要我们用的。

第一列是寄存器的地址是十六进制表示的,第二列是寄存器地址是十进制表示的,第三列是寄存器名称,第四列,是读写权限,RW表示可读可写,R表示只读。
第一个是采用频率分频器,第二个是配置寄存器,第三个是陀螺仪配置寄存器,第四个是加速度计配置寄存器,

这些是数据寄存器。ACC是加速度计的X,Y,Z传感器,GYRO是陀螺仪的X,Y,Z传感器,TRMP是温度传感器,然后_H表示高八位,_L表示低八位。

PWR是电源管理寄存器,WHO就是器件ID号。
3.寄存器说明
(1)采样频率分频器

这里面的8位为一个整体,作为分频值,这个寄存器可以配置采样频率的分频系数,简单来说就是分频越小,内部的AD转换就越快,数据寄存器刷新就越快,反之就越慢。

这里有个公式,可以理解为,采样频率=数据刷新率。
采样频率=陀螺仪输出频率/(1+分频值)。这个晶振就是刚刚说的时钟源,陀螺仪晶振,外部晶振,内部时钟,这里以陀螺仪晶振为例子。

注意事项,不使用低通滤波器时陀螺仪时钟为8KHz,使用滤波器,陀螺仪时钟就是1KHz。
(2)低通滤波器寄存器

配置寄存器

内部有两部分,一个是外部同步设置,一个是低通滤波器配置。外部同步我们不用可以不看。

然后是低通滤波器,配置这些位可以选择这里的各种滤波参数,这个低通滤波器可以让输出数据更加平滑,配置滤波器参数越大,输出数据越稳定,0是不使用低通滤波器,陀螺仪时钟为8KHz。之后使用了滤波器,陀螺仪时钟就是1KHz。
(3)陀螺仪配置寄存器


高三位是X,Y,Z轴的自测使能位

中间两位是满量程选择位。

自测响应=自测使能时数据-自测失能时数据。

这里可以看到自测响应的范围。
(4)陀螺仪数据寄存器

(5)加速度计配置寄存器


高三位是自测使能位

中间是满量程选择位

低三位是配置高通滤波器的,就是内置小功能运动检测用的,对数据输出没有影响,暂时不用。
(6)加速度计数据寄存器

我们想读取数据的话之间读取数据寄存器就可以了。

这是一个2进制的有符号数,以补码的形式存在,我们读出高八位和低八位,高八位左移或上低位数据,最后存在一个int16_t的变量里这样就可以得到数据了。
(7)电源管理寄存器1


第一位:设备复位,这一位写1,所有寄存器恢复到默认值
第二位:睡眠模式,这一位写1,芯片睡眠不工作,进入低功耗
第三位:循环模式,这一位写1,设备进入低功耗过一段时间,设备启动一段时间,并且唤醒的频率由这个寄存器的这两位决定

第五位:温度传感器失能,这一位写1,禁用内部的温度传感器
最后三位:用来选择系统时钟源

按照表里面分别是:内部晶振,XYZ轴陀螺仪晶振,外部引脚的两个方波,一般我们选择内部晶振或者陀螺仪晶振。

这里有个建议,非常建议我们选择陀螺仪晶振,因为陀螺仪的晶振非常准确
(8)电源管理寄存器2

前两位刚刚说过。是低功率下芯片的唤醒频率。

后面六位可以分别控制六个轴进入待机模式。如果只需要部分轴的数据,就可以让其他轴进入待机模式,这样比较省电。
(9)ID号寄存器

这个寄存器是只读的,ID号不可修改

ID号中间的6位,固定位110 100实际上这个ID号就是这个芯片的I2C地址。他的最高位和最低位其实都是0,那么读出这个寄存器值就固定为0x68。

这里有句话AD0引脚的值,并不反映在寄存器上,意思就是之前我们说过,这个I2C地址可以通过AD0引脚进行配置,但是这里的ID号的最低位,是不随AD0引脚变化而变化的。读出ID号始终都是0x68。

还有一句话,所有的寄存器地址上电默认都是0x00。除了下面这两个。
107号寄存器上电默认为:0x40。
117号寄存器上电默认为:0x68。

117号就是ID号默认0x68。

117号就是电源管理寄存器1,默认0x40也就是次高位为1,这里次高位是SLEEP,所以这个芯片上电默认就是睡眠模式。再操作他之前要先记得解除睡眠,否则操作其他寄存器是无效的。
到这里我们MPU6050芯片就了解的差不多了我们接下来就是实现I2C通信,操作MPU6050的寄存器进行数据的读写。
zz