可以看一下我的上一篇博客
https://blog.csdn.net/zhangyufeikk/article/details/97789743
问题的发现:
一开始我以为我已经读到加速度和陀螺仪的数据,但由于一直读不到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 read bytes
*
* \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(" device ok");
}
}
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[6];
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[0]) << 8) | reg_data[1];
mpu9250acceldata.y = (((int16_t)reg_data[2]) << 8) | reg_data[3];
mpu9250acceldata.z = (((int16_t)reg_data[4]) << 8) | reg_data[5];
MPU9250_ReadData(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_GYRO_XOUT_H, reg_data, 6);
mpu9250gyrodata.x = (((int16_t)reg_data[0]) << 8) | reg_data[1];
mpu9250gyrodata.y = (((int16_t)reg_data[2]) << 8) | reg_data[3];
mpu9250gyrodata.z = (((int16_t)reg_data[4]) << 8) | reg_data[5];
// 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[6];
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[0]) << 8) | reg_data[1];
mpu9250magndata.y = (((int16_t)reg_data[2]) << 8) | reg_data[3];
mpu9250magndata.z = (((int16_t)reg_data[4]) << 8) | reg_data[5];
}
// 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);
}
最后还是解决了。
要问怎么解决的,很暴力!!!
因为发现初始化无法完成,于是我就死循环不断地写寄存器并读出来。
从逻辑分析仪中发现,有一两次写进去了。
于是初始化函数,我就这么写了:
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;
}
break;
default:
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是新的。
有差别么?
不过改完了,每一次write都可以成功写进去了。
原始数据是这样的:
最后都能读出来数据了,分别是:ax,ay,az,gx,gy,gz,mx,my,mz..
稍微看看姿态怎么样(pid数据均来自icm20609那时候调的数据)