天天看點

MPU6050/MPU6000中斷配置解決

MPU6050 / MPU6000配置中斷寄存器後INT電平一直不變(為高),解決辦法:

第一步:初始化子產品

//初始化MPU6050
//傳回值: 0,成功
//        其他,錯誤代碼
uint8_t MPU_Init(void)
{   
      uint8_t res;
      MCU6000_INT_Init()
      IIC_Init();                                       //初始化IIC總線
      MPU_Write_Byte(MPU6050_RA_PWR_MGMT_1,0X80);           //複位MPU6050
      delay_ms(100);
      MPU_Write_Byte(MPU6050_RA_PWR_MGMT_1,0X00);           //喚醒MPU6050
      MPU_Set_Gyro_Fsr(3);                              //陀螺儀傳感器,±2000dps
      MPU_Set_Accel_Fsr(0);                             //加速度傳感器 ±2g
      MPU_Set_Rate(200);                                //設定采樣率200-50HZ
      MPU_Write_Byte(MPU6050_RA_INT_ENABLE,0X00);              //關閉所有中斷
      MPU_Write_Byte(MPU6050_RA_USER_CTRL,0X00);           //I2C主模式關閉
      MPU_Write_Byte(MPU6050_RA_FIFO_EN,0X00);             //關閉FIFO
      MPU_Write_Byte(MPU6050_RA_INT_PIN_CFG,0X80);         //中斷的邏輯電平模式,設定為0,中斷信号為高電;設定為1,中斷信号為低電平時。
      res=MPU_Read_Byte(MPU6050_RA_WHO_AM_I);
      if(res==MPU_ADDR)                                 //器件ID正确
      {
            MPU_Write_Byte(MPU6050_RA_PWR_MGMT_1,0X02);     //設定CLKSEL,PLL X 軸為參考
            MPU_Write_Byte(MPU6050_RA_PWR_MGMT_2,0X00);     //加速度陀螺儀都工作
            MPU_Set_Rate(200);                          //設定采樣率為200-50HZ
      }else return 1;
      return 0;
}
           

第二部:設定中斷

void MPU_INT_Init(void)
{
//資料就緒中斷
//    MPU_Write_Byte(MPU6050_RA_CONFIG,0x06);         //配置外部引腳采樣和DLPF數字低通濾波器
//    MPU_Write_Byte(MPU6050_RA_INT_PIN_CFG,0X1C);    //INT引腳低電平平時
//    MPU_Write_Byte(MPU6050_RA_INT_ENABLE,0x01);     //中斷使能寄存器

  
//自由落體、運動、靜止中斷 三選一  
//    Free_Fall_Interrupt();                          //自由落體中斷
    Motion_Interrupt();                               //運動中斷
//    Zero_Motion_Interrupt();                        //靜止中斷
    MPU_Write_Byte(MPU6050_RA_CONFIG,0x04);           //配置外部引腳采樣和DLPF數字低通濾波器
    MPU_Write_Byte(MPU6050_RA_ACCEL_CONFIG,0x1C);     //加速度傳感器量程和高通濾波器配置
    MPU_Write_Byte(MPU6050_RA_INT_PIN_CFG,0X1C);      //INT引腳低電平平時
    MPU_Write_Byte(MPU6050_RA_INT_ENABLE,0x40);       //中斷使能寄存器
}

void Free_Fall_Interrupt(void)          //自由落體中斷
{
    MPU_Write_Byte(MPU6050_RA_FF_THR,0x01);             //自由落體門檻值 
    MPU_Write_Byte(MPU6050_RA_FF_DUR,0x01);             //自由落體檢測時間20ms 機關1ms 寄存器0X20
}
void Motion_Interrupt(void)             //運動中斷
{
    MPU_Write_Byte(MPU6050_RA_MOT_THR,0x01);            //運動門檻值 
    MPU_Write_Byte(MPU6050_RA_MOT_DUR,0x14);            //檢測時間20ms 機關1ms 寄存器0X20
}
void Zero_Motion_Interrupt(void)        //靜止中斷
{
    MPU_Write_Byte(MPU6050_RA_ZRMOT_THR,0x20);          //靜止門檻值 
    MPU_Write_Byte(MPU6050_RA_ZRMOT_DUR,0x20);          //靜止檢測時間20ms 機關1ms 寄存器0X20
}
           

應用層調用代碼:

MPU_Init();
    MPU_INT_Init();
           

進入低功耗:

MPU_Set_Low_power();
           

中斷配置關鍵位置:

MPU_Write_Byte(MPU6050_RA_CONFIG,0×04); //配置外部引腳采樣和DLPF數字低通濾波器

資料就緒中斷使能中斷配置MPU_Write_Byte(MPU6050_RA_CONFIG,0x06); //此次我開啟加速度與陀螺儀

運動檢測中斷配置MPU_Write_Byte(MPU6050_RA_CONFIG,0x04); //開啟加速度

/ *配置外部引腳采樣和DLPF數字低通濾波器* /

#define MPU6050_RA_CONFIG 0x1A

// bit5-bit3一個連接配接到FSYNC端口的外部信号可以通過配置EXT_SYNC_SET來采樣

//也就是說,這裡設定之後,FSYNC的電平0或1進入最終資料

寄存器,具體如下// 0不使用 

// 1 FSYNC電平進入所有資料 

寄存器

// 2 FSYNC電平進入GYRO_XOUT_L  // 3 FSYNC電平進入GYRO_YOUT_L

// 4 FSYNC電平進入GYRO_ZOUT_L 

// 5 FSYNC電平進入ACCEL_XOUT_L 

// 6 FSYNC電平進入ACCEL_YOUT_L

// 7 FSYNC電平進入SYNC_ACCEL_ZOUT_L

// bit2-bit0數字低通濾波器用于濾除高頻幹擾高于這個頻率的幹擾被濾除掉

/ *對應關系如下

 * * | 加速度傳感器| 陀螺儀

 * * DLPF_CFG | 帶寬| 延遲| 帶寬| 延遲| 采樣率

 * ------------- + -------- + ------- + -------- + ------ + - -----------

 * 0 | 260Hz | 0ms | 256Hz | 0.98ms | 8kHz

 * 1 | 184Hz | 2.0ms | 188Hz | 1.9ms | 1kHz

 * 2 | 94Hz | 3.0ms | 98Hz | 2.8ms | 1kHz

 * 3 | 44Hz | 4.9ms | 42Hz | 4.8ms | 1kHz

 * 4 | 21Hz | 8.5ms | 20Hz | 8.3ms | 1kHz

 * 5 | 10Hz | 13.8ms | 10Hz | 13.4ms | 1kHz

 * 6 | 5Hz | 19.0ms | 5Hz | 18.6ms | 1kHz

 * 7 | 保留| 保留| 保留

 * * /

其他代碼:

//設定MPU6050陀螺儀傳感器滿量程範圍
//fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
//傳回值:0,設定成功
//    其他,設定失敗 
uint8_t MPU_Set_Gyro_Fsr(uint8_t fsr)
{
      return MPU_Write_Byte(MPU6050_RA_GYRO_CONFIG,fsr<<3);   //設定陀螺儀滿量程範圍
}

//設定MPU6050加速度傳感器滿量程範圍
//fsr:0,±2g;1,±4g;2,±8g;3,±16g
//傳回值:0,設定成功
//    其他,設定失敗 
uint8_t MPU_Set_Accel_Fsr(uint8_t fsr)
{
      return MPU_Write_Byte(MPU6050_RA_ACCEL_CONFIG,fsr<<3);  //設定加速度傳感器滿量程範圍
}

//設定MPU6050的數字低通濾波器
//lpf:數字低通濾波頻率(Hz)
//傳回值:0,設定成功
//    其他,設定失敗 
uint8_t MPU_Set_LPF(uint16_t lpf)
{
      uint8_t data=0;
      if(lpf>=188) data=1;
      else if(lpf>=98) data=2;
      else if(lpf>=42) data=2;
      else if(lpf>=42) data=3;
      else if(lpf>=20) data=4;
      else if(lpf>=10) data=5;
      else data=6; 
      return MPU_Write_Byte(MPU6050_RA_CONFIG,data);          //設定數字低通濾波器  
}

//設定MPU6050的采樣率(假定Fs=1KHz)
//rate:4~1000(Hz)
//傳回值:0,設定成功
//    其他,設定失敗 
uint8_t MPU_Set_Rate(uint16_t rate)
{
      uint8_t data;
      if(rate>1000)rate=1000;
      if(rate<4)rate=4;
      data=1000/rate-1;
      data=MPU_Write_Byte(MPU6050_RA_SMPLRT_DIV,data);    //設定數字低通濾波器
      return MPU_Set_LPF(rate/2);	                //自動設定LPF為采樣率的一半
}

//IIC寫一個位元組 
//reg:		寄存器位址
//data:		資料
//傳回值:	0,正常
//    		其他,錯誤代碼
uint8_t MPU_Write_Byte(uint8_t reg,uint8_t data)
{
      IIC_Start();
      IIC_Send_Byte((MPU_ADDR<<1)|0);//發送器件位址+寫指令	
      if(IIC_Wait_Ack())	//等待應答
      {
            IIC_Stop();	
            return 1;		
      }
      IIC_Send_Byte(reg);	//寫寄存器位址
      IIC_Wait_Ack();		//等待應答 
      IIC_Send_Byte(data);//發送資料
      if(IIC_Wait_Ack())	//等待ACK
      {
            IIC_Stop();	 
            return 1;		 
      }		 
      IIC_Stop();	 
      return 0;
}

//IIC讀一個位元組 
//reg:寄存器位址 
//傳回值:讀到的資料

uint8_t MPU_Read_Byte(uint8_t reg)
{
      uint8_t res;
      IIC_Start();
      IIC_Send_Byte((MPU_ADDR<<1)|0);//發送器件位址+寫指令	
      IIC_Wait_Ack();//等待應答
      IIC_Send_Byte(reg);//寫寄存器位址
      IIC_Wait_Ack();//等待應答
      IIC_Start();
      IIC_Send_Byte((MPU_ADDR<<1)|1);//發送期間位址+讀指令
      IIC_Wait_Ack();//等待應答
      res=IIC_Read_Byte(0);//讀取資料,發送nACK
      IIC_Stop();//産生一個停止條件
      return res;
}

//IIC連續寫
//addr:器件位址
//reg: 寄存器位址
//len: 寫入長度
//buf: 資料區
//傳回值: 0,正常
//  			其他,錯誤代碼
uint8_t MPU_Write_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf)
{
      uint8_t i;
      IIC_Start();
      IIC_Send_Byte((addr<<1)|0);//發送器件位址+寫指令
      if(IIC_Wait_Ack())//等待應答
      {
            IIC_Stop();
            return 1;
      }
      IIC_Send_Byte(reg);//寫寄存器位址
      IIC_Wait_Ack();//等待應答
      for(i=0;i<len;i++)
      {
            IIC_Send_Byte(buf[i]);//發送資料
            if(IIC_Wait_Ack())//等待ACK
            {
                  IIC_Stop();
                  return 1;
            }
      }
      IIC_Stop();
      return 0;
}
//IIC連續讀
//addr:器件位址
//reg:要讀取的寄存器位址
//len:要讀取得長度
//buf:讀取到的資料存儲區
//傳回值: 0,正常
//				其他,錯誤代碼
uint8_t MPU_Read_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf)
{
      IIC_Start();
      IIC_Send_Byte((addr<<1)|0);//發送器件位址+寫指令
      if(IIC_Wait_Ack())//等待應答
      {
            IIC_Stop();
            return 1;
      }
      IIC_Send_Byte(reg);//寫寄存器位址
      IIC_Wait_Ack();//等待應答
      IIC_Start();
      IIC_Send_Byte((addr<<1)|1);//發送器件位址+讀指令
      IIC_Wait_Ack();//等待應答
      while(len)
      {
            if(len==1) *buf=IIC_Read_Byte(0);//讀資料,發送nACK
            else *buf=IIC_Read_Byte(1);//讀資料,發送ACK
            len--;
            buf++;
      }
      IIC_Stop();//産生一個停止條件
      return 0;
}


//得到溫度值
//傳回值:溫度值(擴大了100倍)
short MPU_Get_Temperature(void)
{
      uint8_t buf[2]; 
      short raw;
      float temp;
      MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf); 
      raw=((uint16_t)buf[0]<<8)|buf[1];  
      temp=36.53+((double)raw)/340;  
      return temp*100;
}

//得到陀螺儀值(原始值)
//gx,gy,gz:陀螺儀x,y,z軸的原始讀數(帶符号)
//傳回值:0,成功
//    其他,錯誤代碼
uint8_t MPU_Get_Gyroscope(short *gx,short *gy,short *gz)
{
      uint8_t buf[6],res;
      res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf);
      if(res==0)
      {
            *gx=((uint16_t)buf[0]<<8)|buf[1];  
            *gy=((uint16_t)buf[2]<<8)|buf[3];  
            *gz=((uint16_t)buf[4]<<8)|buf[5];
      } 	
      return res;
}

//得到加速度值(原始值)
//ax,ay,az:陀螺儀x,y,z軸的原始讀數(帶符号)
//傳回值:0,成功
//    其他,錯誤代碼
uint8_t MPU_Get_Accelerometer(short *ax,short *ay,short *az)
{
      uint8_t buf[6],res;  
      res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);
      if(res==0)
      {
            *ax=((uint16_t)buf[0]<<8)|buf[1];  
            *ay=((uint16_t)buf[2]<<8)|buf[3];  
            *az=((uint16_t)buf[4]<<8)|buf[5];
      } 	
      return res;;
}
           

繼續閱讀