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