记录关于使用MPU6050遇到的各种问题


注意:我的代码基于正点原子官方提供的MPU6050实验代码,使用到了dmp库求欧拉角。

一、问题一:MPU6050的初始化失败,不进入while循环

原因:MPU6050在上电初始化时需要自检,如果硬件是一个很倾斜的状态,就导致卡住,必须保证平放,或者不乱晃动。

二、问题二:MPU6050需要接AD0引脚吗?

答:AD0引脚如果接地,则硬件地址为0x68,如果接3V3,则地址为0x69,这里没必要接线,代码里面定义了地址为0x68,同时,在MPU6050的初始化函数里,也可以把关于AD0的引脚的初始化语句注释掉。

三、问题三:MPU6050供电接5V或者3V3可以吗?

答:我买的这个普遍版本都是可以两个都接的。

四、问题四:MPU6050的IIC通信是使用硬件IIC好还是软件IIC好?

答:只能说根据情况来看。对于 MPU6050 来说,硬件 IIC 具有更高的速度和更少的 CPU 占用率。软件 IIC 通信则需要更多的 CPU 时间和计算资源,但是硬件IIC网上说不稳定,容易出问题,这里我用软件IIC模拟更好,因为我要求的传输速度不高。如果需要更高速的传输,那就上硬件IIC。
这是硬件IIC的初始化函数:

void IIC_Init( u32 bound , u16 address )
{
    
    
	GPIO_InitTypeDef GPIO_InitStructure;
	I2C_InitTypeDef I2C_InitTSturcture;

	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE );
//	GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);
	RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C2, ENABLE );

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init( GPIOB, &GPIO_InitStructure );

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init( GPIOB, &GPIO_InitStructure );

	I2C_InitTSturcture.I2C_ClockSpeed = bound;
	I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;
	I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_16_9;
	I2C_InitTSturcture.I2C_OwnAddress1 = address;
	I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;
	I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init( I2C2, &I2C_InitTSturcture );
	I2C_Cmd( I2C2, ENABLE );
	I2C_AcknowledgeConfig( I2C2, ENABLE );
}

这是软件IIC的初始化函数:

//初始化IIC接口引脚
void IIC_Init(void)
{
    
    
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
    //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    //GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8|GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStructure);
    GPIO_SetBits(GPIOB,GPIO_Pin_7|GPIO_Pin_6);
}

硬件IIC方便的是可以调用现成的成员变量和库函数进行通信和读写操作,软件IIC方便的是可以自定义SCL和SDA引脚,用GPIO的高低电平模拟IIC效果,需要自己写start、stop、ack等函数,不过现在网上相关代码很容易找到。

五、问题五:一处建议修改的代码

源代码为:

  if(mpu_dmp_get_data(&Pitch, &Roll, &Yaw)==0){
    
    
     //xxxxxx
           }

现在改为:

  while(mpu_dmp_get_data(&Pitch, &Roll, &Yaw)!=0){
    
    

           }

这样修改后,可以有效防止新的数据进缓存区过快导致FIFO溢出,防止MPU6050出现卡死的情况。

六、问题六:一个十分玄学的问题:接线

问题说明:我正常上电,当MPU6050不晃动时,正常打印数据,但是一旦晃动过快,就会卡死。我首先就想到是线的问题,于是换了线,结果还是会出现这个问题。然后,我又怀疑是代码的问题,但是调试时也不会卡死在特定的某个程序,而是完全随机中断。之后,我把VCC、GND、SCL、SDA端口和杜邦线用热熔胶粘牢,还会有这个问题。很玄学。

解决方法:更加玄学。经过好几天的测试,发现居然跟杜邦线的长短有关系。我一直使用的是40cm长的杜邦线,总出问题。而当我换成20cm的短杜邦线时,居然没问题了!!!离谱的是,长杜邦线接SCL和SDA没问题,但是不能接VCC和GND,VCC和GND二者必须有至少一个要接短线才能正常运行不卡死。…

七、关于软件IIC的端口配置问题

代码如下:

//IO方向设置
#define SDA_IN() {
      
      GPIOB->CFGLR&=0X0FFFFFFF;GPIOB->CFGLR|=(u32)8<<28;}
#define SDA_OUT() {
      
      GPIOB->CFGLR&=0X0FFFFFFF;GPIOB->CFGLR|=(u32)3<<28;}

//IO操作函数
//#define IIC_SCL PBout(6)
//#define IIC_SDA PBout(7)
//#define READ_SDA PBin(9)

#define IIC_SCL_0 GPIO_ResetBits(GPIOB,GPIO_Pin_6)
#define IIC_SDA_0 GPIO_ResetBits(GPIOB,GPIO_Pin_7)
#define IIC_SCL_1 GPIO_SetBits(GPIOB,GPIO_Pin_6)
#define IIC_SDA_1 GPIO_SetBits(GPIOB,GPIO_Pin_7)


鉴于stm32的位带操作移植到其他平台是不太行的,所以要进行改写,改写形式如上。

猜你喜欢

转载自blog.csdn.net/qq_53092944/article/details/132240114
今日推荐