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;;
}

 

 

 

 

 

### MPU6050 INT引脚连接要求 对于MPU6050传感器而言,INT引脚用于向微控制器发送中断信号。该引脚通常设置为低电平触发中断,在数据准备好或其他特定事件发生时激活[^2]。 具体来说,当配置MPU6050作为I²C从设备工作时,其硬件地址由固定部分(高位7位)和通过AD0引脚设定的部分组成,默认情况下为0x68或0x69取决于AD0的状态。而INT引脚则可以根据应用需求灵活配置并连接到MCU相应的GPIO端口来接收中断通知[^4]。 ### 配置方法 为了使能这一功能,需按照以下方式操作: #### 初始化阶段 - **关闭全局中断**:某些实现会在初始化过程中先禁用所有可能产生的中断以防止意外触发。 ```c // 关闭中断 (仅作示意, 实际代码依赖于具体的库函数) HAL_NVIC_DisableIRQ(EXTI_Line); ``` #### 设置电源管理模式及时钟源 确保选择了合适的内部振荡器频率以便后续调整采样率。例如,将`PWR_MGMT_1`寄存器设为0x00可以选择8MHz的PLL时钟源[^5]。 ```c Wire.beginTransmission(MPU6050_ADDRESS); // 开始通信 Wire.write(PWR_MGMT_1_REG); // 指定目标寄存器 Wire.write(0x00); // 应用所需配置值 Wire.endTransmission(); // 结束本次写入过程 ``` #### 调整采样速率 根据实际应用场景的需求调节样本获取的速度。比如要达到每秒200次的数据更新,则应相应地修改`SMPLRT_DIV`寄存器中的数值至39(十六进制表示法下为0x27),从而使得最终的有效采样率为\( \frac{8\text{kHz}}{(39+1)}=200Hz\) . ```c Wire.beginTransmission(MPU6050_ADDRESS); Wire.write(SMPLRT_DIV_REG); Wire.write(0x27); // 设定分频系数 Wire.endTransmission(); ``` #### 启用指定类型的中断 最后一步便是开启希望监听的具体种类的中断条件。这里假设我们关注的是原始加速度计/陀螺仪读数可用的情况,那么就需要针对`INT_ENABLE`寄存器执行恰当的操作[^1]: ```c Wire.beginTransmission(MPU6050_ADDRESS); Wire.write(INT_ENABLE_REG); Wire.write(0x01); // RAW_RDY_EN bit enabled Wire.endTransmission(); ``` 以上步骤完成后,每当新的测量结果被记录下来之后,INT引脚就会自动切换成逻辑'0',直到主机读取完毕为止;期间如果再次满足触发条件的话还会继续翻转状态直至清除标志位。
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值