MPU6050驱动及如何读取参数值


  想到2017年的全国大学生电子竞技大赛,因为一款加速度传感器(MPU6050)而忙的焦头烂额;虽然那个时候真的很累,但是感觉还不错的样子,认识了很多很多的人,也包括那个只会挠头的傻子,一天都没个正行。哪一年,让我学到了很多,而我自己也没有想到会因此走上这条路,现在想想感觉就是如梦一般,可惜的是,这个梦好像醒不过来了。

  到现在我依然记得哪年我做的那道题,检测不透明管道内小球的运动状态和个数(题号忘了),管道我们采用的是PVB管,小球则是铁球;

  1、关于检测小球方向和个数我们用的是电涡流传感器(常闭)

  1.1 原理:当铁球经过传感器的范围时,传感器会产生一个脉冲,通过对该脉冲进行计数,即可得到通过管道的小球个数

    但是,当时我们没有考虑到时间的概念,以至于在比赛调试时,出现计数不准确,现象为:多个小球排列通过(小球之间没有间隔)

    2、关于测量管道和水平面的角度问题

  1.1 传感器开始准备使用的是MPU6050,不过到最后却使用的是MMA7455(数字输出三轴加速度传感器),到比赛前一天一切测试都ok,没有想到的是,到比赛现场之后却出现了诸多意外,顿时自己的心就慌了,完全平复不下来,那是我第二次真的感觉手足无措。

 

  3、编写IIC时序:(只对STC89C51/C52有效)

  •   IIC起始时序

  SCL高电平期间,SDA有高到低的跳变

1 void I2C_Start()
2 {
3     SDA = 1;                    //拉高数据线
4     SCL = 1;                    //拉高时钟线
5     Delay5us();                 //延时
6     SDA = 0;                    //产生下降沿
7     Delay5us();                 //延时
8     SCL = 0;                    //拉低时钟线
9 }
  •       IIC停止时序

  SCL在高电平期间,SDA有低到高的跳变

1 void I2C_Stop()
2 {
3     SDA = 0;                    //拉低数据线
4     SCL = 1;                    //拉高时钟线
5     Delay5us();                 //延时
6     SDA = 1;                    //产生上升沿
7     Delay5us();                 //延时
8 }
  •       IIC发送应答

  应答:SCL高电平期间,SDA为低电平

  不应答:SCL高电平期间,SDA为高电平

1 void I2C_SendACK(bit ack)
2 {
3     SDA = ack;                  //写应答信号
4     SCL = 1;                    //拉高时钟线
5     Delay5us();                 //延时
6     SCL = 0;                    //拉低时钟线
7     Delay5us();                 //延时
8 }
  •        IIC接收应答
1 bit I2C_RecvACK()
2 {
3     SCL = 1;                    //拉高时钟线
4     Delay5us();                 //延时
5     CY = SDA;                   //读应答信号
6     SCL = 0;                    //拉低时钟线
7     Delay5us();                 //延时
8     return CY;
9 }
  •         IIC写一个字节(发送)
 1 void I2C_SendByte(uchar dat)
 2 {
 3     uchar i;
 4     for (i=0; i<8; i++)         //8位计数器
 5     {
 6         dat <<= 1;              //移出数据的最高位
 7         SDA = CY;               //送数据口
 8         SCL = 1;                //拉高时钟线
 9         Delay5us();             //延时
10         SCL = 0;                //拉低时钟线
11         Delay5us();             //延时
12     }
13     I2C_RecvACK();
14 }
  •        IIC读一个字节(接收)
 1 uchar I2C_RecvByte()
 2 {
 3     uchar i;
 4     uchar dat = 0;
 5     SDA = 1;                    //使能内部上拉,准备读取数据,
 6     for (i=0; i<8; i++)         //8位计数器
 7     {
 8         dat <<= 1;
 9         SCL = 1;                //拉高时钟线
10         Delay5us();             //延时
11         dat |= SDA;             //读数据               
12         SCL = 0;                //拉低时钟线
13         Delay5us();             //延时
14     }
15     return dat;
16 }

 

  4、 对传感器(MPU6050)读写时序

  在读写之前先设置AD0的电平,此关系IIC的设备地址

  AD0=0;b11010000   0xD0(IIC设备地址)

  AD0=1;b11010001   0xD1(IIC设备地址)

  时序中符号说明:

  

 

  4.1 read:

  4.1.1  单字节读

  

 1 uchar Single_ReadI2C(uchar REG_Address)
 2 {
 3     uchar REG_data;
 4     I2C_Start();                 
 5     I2C_SendByte(SlaveAddress);    //设备地址+写
 6     I2C_SendByte(REG_Address);   
 7     I2C_Start();                
 8     I2C_SendByte(SlaveAddress+1);  //设备地址+读
 9     REG_data=I2C_RecvByte();     
10     I2C_SendACK(1);                //接收应答
11     I2C_Stop();                   
12     return REG_data;
13 }

  4.1.2 多字节读:

 1 //函数名: MMA8451_Multiple_Read
 2 //函数功能: 从传感器设备读多个字节
 3 //参数: REG_Address -- 寄存器地址  
 4 //        num -- 要读的字节数
 5 //        *data_buf -- 存放读回数据的缓冲区
 6 //返回值: 无
 7 void MPU6050_Multiple_Read(unsigned char REG_Address, unsigned char num, unsigned char *data_buf)   
 8 {   
 9     unsigned char i;
10     num += 1;
11     I2C_Start();  
12     I2C_SendByte(SlaveAddress);     //设备地址 
13     I2C_SendByte(REG_Address);    
14     I2C_Start();                      //SR
15     I2C_SendByte(SlaveAddress+1);     //设备地址 + read 方向
16     for(i=0;i<num-1;i++)
17     {
18         *(data_buf+i) = I2C_RecvByte();    
19         if(i == num-1)
20             I2C_SendACK(1);
21         else
22             I2C_SendACK(0);
23     }
24     I2C_Stop();
25 } 

 

  4.2 write:

  4.2.1  单字节写:

  

1 void Single_WriteI2C(uchar REG_Address,uchar REG_data)
2 {
3     I2C_Start();                 
4     I2C_SendByte(SlaveAddress);   //设备地址+写
5     I2C_SendByte(REG_Address);    //寄存器地址,
6     I2C_SendByte(REG_data);      
7     I2C_Stop();                  
8 }

 

  4、MPU6050初始化

寄存器 PWR_MGMT_1(read/write)

  

  说明:该寄存器允许用户配置电源模式和时钟源。它还提供了用于重置整个设备的位,以及用于禁用温度传感器的位。

  CYCLE:  休眠/唤醒

  CYCLE=0; 唤醒

  CYCLE=1; 休眠

 

寄存器 SMPRT_DIV(read/write)

  

  采样速率由陀螺仪输出速率除以SMPLRT_DIV得到:  

          Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)
  当DLPF被禁用时陀螺仪输出速率为8kHz (DLPF_CFG = 0或7),当DLPF被启用时陀螺仪输出速率为1kHz(见寄存器26)。

  注:加速度计输出速率为1kHz。这意味着对于大于1kHz的采样率,相同的加速度计采样可能不止一次地输出到FIFO、DMP和传感器寄存器。

  SMPLRT_DIV:8位无符号值。采样速率是由陀螺仪输出速率除以这个值决定的。

 

寄存器CONFIG(read/write)

  

说明:

   该寄存器为陀螺仪和加速度计配置外部帧同步(FSYNC) pin采样和数字低通滤波器(DLPF)设置。

  可以通过配置EXT_SYNC_SET对连接到FSYNC pin的外部信号进行采样。  

   对FSYNC引脚的信号更改被锁定,以便可以捕获短频闪。锁定的FSYNC信号将按照寄存器25中定义的采样速率进行采样。采样后,锁存器复位到当前FSYNC信号状态。

   在传感器数据寄存器中,根据下表EXT_SYNC_SET的值确定的最小有效位将被报告为采样值。

   

DLPF由DLPF_CFG配置。加速度计和陀螺仪根据DLPF_CFG的值进行滤波,如下表所示。

   

  保留位:6、7

 参数:

 EXT_SYNC_SET: 3-bit无符号值。配置FSYNC采样。

 DLPF:3-bit无符号值。配置DLPF设置。

  

  

  


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM