Lancer_zhang 发表于 2019-7-30 16:43:17

调试mpu9250出现无法配置寄存器的问题

这两天一直在调mpu9250,用的就是这个模块如图:
采用模拟iic读取加速度+陀螺仪+磁力计数据,发现无法写集成的MPU6050的寄存器,具体描述如下:
问题的发现:
一开始我以为我已经读到加速度和陀螺仪的数据,但由于一直读不到ak8963的id,没办法读取磁力计的数据,我就试着改了一下waitack的代码,然后就能读到磁力计的数据了。
接着,我就发现我原先读到的加速度值不对,因为默认的加速度量程时2G,而我设置的是16G,不知道是我重新上电了还是什么的,又读不到磁力计的数值了。
这时我才发现,原先我一直就没能写加速度config的寄存器。

现象描述:
1、软件iic是我之前写icm20609的代码,直接porting过来的,初始化函数也是porting原来的,没有变过,icm20609也一直读取的很稳定。
2、我可以读取芯片ID,能够读到默认量程的加速度值和陀螺仪的值。
贴一下代码:
/**
* \brief MPU6050 write single byte
*
* \param address,value
*
* \return 1:write success or 0:write fail
*/
u8 MPU9250_WriteReg(u8 device, u8 address, u8 Value)
{
    i2c_Start();
    i2c_SendByte(device | I2C_WR);
    if (i2c_WaitAck() != 1)
    {
      goto writesingle_fail;
    }
    i2c_SendByte(address);
    if (i2c_WaitAck() != 1)
    {
      goto writesingle_fail;
    }
    i2c_SendByte(Value);
    if (i2c_WaitAck() != 1)
    {
      goto writesingle_fail;
    }
    i2c_Stop();
    return 1;

writesingle_fail:
    i2c_Stop();
    return 0;
}

/**
* \brief iam20609 read single byte
*
* \param address,value
*
* \return 1:read success or 0:read fail
*/
u8 MPU9250_ReadReg(u8 device, u8 address, u8 * value)
{
    i2c_Start();
    i2c_SendByte(device | I2C_WR);
    if (i2c_WaitAck() != 0)
    {
      goto readsingle_fail;
    }
    i2c_SendByte(address);
    if (i2c_WaitAck() != 0)
    {
      goto readsingle_fail;
    }
    i2c_Start();
    i2c_SendByte(device | I2C_RD);

    if (i2c_WaitAck() != 0)
    {
      goto readsingle_fail;
    }
    *value = i2c_ReadByte();
    i2c_NAck();
    i2c_Stop();
    return 1;

readsingle_fail:
    i2c_Stop();
    return 0;
}

/**
* \brief iam20609 readbytes
*
* \param address,rxbuff,num
*
* \return 1:read success or 0:read fail
*/
u8 MPU9250_ReadData(u8 device, u8 address, u8 * rxBuff, u8 num)
{
    u8 i = 0;
    i2c_Start();
    i2c_SendByte(device | I2C_WR);
    if (i2c_WaitAck() != 0)
    {
      goto readdata_fail;
    }
    i2c_SendByte(address);
    if (i2c_WaitAck() != 0)
    {
      goto readdata_fail;
    }
    i2c_Start();
    i2c_SendByte(device | I2C_RD);
    if (i2c_WaitAck() != 0)
    {
      goto readdata_fail;
    }
    for(i=0; i<(num); i++)
    {
                *rxBuff = i2c_ReadByte();
      if (i != (num - 1))
      {
            i2c_Ack();
      }
      else
      {
            i2c_NAck();
      }
                rxBuff++;
        }

    i2c_Stop();
    return 1;

readdata_fail:
    i2c_Stop();
    return 0;
}

/**
* \brief iam20609_readid
*
* \param none
*
* \return none
*/
void MPU9250_ReadID(void)
{
    mpu9250regdata.WHO_AM_I_REG = 0x00;
    MPU9250_ReadReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_WHO_AM_I, &mpu9250regdata.WHO_AM_I_REG);
    if(0x71 != mpu9250regdata.WHO_AM_I_REG)
    {
       mpu9250_device = 0;
//       log_e("not found device");
    }
    else
    {
       mpu9250_device = 1;
       log_i(" deviceok");
    }
}

void mpu9250_InitState(void)
{
    mpu9250_init_State = mpu9250_init_pre_state;
    mpu9250_device = DEVICE_INIT;
    mpu9250_init_delay = 0;
    IMU_init();
}



int8_t MPU9250_Init(void)
{
    int8_t mpu9250_init_returnvalue = 0xff;
    u8 rest = 0;
    switch (mpu9250_init_State)
    {
      case mpu9250_init_pre_state:
            MPU9250_ReadID();
            mpu9250_init_State = mpu9250_init_step1_state;
            break;
      case mpu9250_init_step1_state:
            if (mpu9250_init_delay == 0x00)
            {
                mpu9250_init_delay++;
                mpu9250regdata.PWR_MGMT_1_REG = 0x00;
                MPU9250_WriteReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_PWR_MGMT_1, 0x81);
            }
            else
            {
                    mpu9250_init_delay++;
                if (mpu9250_init_delay > 8) //瀵よ埖妞?160ms
                {
                        mpu9250_init_delay = 0;
                        mpu9250_init_State = mpu9250_init_step2_state;
                }
            }
            break;

      case mpu9250_init_step2_state:
            mpu9250_init_delay++;
            switch (mpu9250_init_delay)
            {
                case 0x01:
                  MPU9250_WriteReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_PWR_MGMT_1, MPU6050_CLOCK_PLL_XGYRO);
                  break;
                case 0x02:
                  MPU9250_WriteReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_SMPLRT_DIV, 0x04);//200 Hz
       //             MPU9250_WriteReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_PWR_MGMT_2, 0);
                  break;
                case 0x03:
       //             MPU9250_WriteReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_CONFIG, 0x06);
                  break;
                case 0x04:
                  MPU9250_WriteReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_ACCEL_CONFIG, (MPU6050_ACCEL_FS_16 << 3));//+-2g
      //            MPU9250_WriteReg(MPU6050_RA_FF_THR, IAM20609_ACCEL_BW_21HZ);/*accel LPF 20HZ*/
                  break;
                case 0x05:
                  
                  MPU9250_WriteReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_GYRO_CONFIG, (MPU6050_GYRO_FS_1000 << 3));//+-2000dps
          //          IAM20609_WriteReg(IAM20609_CONFIG_REG,IAM20609_GYRO_BW_20HZ); //gtro and temp LPF
                  break;
                case 0x06:
      //            MPU9250_WriteReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_FF_THR, 0x00);
                  break;
                case 0x07:
       //             MPU9250_WriteReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_USER_CTRL, 0x00);
                  break;
                case 0x08:
                  MPU9250_WriteReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_INT_PIN_CFG, 0x02);//set i2c bypass enable pin to true to access magnetometer
                  
                  break;
                case 0x09:
                  MPU9250_WriteReg(MPU9150_RA_MAG_ADDRESS, AK8963_CNTL2,0x01);//复位器件
                  MPU9250_WriteReg(MPU9150_RA_MAG_ADDRESS, AK8963_CNTL1,0x11);//设置为16bit模式
                  mpu9250_init_State = mpu9250_init_step3_state;
                  break;
                default:
                  break;
            }
            break;
      case mpu9250_init_step3_state:
            if(0x48 == InitAK8963())
            {
                mpu9250_init_State = mpu9250_init_finish_state;
            }
            break;
      case mpu9250_init_finish_state:
            mpu9250_init_returnvalue = 0x01;
            break;
      default:
            break;
    }

    return mpu9250_init_returnvalue;
}

u8 InitAK8963(void)
{
    u8 wia = 0;
    MPU9250_ReadReg(MPU9150_RA_MAG_ADDRESS, 0x00, (u8 *)&wia);
    log_i("ak8963 id = %d ",wia);
    return wia;
}


void MPU9250_testMotion6(void)
{
    u8 reg_data;
    accel_t acc;
    gyro_t gyro;
    MPU9250_ReadData(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_ACCEL_XOUT_H, reg_data, 6);
    mpu9250acceldata.x = (((int16_t)reg_data) << 8) | reg_data;
    mpu9250acceldata.y = (((int16_t)reg_data) << 8) | reg_data;
    mpu9250acceldata.z = (((int16_t)reg_data) << 8) | reg_data;
    MPU9250_ReadData(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_GYRO_XOUT_H, reg_data, 6);
    mpu9250gyrodata.x = (((int16_t)reg_data) << 8) | reg_data;
    mpu9250gyrodata.y = (((int16_t)reg_data) << 8) | reg_data;
    mpu9250gyrodata.z = (((int16_t)reg_data) << 8) | reg_data;
//    log_i("%6d %6d %6d %6d %6d %6d ",acc.x,acc.y,acc.z,gyro.x,gyro.y,gyro.z);
}

void MPU9250_testMotion9(void)
{
    u8 reg_data;
    u8 st1 = 0;
    MPU9250_testMotion6();

//MPU9250_ReadReg(MPU9150_RA_MAG_ADDRESS,AK8963_ST1, &st1);
//   if(st1)
    {
      MPU9250_ReadData(MPU9150_RA_MAG_ADDRESS, MPU9150_RA_MAG_XOUT_L, reg_data, 6);
      mpu9250magndata.x = (((int16_t)reg_data) << 8) | reg_data;
      mpu9250magndata.y = (((int16_t)reg_data) << 8) | reg_data;
      mpu9250magndata.z = (((int16_t)reg_data) << 8) | reg_data;
    }
//    MPU9250_WriteReg(MPU9150_RA_MAG_ADDRESS, AK8963_CNTL2,0x01);
    MPU9250_WriteReg(MPU9150_RA_MAG_ADDRESS,AK8963_CNTL1,0x11);//设置为16bit模式 采样率为100HZ


   
//    log_i("%6d %6d %6d %6d %6d %6d ",acc.x,acc.y,acc.z,gyro.x,gyro.y,gyro.z);
//    MPU9250_WriteReg(MPU9150_RA_MAG_ADDRESS, 0x0A, 0x01); //enable the magnetometer
    //        delay(10);
   
   
//    MPU9250_WriteReg(MPU9150_RA_MAG_ADDRESS,AK8963_CNTL1,0x11);//每读一次,ak8963自动进入powerdown模式,这里需要重新设定单测量模式

}

void MPU9250_shelldata(void)
{
//   log_i("%6d %6d %6d ",mpu9250acceldata.x,mpu9250acceldata.y,mpu9250acceldata.z);
//   ANO_DT_Send_Senser(mpu9250acceldata.x,mpu9250acceldata.y,mpu9250acceldata.z,mpu9250gyrodata.x,mpu9250gyrodata.y,mpu9250gyrodata.z,0,0,0,0);

    log_i("%6d %6d %6d %6d %6d %6d %6d %6d %6d ",mpu9250acceldata.x,mpu9250acceldata.y,mpu9250acceldata.z,mpu9250gyrodata.x,mpu9250gyrodata.y,mpu9250gyrodata.z,mpu9250magndata.x,mpu9250magndata.y,mpu9250magndata.z);
}

求大神能够指明一些思路

Lancer_zhang 发表于 2019-7-30 16:43:47

我顶我自己,真的非常非常捉急

Lancer_zhang 发表于 2019-7-30 16:44:17

不胜感激,顶自己一下,希望有人能看到

Lancer_zhang 发表于 2019-7-30 18:16:08

这是我买的mpu9250的模块,目前就接了vcc 、3.3v、gnd、ad0、sck
望大佬们能看一下

Lancer_zhang 发表于 2019-7-31 08:49:25

自己再顶一顶。确实是非常奇怪的现象,没有人遇到过吗?

Lancer_zhang 发表于 2019-7-31 17:46:55

最后还是解决了。
要问怎么解决的,很暴力!!!
因为发现初始化无法完成,于是我就死循环不断地写寄存器并读出来。
从逻辑分析仪中发现,有一两次写进去了。
于是初始化函数,我就这么写了:
int8_t MPU9250_Init(void)
{
    int8_t mpu9250_init_returnvalue = 0xff;
    u8 rest = 0;
    switch (mpu9250_init_State)
    {
      case mpu9250_init_pre_state:
            MPU9250_ReadID();
            mpu9250_init_State = mpu9250_init_step1_state;
            break;
      case mpu9250_init_step1_state:
            if (mpu9250_init_delay == 0x00)
            {
                mpu9250_init_delay++;
                mpu9250regdata.PWR_MGMT_1_REG = 0x00;
                MPU9250_WriteReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_PWR_MGMT_1, 0x81);
            }
            else
            {
                    mpu9250_init_delay++;
                if (mpu9250_init_delay > 8) //瀵よ埖妞?160ms
                {
                        mpu9250_init_delay = 0;
                        mpu9250_init_State = mpu9250_init_step2_state;
                }
            }
            break;

      case mpu9250_init_step2_state:
            
            switch (mpu9250_init_delay)
            {
               case 0x00:
                  MPU6050_WriteReg(MPU6050_RA_PWR_MGMT_1, MPU6050_CLOCK_PLL_XGYRO);
                  MPU9250_ReadReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_PWR_MGMT_1, (u8 *)&rest);
                  if((rest&0x01) == 0x01)
                  {
                        mpu9250_init_delay++;
                  }
                  break;
                case 0x01:
                  MPU6050_WriteReg(MPU6050_RA_SMPLRT_DIV, 0x04);//200 Hz
                  MPU9250_ReadReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_SMPLRT_DIV, (u8 *)&rest);
                  if((rest&0x04) == 0x04)
                  {
                        mpu9250_init_delay++;
                  }
                  break;
                case 0x02:
                  MPU6050_WriteReg(MPU6050_RA_ACCEL_CONFIG, (MPU6050_ACCEL_FS_8 << 3));
                  MPU9250_ReadReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_ACCEL_CONFIG, (u8 *)&rest);
                  if((rest&(MPU6050_ACCEL_FS_8 << 3)) == (MPU6050_ACCEL_FS_8 << 3))
                  {
                        mpu9250_init_delay++;
                  }
                  break;
                case 0x03:
                  MPU6050_WriteReg(MPU6050_RA_GYRO_CONFIG, (MPU6050_GYRO_FS_2000 << 3));
                  MPU9250_ReadReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_GYRO_CONFIG, (u8 *)&rest);
                  if((rest&(MPU6050_GYRO_FS_2000 << 3)) == (MPU6050_GYRO_FS_2000 << 3))
                  {
                        mpu9250_init_delay++;
                  }
                  break;
                case 0x04:
                  MPU6050_WriteReg(MPU6050_RA_INT_PIN_CFG, 0x02);
                  MPU9250_ReadReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_INT_PIN_CFG, (u8 *)&rest);
                  if((rest&0x02) == 0x02)
                  {
                        mpu9250_init_delay++;
                  }
                  break;
                case 0x05:
                  ak8963_WriteReg(AK8963_CNTL2,0x01);//复位器件
                  ak8963_WriteReg(AK8963_CNTL1,0x11);//设置为16bit模式
                  mpu9250_init_delay++;
          //          IAM20609_WriteReg(IAM20609_CONFIG_REG,IAM20609_GYRO_BW_20HZ); //gtro and temp LPF
                  break;
                case 0x06:
                  if(0x48 == InitAK8963())
                  {
                        mpu9250_init_State = mpu9250_init_finish_state;
                  }
                  else
                  {
                        mpu9250_init_delay = 0x05;
                  }
      //            MPU9250_WriteReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_FF_THR, 0x00);
                  break;
            }
            break;
      case mpu9250_init_finish_state:
            mpu9250_init_returnvalue = 0x01;
            break;
      default:
            break;
    }

    return mpu9250_init_returnvalue;
}


没错,改成了写一个寄存器就读一个寄存器,直到写成功为止。
接着,我试着修改了下MPU9250_WriteReg函数,因为读函数一直是没问题的,于是我移植了一个其他的写iic的函数,我感觉没什么差别:
static void MPU6050_WriteReg(u8 reg_add,u8 reg_dat)
{
        i2c_Start();
        i2c_SendByte(MPU6050_DEFAULT_ADDRESS | I2C_WR);
        i2c_WaitAck();
        i2c_SendByte(reg_add);
        i2c_WaitAck();
        i2c_SendByte(reg_dat);
        i2c_WaitAck();
        i2c_Stop();
}
static void ak8963_WriteReg(u8 reg_add,u8 reg_dat)
{
        i2c_Start();
        i2c_SendByte(MPU9150_RA_MAG_ADDRESS | I2C_WR);
        i2c_WaitAck();
        i2c_SendByte(reg_add);
        i2c_WaitAck();
        i2c_SendByte(reg_dat);
        i2c_WaitAck();
        i2c_Stop();
}


u8 MPU9250_WriteReg(u8 device, u8 address, u8 Value)
{
    i2c_Start();
    i2c_SendByte(device | I2C_WR);
    if (i2c_WaitAck() != 1)
    {
      goto writesingle_fail;
    }
    i2c_SendByte(address);
    if (i2c_WaitAck() != 1)
    {
      goto writesingle_fail;
    }
    i2c_SendByte(Value);
    if (i2c_WaitAck() != 1)
    {
      goto writesingle_fail;
    }
    i2c_Stop();
    return 1;

writesingle_fail:
    i2c_Stop();
    return 0;
}

MPU9250_WriteReg这个是原来的,MPU6050_WriteReg和ak8963_WriteReg是新的。
有差别么?
不过改完了,每一次都能成功写进去了。

fengyuxiaoxiao 发表于 2019-8-1 09:55:45

解决了就好{:lol:}

Lancer_zhang 发表于 2019-8-1 14:31:28

fengyuxiaoxiao 发表于 2019-8-1 09:55
解决了就好

是的哈,我也没有继续看看两者的波形有什么差异了。。。。{:tongue:}
页: [1]
查看完整版本: 调试mpu9250出现无法配置寄存器的问题