1.陀螺仪及MPU6050模块介绍(大同小异可以略过)

Ⅰ.陀螺仪
陀螺仪是用高速回转体的动量矩敏感壳体相对惯性空间绕正交于自转轴的一个或二个轴的角运动检测装置。利用其他原理制成的角运动检测装置起同样功能的也称陀螺仪。
从力学的观点近似的分析陀螺的运动时,可以把它看成是一个刚体,刚体上有一个万向支点,而陀螺可以绕着这个支点作三个自由度的转动,所以陀螺的运动是属于刚体绕一个定点的转动运动。更确切地说,一个绕对称铀高速旋转的飞轮转子叫陀螺。将陀螺安装在框架装置上,使陀螺的自转轴有角转动的自由度,这种装置的总体叫做陀螺仪。
陀螺仪的原理就是,一个旋转物体的旋转轴所指的方向在不受外力影响时,是不会改变的。人们根据这个道理,用它来保持方向,制造出来的东西就叫陀螺仪。我们骑自行车其实也是利用了这个原理。轮子转得越快越不容易倒,因为车轴有一股保持水平的力量。陀螺仪在工作时要给它一个力,使它快速旋转起来,一般能达到每分钟几十万转,可以工作很长时间。然后用多种方法读取轴所指示的方向,并自动将数据信号传给控制系统。

Ⅱ.MPU6050模块
简介:
MPU6050内部整合了三轴MEMS陀螺仪三轴MEMS加速度计以及一个可扩展的数字运动处理器DMP(Digital Motion Processor),而且还可以连接一个第三方数字传感器(如磁力计),这样的话,就可以通过IIC接口输出一个9轴信号(链接第三方数字传感器才可以输出九轴信号,否则只有六轴信号)。更加方便的是,有了DMP,可以结合InvenSense公司提供的运动处理资料库,实现姿态解算。通过自带的DMP,可以通过IIC接口输出9轴融合演算的数据,大大降低了运动处理运算对操作系统的负荷,同时也降低了开发难度。其实,简单一句话说,陀螺仪就是测角速度的,加速度传感器就是测角加速度的,二者数据通过算法就可以得到PITCH、YAW、ROLL角了。
特点:

  • 以数字形式输出 6 轴或 9 轴(需外接磁传感器)的旋转矩阵、四元数(quaternion)、欧拉角格式(Euler Angle forma)的融合演算数据(需 DMP 支持)
  • 具有 131 LSBs/° /sec 敏感度与全格感测范围为±250、±500、±1000 与±2000° /sec的 3 轴角速度感测器(陀螺仪)
  • 集成可程序控制,范围为±2g、±4g、±8g 和±16g 的 3 轴加速度传感器
  • 移除加速器与陀螺仪轴间敏感度,降低设定给予的影响与感测器的飘移
  • 自带数字运动处理(DMP: Digital Motion Processing)引擎可减少 MCU 复杂的融合演算数据、感测器同步化、姿势感应等的负荷
  • 内建运作时间偏差与磁力感测器校正演算技术,免除了客户须另外进行校正的需求
  • 自带一个数字温度传感器
  • 带数字输入同步引脚(Sync pin)支持视频电子影相稳定技术与 GPS
  • 可程序控制的中断(interrupt),支持姿势识别、摇摄、画面放大缩小、滚动、快速下降中断、 high-G 中断、零动作感应、触击感应、摇动感应功能
  • VDD 供电电压为 2.5V±5%、 3.0V±5%、 3.3V±5%; VLOGIC 可低至 1.8V± 5%
  • 陀螺仪工作电流: 5mA,陀螺仪待机电流: 5uA; 加速器工作电流:500uA,加速器省电模式电流: 40uA@10Hz
  • 自带 1024 字节 FIFO,有助于降低系统功耗
  • 高达 400Khz 的 IIC 通信接口
  • 超小封装尺寸: 4x4x0.9mm(QFN)
MPU6050三轴角(姿态角)



绕向即为正方向,可根据右手螺旋定则确定方向。
MPU6050框图:


可以很清晰地观察到,MPU6050芯片中内置了三轴加速度传感器、三轴陀螺仪和一个温度传感器。右侧INT为中断输出脚,TCS为片选脚、AD0为设置地址脚、SCL和SDA为主IIC接口、AUX_CL和AUX_DA为从IIC接口,主要用到的是AD0、SCL、SDA。
相关寄存器(想深入了解的朋友可以看一下)结合后面的代码更容易理解一些




DEVICE_RESE=1,复位MPU6050,复位完成后,自动清零。SLEEP=1,进入睡眠模式;SLEEP=0,正常工作模式。TEMP_DIS,用于设置是否使能温度传感器,设置为0,则使能CLKSEL[2:0],用于选择系统时钟源,如下所示:
CLKSEL[2:0]
时钟源
001
内部8M RC晶振
010
PLL,使用X轴陀螺作为参考
011
PLL,使用Y轴陀螺作为参考
100
PLL,使用Z轴陀螺作为参考
101
PLL,使用外部32.768Khz作为参考
110
PLL,使用外部19.2Mhz作为参考
11
保留
001
关闭时钟,保持时序产生电路复位状态



总之,电源管理寄存器就是复位MPU6050




该寄存器我们只关心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)。
总之,陀螺仪配置寄存器就是配置陀螺仪满量程范围,设置最大




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




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




该寄存器用于设置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采集一次陀螺仪的数据。




总之,配置寄存器就是设置数字低通滤波器的DLPF_CFG位来结合陀螺仪采样分频寄存器来共同设置采样周期。




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




加速度传感器数据输出寄存器总共由6个寄存器组成,输出X/Y/Z三个轴的加速度传感器值,高字节在前,低字节在后。
总之,加速度传感器数据输出寄存器就是把加速度传感器测量到的数据输出出来。




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




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

3.硬件连接



VCC:接5V电源
GND:接地
SCL:主IIC时钟线 (我接的PB10)
SDA:主IIC数据线 (我接的PB11)
AD0:地址线,接3V地址为0x68,接地地址为0x69(我接的PA15,高电平,地址为0x68)

4.软件代码————官方自带库
MPU6050处理寄存器的相关数据时需要移植几个官方库,以便将数据处理为所需要的欧拉角。正点原子共提供了五个源码,如下图:



这些是需要在写MPU6050代码之前移植过来的,具体代码内容大家可以下载下方源码查看。

5.软件代码————其他代码
MPU6050.h
主要宏定义一些MPU6050寄存器的地址,方便IIC发送给寄存器数据初始化MPU6050。
  1. #ifndef __MPU6050_H
  2. #define __MPU6050_H
  3. #include "mpuiic.h"                                                                                                               
  4. #define MPU_AD0_CTRL                        PAout(15)       
  5. #define MPU_SELF_TESTX_REG                0X0D       
  6. #define MPU_SELF_TESTY_REG                0X0E       
  7. #define MPU_SELF_TESTZ_REG                0X0F       
  8. #define MPU_SELF_TESTA_REG                0X10       
  9. #define MPU_SAMPLE_RATE_REG                0X19       
  10. #define MPU_CFG_REG                                                0X1A       
  11. #define MPU_GYRO_CFG_REG                        0X1B       
  12. #define MPU_ACCEL_CFG_REG                        0X1C       
  13. #define MPU_MOTION_DET_REG                0X1F       
  14. #define MPU_FIFO_EN_REG                                0X23       
  15. #define MPU_I2CMST_CTRL_REG                0X24       
  16. #define MPU_I2CSLV0_ADDR_REG        0X25       
  17. #define MPU_I2CSLV0_REG                                0X26       
  18. #define MPU_I2CSLV0_CTRL_REG        0X27       
  19. #define MPU_I2CSLV1_ADDR_REG        0X28       
  20. #define MPU_I2CSLV1_REG                                0X29       
  21. #define MPU_I2CSLV1_CTRL_REG        0X2A       
  22. #define MPU_I2CSLV2_ADDR_REG        0X2B       
  23. #define MPU_I2CSLV2_REG                                0X2C       
  24. #define MPU_I2CSLV2_CTRL_REG        0X2D       
  25. #define MPU_I2CSLV3_ADDR_REG        0X2E       
  26. #define MPU_I2CSLV3_REG                                0X2F       
  27. #define MPU_I2CSLV3_CTRL_REG        0X30       
  28. #define MPU_I2CSLV4_ADDR_REG        0X31       
  29. #define MPU_I2CSLV4_REG                                0X32       
  30. #define MPU_I2CSLV4_DO_REG                0X33       
  31. #define MPU_I2CSLV4_CTRL_REG        0X34       
  32. #define MPU_I2CSLV4_DI_REG                0X35       
  33. #define MPU_I2CMST_STA_REG                0X36       
  34. #define MPU_INTBP_CFG_REG                        0X37       
  35. #define MPU_INT_EN_REG                                0X38       
  36. #define MPU_INT_STA_REG                                0X3A       
  37. #define MPU_ACCEL_XOUTH_REG                0X3B       
  38. #define MPU_ACCEL_XOUTL_REG                0X3C       
  39. #define MPU_ACCEL_YOUTH_REG                0X3D       
  40. #define MPU_ACCEL_YOUTL_REG                0X3E       
  41. #define MPU_ACCEL_ZOUTH_REG                0X3F       
  42. #define MPU_ACCEL_ZOUTL_REG                0X40       
  43. #define MPU_TEMP_OUTH_REG                        0X41       
  44. #define MPU_TEMP_OUTL_REG                        0X42       
  45. #define MPU_GYRO_XOUTH_REG                0X43       
  46. #define MPU_GYRO_XOUTL_REG                0X44       
  47. #define MPU_GYRO_YOUTH_REG                0X45       
  48. #define MPU_GYRO_YOUTL_REG                0X46       
  49. #define MPU_GYRO_ZOUTH_REG                0X47       
  50. #define MPU_GYRO_ZOUTL_REG                0X48       
  51. #define MPU_I2CSLV0_DO_REG                0X63       
  52. #define MPU_I2CSLV1_DO_REG                0X64       
  53. #define MPU_I2CSLV2_DO_REG                0X65       
  54. #define MPU_I2CSLV3_DO_REG                0X66       
  55. #define MPU_I2CMST_DELAY_REG        0X67       
  56. #define MPU_SIGPATH_RST_REG                0X68       
  57. #define MPU_MDETECT_CTRL_REG        0X69       
  58. #define MPU_USER_CTRL_REG                        0X6A       
  59. #define MPU_PWR_MGMT1_REG                        0X6B       
  60. #define MPU_PWR_MGMT2_REG                        0X6C       
  61. #define MPU_FIFO_CNTH_REG                        0X72       
  62. #define MPU_FIFO_CNTL_REG                        0X73       
  63. #define MPU_FIFO_RW_REG                                0X74       
  64. #define MPU_DEVICE_ID_REG                        0X75       
  65. #define MPU_ADDR                                                        0X68
  66. u8 MPU_Init(void);                                                                                                                        
  67. u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf);
  68. u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf);
  69. u8 MPU_Write_Byte(u8 reg,u8 data);                                                       
  70. u8 MPU_Read_Byte(u8 reg);                                                                                               
  71. u8 MPU_Set_Gyro_Fsr(u8 fsr);
  72. u8 MPU_Set_Accel_Fsr(u8 fsr);
  73. u8 MPU_Set_LPF(u16 lpf);
  74. u8 MPU_Set_Rate(u16 rate);
  75. u8 MPU_Set_Fifo(u8 sens);
  76. short MPU_Get_Temperature(void);
  77. u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz);
  78. u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az);
  79. #endif
  80. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  81. MPU6050.c
  82. 主要是单片机通过IIC协议向MPU6050写数据读数据的函数以及MPU6050初始化函数
  83. #include "mpu6050.h"
  84. #include "sys.h"
  85. #include "delay.h"
  86. #include "usart.h"   
  87. u8 MPU_Init(void)
  88. {
  89.         u8 res;
  90.   
  91.         GPIO_InitTypeDef  GPIO_InitStructure;
  92.        
  93.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);               
  94.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);       
  95.        
  96.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;                                          
  97.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                         
  98.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                  
  99.   GPIO_Init(GPIOA, &GPIO_InitStructure);                                             
  100.         GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
  101.        
  102.         MPU_AD0_CTRL=0;                       
  103.        
  104.         MPU_IIC_Init();                       
  105.         MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80);       
  106.   delay_ms(100);
  107.         MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00);       
  108.         MPU_Set_Gyro_Fsr(3);                                                                               
  109.         MPU_Set_Accel_Fsr(0);                                                                               
  110.         MPU_Set_Rate(50);                                                                                               
  111.         MPU_Write_Byte(MPU_INT_EN_REG,0X00);               
  112.         MPU_Write_Byte(MPU_USER_CTRL_REG,0X00);       
  113.         MPU_Write_Byte(MPU_FIFO_EN_REG,0X00);               
  114.         MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80);       
  115.        
  116.         res=MPU_Read_Byte(MPU_DEVICE_ID_REG);
  117.         if(res==MPU_ADDR)                                                                                               
  118.         {
  119.                 MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);               
  120.                 MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00);               
  121.                 MPU_Set_Rate(50);                                                                                                       
  122.         }else return 1;   
  123.         return 0;                                         
  124. }
  125. u8 MPU_Set_Gyro_Fsr(u8 fsr)
  126. {
  127.         return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);
  128. }
  129. u8 MPU_Set_Accel_Fsr(u8 fsr)
  130. {
  131.         return MPU_Write_Byte(MPU_ACCEL_CFG_REG,fsr<<3);
  132. }
  133. u8 MPU_Set_LPF(u16 lpf)
  134. {
  135.         u8 data=0;
  136.        
  137.         if(lpf>=188)data=1;
  138.         else if(lpf>=98)data=2;
  139.         else if(lpf>=42)data=3;
  140.         else if(lpf>=20)data=4;
  141.         else if(lpf>=10)data=5;
  142.         else data=6;
  143.         return MPU_Write_Byte(MPU_CFG_REG,data);
  144. }
  145. u8 MPU_Set_Rate(u16 rate)
  146. {
  147.         u8 data;
  148.         if(rate>1000)rate=1000;
  149.         if(rate<4)rate=4;
  150.         data=1000/rate-1;
  151.         data=MPU_Write_Byte(MPU_SAMPLE_RATE_REG,data);       
  152.         return MPU_Set_LPF(rate/2);                                                                                       
  153. }
  154. short MPU_Get_Temperature(void)
  155. {
  156.    u8 buf[2];
  157.    short raw;
  158.          float temp;
  159.        
  160.          MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf);
  161.    raw=((u16)buf[0]<<8)|buf[1];
  162.    temp=36.53+((double)raw)/340;
  163.    return temp*100;
  164. }
  165. u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz)
  166. {
  167.   u8 buf[6],res;
  168.        
  169.         res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf);
  170.         if(res==0)
  171.         {
  172.                 *gx=((u16)buf[0]<<8)|buf[1];
  173.                 *gy=((u16)buf[2]<<8)|buf[3];
  174.                 *gz=((u16)buf[4]<<8)|buf[5];
  175.         }        
  176.   return res;
  177. }
  178. u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
  179. {
  180.     u8 buf[6],res;  
  181.         res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);
  182.         if(res==0)
  183.         {
  184.                 *ax=((u16)buf[0]<<8)|buf[1];  
  185.                 *ay=((u16)buf[2]<<8)|buf[3];  
  186.                 *az=((u16)buf[4]<<8)|buf[5];
  187.         }        
  188.     return res;
  189. }
  190. u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
  191. {
  192.         u8 i;
  193.        
  194.         MPU_IIC_Start();
  195.         MPU_IIC_Send_Byte((addr<<1)|0);      
  196.         if(MPU_IIC_Wait_Ack())                                                         
  197.         {
  198.                 MPU_IIC_Stop();
  199.                 return 1;
  200.         }
  201.     MPU_IIC_Send_Byte(reg);                                                 
  202.     MPU_IIC_Wait_Ack();                             
  203.         for(i=0;i<len;i++)
  204.         {
  205.                 MPU_IIC_Send_Byte(buf[i]);               
  206.                 if(MPU_IIC_Wait_Ack())                        
  207.                 {
  208.                         MPU_IIC_Stop();
  209.                         return 1;
  210.                 }
  211.         }
  212.     MPU_IIC_Stop();
  213.         return 0;
  214. }
  215. u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
  216. {
  217.                 MPU_IIC_Start();
  218.                 MPU_IIC_Send_Byte((addr<<1)|0);               
  219.                 if(MPU_IIC_Wait_Ack())                                               
  220.                 {
  221.                         MPU_IIC_Stop();                 
  222.                         return 1;
  223.                 }
  224.     MPU_IIC_Send_Byte(reg);                                               
  225.     MPU_IIC_Wait_Ack();                                                               
  226.     MPU_IIC_Start();
  227.                 MPU_IIC_Send_Byte((addr<<1)|1);               
  228.     MPU_IIC_Wait_Ack();                                                               
  229.                 while(len)
  230.                 {
  231.                         if(len==1) *buf=MPU_IIC_Read_Byte(0);   
  232.                         else                          *buf=MPU_IIC_Read_Byte(1);               
  233.                         len--;
  234.                         buf++;
  235.                 }
  236.     MPU_IIC_Stop();       
  237.                 return 0;       
  238. }
  239. u8 MPU_Write_Byte(u8 reg,u8 data)
  240. {
  241.   MPU_IIC_Start();
  242.         MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);
  243.         if(MPU_IIC_Wait_Ack())                                                 
  244.         {
  245.                 MPU_IIC_Stop();
  246.                 return 1;
  247.         }
  248.   MPU_IIC_Send_Byte(reg);               
  249.   MPU_IIC_Wait_Ack();                               
  250.         MPU_IIC_Send_Byte(data);       
  251.         if(MPU_IIC_Wait_Ack())          
  252.         {
  253.                 MPU_IIC_Stop();
  254.                 return 1;
  255.         }
  256.   MPU_IIC_Stop();
  257.         return 0;
  258. }
  259. u8 MPU_Read_Byte(u8 reg)
  260. {
  261.         u8 res;
  262.        
  263.   MPU_IIC_Start();
  264.         MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);               
  265.         MPU_IIC_Wait_Ack();                                                                               
  266.   MPU_IIC_Send_Byte(reg);                                                               
  267.   MPU_IIC_Wait_Ack();                                                                               
  268.   MPU_IIC_Start();
  269.         MPU_IIC_Send_Byte((MPU_ADDR<<1)|1);               
  270.   MPU_IIC_Wait_Ack();                                                                               
  271.         res=MPU_IIC_Read_Byte(0);                                                       
  272.   MPU_IIC_Stop();                                                                                               
  273.         return res;               
  274. }
  275. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  276. mpuiic.h
  277. MPU的IIC协议函数头文件,PB11为SDA,PB10为SCL。
  278. #ifndef __MPUIIC_H
  279. #define __MPUIIC_H
  280. #include "sys.h"
  281. #define MPU_SDA_IN()  {GPIOB->CRH &= 0XFFFF0FFF;GPIOB->CRH |= 8<<12;}   
  282. #define MPU_SDA_OUT() {GPIOB->CRH &= 0XFFFF0FFF;GPIOB->CRH |= 3<<12;}               
  283. #define MPU_IIC_SCL    PBout(10)                
  284. #define MPU_IIC_SDA    PBout(11)                
  285. #define MPU_READ_SDA   PBin(11)                
  286. void MPU_IIC_Delay(void);                                                               
  287. void MPU_IIC_Init(void);               
  288. void MPU_IIC_Start(void);                                                               
  289. void MPU_IIC_Stop(void);                                                         
  290. void MPU_IIC_Send_Byte(u8 txd);                                       
  291. u8 MPU_IIC_Read_Byte(unsigned char ack);
  292. u8 MPU_IIC_Wait_Ack(void);                                                        
  293. void MPU_IIC_Ack(void);                                                                       
  294. void MPU_IIC_NAck(void);                                                               
  295. void IMPU_IC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
  296. u8 MPU_IIC_Read_One_Byte(u8 daddr,u8 addr);          
  297. #endif
  298. 1234567891011121314151617181920212223242526272829
  299. mpuiic.c
MPU的IIC协议函数编写
  1. #include "mpuiic.h"
  2. #include "delay.h"
  3. void MPU_IIC_Delay(void)
  4. {
  5.         delay_us(2);
  6. }
  7. void MPU_IIC_Init(void)
  8. {                                             
  9.   GPIO_InitTypeDef  GPIO_InitStructure;
  10.        
  11.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);                       
  12.                
  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;          
  14.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                                   
  15.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                  
  16.   GPIO_Init(GPIOB, &GPIO_InitStructure);                                                                                
  17.        
  18.   GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11);                                                  
  19. }
  20. void MPU_IIC_Start(void)
  21. {
  22.         MPU_SDA_OUT();     
  23.         MPU_IIC_SDA=1;                    
  24.         MPU_IIC_SCL=1;
  25.         MPU_IIC_Delay();
  26.         MPU_IIC_SDA=0;     
  27.         MPU_IIC_Delay();
  28.         MPU_IIC_SCL=0;                 
  29. }
  30. void MPU_IIC_Stop(void)
  31. {
  32.         MPU_SDA_OUT();                 
  33.         MPU_IIC_SCL=0;
  34.         MPU_IIC_SDA=0;                 
  35.         MPU_IIC_Delay();
  36.         MPU_IIC_SCL=1;
  37.         MPU_IIC_SDA=1;                 
  38.         MPU_IIC_Delay();                                                                  
  39. }
  40. u8 MPU_IIC_Wait_Ack(void)
  41. {
  42.         u8 ucErrTime=0;
  43.         MPU_SDA_IN();  
  44.         MPU_IIC_SDA=1;MPU_IIC_Delay();
  45.         MPU_IIC_SCL=1;MPU_IIC_Delay();
  46.         while(MPU_READ_SDA)
  47.         {
  48.                 ucErrTime++;
  49.                 if(ucErrTime>250)
  50.                 {
  51.                         MPU_IIC_Stop();
  52.                         return 1;
  53.                 }
  54.         }
  55.         MPU_IIC_SCL=0;
  56.         return 0;
  57. }
  58. void MPU_IIC_Ack(void)
  59. {
  60.         MPU_IIC_SCL=0;
  61.         MPU_SDA_OUT();
  62.         MPU_IIC_SDA=0;
  63.         MPU_IIC_Delay();
  64.         MPU_IIC_SCL=1;
  65.         MPU_IIC_Delay();
  66.         MPU_IIC_SCL=0;
  67. }
  68.    
  69. void MPU_IIC_NAck(void)
  70. {
  71.         MPU_IIC_SCL=0;
  72.         MPU_SDA_OUT();
  73.         MPU_IIC_SDA=1;
  74.         MPU_IIC_Delay();
  75.         MPU_IIC_SCL=1;
  76.         MPU_IIC_Delay();
  77.         MPU_IIC_SCL=0;
  78. }
  79. void MPU_IIC_Send_Byte(u8 txd)
  80. {                        
  81.     u8 t;   
  82.                 MPU_SDA_OUT();             
  83.     MPU_IIC_SCL=0;               
  84.     for(t=0;t<8;t++)
  85.     {              
  86.         MPU_IIC_SDA=(txd&0x80)>>7;
  87.         txd<<=1;           
  88.                     MPU_IIC_SCL=1;
  89.                     MPU_IIC_Delay();
  90.                     MPU_IIC_SCL=0;       
  91.                     MPU_IIC_Delay();
  92.     }         
  93. }             
  94. u8 MPU_IIC_Read_Byte(unsigned char ack)
  95. {
  96.         unsigned char i,receive=0;
  97.   MPU_SDA_IN();              
  98.     for(i=0;i<8;i++)
  99.           {
  100.         MPU_IIC_SCL=0;
  101.         MPU_IIC_Delay();
  102.                                 MPU_IIC_SCL=1;
  103.         receive<<=1;
  104.         if(MPU_READ_SDA)receive++;   
  105.                                 MPU_IIC_Delay();
  106.     }                                         
  107.     if (!ack)
  108.         MPU_IIC_NAck();   
  109.     else
  110.         MPU_IIC_Ack();   
  111.     return receive;
  112. }
  113. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
还有一些函数就不做过多赘述了,上面的代码备注已经做好了,认真吃肯定是会吃透的。多下点功夫肯定可以看懂。

6.学习补充
补充1:FIFO
FIFO( First Input First Output)简单说就是指先进先出。由于微电子技术的飞速发展,新一代FIFO芯片容量越来越大,体积越来越小,价格越来越便宜。作为一种新型大规模集成电路,FIFO芯片以其灵活、方便、高效的特性,逐渐在高速数据采集、高速数据处理、高速数据传输以及多机处理系统中得到越来越广泛的应用。在系统设计中,以增加数据传输率、处理大量数据流、匹配具有不同传输率的系统为目的而广泛使用FIFO存储器,从而提高了系统性能。FIFO存储器是一个先入先出的双口缓冲器,即第一个进入其内的数据第一个被移出,其中一个是存储器的输入口,另一个口是存储器的输出口。对于单片FIFO来说,主要有两种结构:触发导向结构和零导向传输结构。触发导向传输结构的FIFO是由寄存器阵列构成的,零导向传输结构的FIFO是由具有读和写地址指针的双口RAM构成。详见这篇博客:FIFO工作原理
补充2:关于PA15使用问题
在使用PA15作为普通IO口的时候,需要禁用JTAG才可以,代码如下:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);                GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);这是个大坑
补充3:关于MPU6050参考点
当代码烧入后,MPU的参考点是什么呢?参考点其实就是MPU6050初始化之后一开始的位置,没有一个强制的规定哪一个方向就是基准点,初始化之后的初始位置就是(0,0,0)点
补充4:想到了再写吧

7.效果展示(可以先来看这个)
PITCH(俯仰角)、ROLL(翻滚角)、YAW(偏航角),单位均为 度。TEMP为当前温度,单位为摄氏度。