在使用MPU6050时遇到的令人头疼的问题
1.整个程序在一开始运行就卡死在启动文件
首先看一下,Target设置选项下的Use MicroLIB选项是不是选上勾了。 如果这个设置也解决不了问题,那么你需要检查一下程序里,是否写了printf函数的接口函数。因为MPU6050里面有 用到了这个函数,如果你没写这个函数的接口函数,就会导致系统卡死在系统文件里。 printf函数的接口函数
int fputc(int ch, FILE *f)
{
USART_SendData(DEBUG_USARTx, (uint8_t) ch);
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
return (ch);
}
2.while循环里的条件明明不满足了,程序却一致卡死在此循环里
检查一下,判断条件里的变量的类型是否正确。另外,如果这个变量在中断服务函数里面需要改变值,那么在定义这个变量的语句前应该加上关键字 volatile volatile的具体描述参考
3.MPU6050在执行mpu_dmp_init()函数时,一直出现错误,且错误在run_self_test()
1)首先,看一下是不是因为你在程序初始化的时候,没有把MPU6050水平放置,至于为什么要水平放置呢? 因为在run_self_test()函数里面有一个mpu_run_self_test(gyro, accel)函数,这个函数上面有一个注释特别重要:
This function must be called with the device either face-up or face-down
* (z-axis is parallel to gravity).此函数必须在设备面朝上或面朝下时调用(z轴与重力平行)
2)如果照着1)的方法还是解决不了这个问题,那么请你检查一下run_self_test函数里面的具体内容是否和下面的一模一样:
u8 run_self_test(void)
{
int result;
long gyro[3], accel[3];
result = mpu_run_self_test(gyro, accel);
if (result == 0x3)
{
float sens;
unsigned short accel_sens;
mpu_get_gyro_sens(&sens);
gyro[0] = (long)(gyro[0] * sens);
gyro[1] = (long)(gyro[1] * sens);
gyro[2] = (long)(gyro[2] * sens);
dmp_set_gyro_bias(gyro);
mpu_get_accel_sens(&accel_sens);
accel[0] *= accel_sens;
accel[1] *= accel_sens;
accel[2] *= accel_sens;
dmp_set_accel_bias(accel);
return 0;
}else return 1;
}
4.mpu_dmp_get_data(&pitch,&roll,&yaw)函数的返回值不正确(一直不是0)
MPU6050读不出来数据 如果参考以上这篇文章还是无法帮助解决问题,那么不妨试一下,把模拟iic的这部分代码换一下,也许可能就是因为iic这部分程序不正确。 模拟IIC的代码:
#include "mpuiic.h"
#include "./systick/bsp_SysTick.h"
#define Soft_I2C_SDA GPIO_Pin_3
#define Soft_I2C_SCL GPIO_Pin_4
#define Soft_I2C_PORT GPIOB
#define MPU6050_GPIO_CLK RCC_APB2Periph_GPIOB
#define MPU_SDA_IN() {Soft_I2C_PORT ->CRL &= 0XFFFF0FFF;Soft_I2C_PORT ->CRL |= 8<<12;}
#define MPU_SDA_OUT() {Soft_I2C_PORT ->CRL &= 0XFFFF0FFF;Soft_I2C_PORT ->CRL |= 7<<12;}
#if 1
#define MPU6050_I2C_SCL_1() GPIO_SetBits(Soft_I2C_PORT, Soft_I2C_SCL)
#define MPU6050_I2C_SCL_0() GPIO_ResetBits(Soft_I2C_PORT, Soft_I2C_SCL)
#define MPU6050_I2C_SDA_1() GPIO_SetBits(Soft_I2C_PORT, Soft_I2C_SDA)
#define MPU6050_I2C_SDA_0() GPIO_ResetBits(Soft_I2C_PORT, Soft_I2C_SDA)
#define MPU6050_I2C_SDA_READ() GPIO_ReadInputDataBit(Soft_I2C_PORT, Soft_I2C_SDA)
#else
#define MPU6050_I2C_SCL_1() Soft_I2C_PORT->BSRR = Soft_I2C_SCL
#define MPU6050_I2C_SCL_0() Soft_I2C_PORT->BRR = Soft_I2C_SCL
#define MPU6050_I2C_SDA_1() Soft_I2C_PORT->BSRR = Soft_I2C_SDA
#define MPU6050_I2C_SDA_0() Soft_I2C_PORT->BRR = Soft_I2C_SDA
#define MPU6050_I2C_SDA_READ() ((Soft_I2C_PORT->IDR & Soft_I2C_SDA) != 0)
#endif
void MPU_IIC_Delay(void)
{
uint8_t i;
for (i = 0; i < 100; i++);
}
void MPU_IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(MPU6050_GPIO_CLK|RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
GPIO_InitStructure.GPIO_Pin = Soft_I2C_SCL|Soft_I2C_SDA;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(Soft_I2C_PORT , &GPIO_InitStructure);
GPIO_SetBits(Soft_I2C_PORT,Soft_I2C_SCL|Soft_I2C_SDA);
}
void MPU_IIC_Start(void)
{
MPU_SDA_OUT();
MPU6050_I2C_SDA_1();
MPU6050_I2C_SCL_1();
MPU_IIC_Delay();
MPU6050_I2C_SDA_0();
MPU_IIC_Delay();
MPU6050_I2C_SCL_0();
}
void MPU_IIC_Stop(void)
{
MPU_SDA_OUT();
MPU6050_I2C_SCL_0();
MPU6050_I2C_SDA_0();
MPU_IIC_Delay();
MPU6050_I2C_SCL_1();
MPU6050_I2C_SDA_1();
MPU_IIC_Delay();
}
u8 MPU_IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
MPU_SDA_IN();
MPU6050_I2C_SDA_1();MPU_IIC_Delay();
MPU6050_I2C_SCL_1();MPU_IIC_Delay();
while(MPU6050_I2C_SDA_READ())
{
ucErrTime++;
if(ucErrTime>250)
{
MPU_IIC_Stop();
return 1;
}
}
MPU6050_I2C_SCL_0();
return 0;
}
void MPU_IIC_Ack(void)
{
MPU6050_I2C_SCL_0();
MPU_SDA_OUT();
MPU6050_I2C_SDA_0();
MPU_IIC_Delay();
MPU6050_I2C_SCL_1();
MPU_IIC_Delay();
MPU6050_I2C_SCL_0();
}
void MPU_IIC_NAck(void)
{
MPU6050_I2C_SCL_0();
MPU_SDA_OUT();
MPU6050_I2C_SDA_1();
MPU_IIC_Delay();
MPU6050_I2C_SCL_1();
MPU_IIC_Delay();
MPU6050_I2C_SCL_0();
}
void MPU_IIC_Send_Byte(u8 _ucByte)
{
uint8_t i;
MPU_SDA_OUT();
MPU6050_I2C_SCL_0();
for (i = 0; i < 8; i++)
{
if (_ucByte & 0x80)
{
MPU6050_I2C_SDA_1();
}
else
{
MPU6050_I2C_SDA_0();
}
_ucByte <<= 1;
MPU6050_I2C_SCL_1();
MPU_IIC_Delay();
MPU6050_I2C_SCL_0();
MPU_IIC_Delay();
}
}
u8 MPU_IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
MPU_SDA_IN();
for(i=0;i<8;i++ )
{
MPU6050_I2C_SCL_0();
MPU_IIC_Delay();
MPU6050_I2C_SCL_1();
receive<<=1;
if(MPU6050_I2C_SDA_READ())receive++;
MPU_IIC_Delay();
}
if (!ack)
MPU_IIC_NAck();
else
MPU_IIC_Ack();
return receive;
}
5.读取的数据成功率低(也就是说读取10次,mpu_dmp_get_data有5次都返回1,而不是0)
可能是 MPU_IIC_Delay()这个函数取值不恰当,可以调整一下看看效果。
6.容易忽视的小问题,却恰恰最致命
例如:
STM32的PB3、PB4,分别是JTAG的JTDO和NJTRST引脚,在没关闭JTAG功能之前,在程序中是配置不了这些引脚的功能的。要配置这些引脚,首先要开启AFIO时钟,然后在AFIO的设置中,释放这些引脚。具体看STM32的参考手册中有关AFIO的部分。
RCC_APB2PeriphClockCmd(MPU6050_GPIO_CLK|RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
STM32——GPIO重映射(GPIO_PinRemapConfig)
|