MPU9250 初始化
static uint8_t MPU_Basic_Init(void)
{
uint8_t res = 0;
MPU_ADDR_CTRL();
MPU_IIC_Init();
MPU_Delay_ms(10);
MPU_Write_Byte(MPU9250_ADDR, MPU_PWR_MGMT1_REG, 0X80); // Reset MPU9250 //复位MPU9250
MPU_Delay_ms(100); // Delay 100 ms //延时100ms
MPU_Write_Byte(MPU9250_ADDR, MPU_PWR_MGMT1_REG, 0X00); // Wake mpu9250 //唤醒MPU9250
MPU_Set_Gyro_Fsr(1); // Gyroscope sensor //陀螺仪传感器,±500dps=±500°/s ±32768 (gyro/32768*500)*PI/180(rad/s)=gyro/3754.9(rad/s)
MPU_Set_Accel_Fsr(0); // Acceleration sensor //加速度传感器,±2g=±2*9.8m/s^2 ±32768 accel/32768*19.6=accel/1671.84
MPU_Set_Rate(50); // Set the sampling rate to 50Hz //设置采样率50Hz
MPU_Write_Byte(MPU9250_ADDR, MPU_INT_EN_REG, 0X00); // Turn off all interrupts //关闭所有中断
MPU_Write_Byte(MPU9250_ADDR, MPU_USER_CTRL_REG, 0X00); // The I2C main mode is off //I2C主模式关闭
MPU_Write_Byte(MPU9250_ADDR, MPU_FIFO_EN_REG, 0X00); // Close the FIFO //关闭FIFO
// The INT pin is low, enabling bypass mode to read the magnetometer directly
// INT引脚低电平有效,开启bypass模式,可以直接读取磁力计
MPU_Write_Byte(MPU9250_ADDR, MPU_INTBP_CFG_REG, 0X82);
// Read the ID of MPU9250 读取MPU9250的ID
res = MPU_Read_Byte(MPU9250_ADDR, MPU_DEVICE_ID_REG);
printf("MPU9250 RD ID=0x%02X\n", res);
if (res == MPU9250_ID) // The device ID is correct //器件ID正确
{
MPU_Write_Byte(MPU9250_ADDR, MPU_PWR_MGMT1_REG, 0X01); // Set CLKSEL,PLL X axis as reference //设置CLKSEL,PLL X轴为参考
MPU_Write_Byte(MPU9250_ADDR, MPU_PWR_MGMT2_REG, 0X00); // Acceleration and gyroscope both work //加速度与陀螺仪都工作
MPU_Set_Rate(50); // Set the sampling rate to 50Hz //设置采样率为50Hz
}
else
return 1;
res = MPU_Read_Byte(AK8963_ADDR, MAG_WIA); // Read AK8963ID //读取AK8963ID
printf("AK8963 RD ID=0x%02X\n", res);
if (res == AK8963_ID)
{
MPU_Write_Byte(AK8963_ADDR, MAG_CNTL1, 0X11); // Set AK8963 to single measurement mode //设置AK8963为单次测量模式
}
else
return 1;
MPU_Delay_ms(30);
return 0;
}
上述代码我们实现了MPU9250的初始化
1、设置地址
MPU_ADDR_CTRL(); // 控制MPU9250的IIC地址为0x68 控制9脚高电平地址为011010001(B) 低电平为011010000(B)
2、初始化IIC控制引脚设置为推完输出
MPU_IIC_Init();
3、复位9250
MPU_Write_Byte(MPU9250_ADDR, MPU_PWR_MGMT1_REG, 0X80); // Reset MPU9250 //复位MPU9250
MPU_Delay_ms(100); // Delay 100 ms //延时100ms
MPU_Write_Byte(MPU9250_ADDR, MPU_PWR_MGMT1_REG, 0X00); // Wake mpu9250 //唤醒MPU9250 这个应该是清除复位
4、设置参数
MPU_Set_Gyro_Fsr(1); // Gyroscope sensor //陀螺仪传感器,±500dps=±500°/s ±32768 (gyro/32768*500)*PI/180(rad/s)=gyro/3754.9(rad/s)
MPU_Set_Accel_Fsr(0); // Acceleration sensor //加速度传感器,±2g=±2*9.8m/s^2 ±32768 accel/32768*19.6=accel/1671.84
MPU_Set_Rate(50); // Set the sampling rate to 50Hz //设置采样率50Hz
//设置MPU9250的采样率(假定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(MPU9250_ADDR, MPU_SAMPLE_RATE_REG, data); //设置数字低通滤波器
return MPU_Set_LPF(rate / 2); //自动设置LPF为采样率的一半
}
//设置MPU9250的数字低通滤波器
// 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 = 3;
else if (lpf >= 20)
data = 4;
else if (lpf >= 10)
data = 5;
else
data = 6;
return MPU_Write_Byte(MPU9250_ADDR, MPU_CFG_REG, data); //设置数字低通滤波器
}
这里注意几个问题:1、带宽是指的传感器对待测量信号的响应,比如带宽过宽对高频信号也进行测量,传感器响应速度快(延时低),但是会测量到高频干扰。如果带宽窄会滤波高频信号那么响应速度也相应降低。
2、这里的FCHOICE[1:0]和下面的Fchoice_b[1:0]是一个位。上面我们配置陀螺仪的量程范围时,已经设置过这个寄存器了。设置为00也就是这里设置为11 然后我们写入的值,比如程序中的50/2 是25相应写入data值为4 也就是配置了DLPF_CFG[2:0]为4 即带宽为20HZ 延迟为9.9ms
5、关闭中断
MPU_Write_Byte(MPU9250_ADDR, MPU_INT_EN_REG, 0X00); // Turn off all interrupts //关闭所有中断
这个寄存器没找到
6、设置IIC为从机模式
MPU_Write_Byte(MPU9250_ADDR, MPU_USER_CTRL_REG, 0X00); // The I2C main mode is off //I2C主模式关闭
7、关闭FIFO
MPU_Write_Byte(MPU9250_ADDR, MPU_FIFO_EN_REG, 0X00); // Close the FIFO //关闭FIFO
8、设置bypass模式
// The INT pin is low, enabling bypass mode to read the magnetometer directly
// INT引脚低电平有效,开启bypass模式,可以直接读取磁力计
MPU_Write_Byte(MPU9250_ADDR, MPU_INTBP_CFG_REG, 0X82);
9、读取ID
res = MPU_Read_Byte(MPU9250_ADDR, MPU_DEVICE_ID_REG);
这里不懂复位值是0x68返回值却是0x71
10、设备ID正确的情况下设置时钟和加速度和陀螺仪
MPU_Write_Byte(MPU9250_ADDR, MPU_PWR_MGMT1_REG, 0X01); // Set CLKSEL,PLL X axis as reference //设置CLKSEL,PLL X轴为参考
MPU_Write_Byte(MPU9250_ADDR, MPU_PWR_MGMT2_REG, 0X00); // Acceleration and gyroscope both work //加速度与陀螺仪都工作
MPU_Set_Rate(50); // Set the sampling rate to 50Hz //设置采样率为50Hz
11、设置磁力计
res = MPU_Read_Byte(AK8963_ADDR, MAG_WIA); // Read AK8963ID //读取AK8963ID
printf("AK8963 RD ID=0x%02X\n", res);
if (res == AK8963_ID)
{
MPU_Write_Byte(AK8963_ADDR, MAG_CNTL1, 0X11); // Set AK8963 to single measurement mode //设置AK8963为单次测量模式 14位输出
}
自此初始化设置完毕
MPU9250 数据读取
MPU_Get_Gyroscope(mpu_data.gyro); //陀螺仪
MPU_Get_Accelerometer(mpu_data.accel);//加速度
MPU_Get_Magnetometer(mpu_data.compass);//磁力计
uint8_t MPU_Get_Gyroscope(short *gyro)
{
#if ENABLE_MPU9250_FILTER
uint8_t buf[6],res;
res=MPU_Read_Len(MPU9250_ADDR,MPU_GYRO_XOUTH_REG,6,buf);
if(res==0)
{
/*前1000次作为陀螺仪零点*/
if(Deviation_Count<CONTROL_DELAY)
{
Deviation_Count++;
//Read the gyroscope zero //读取陀螺仪零点
Deviation_gyro[0] = (((uint16_t)buf[0]<<8)|buf[1]);
Deviation_gyro[1] = (((uint16_t)buf[2]<<8)|buf[3]);
Deviation_gyro[2] = (((uint16_t)buf[4]<<8)|buf[5]);
}
else
{
/*g_mpu_start 作为1000次读取的标志位,把第999次作为原点值值打印出来*/
if (g_mpu_start == 0)
{
g_mpu_start = 1;
Beep_On_Time(100);
DEBUG("OFFSET GYRO:%d, %d, %d", Deviation_gyro[0], Deviation_gyro[1], Deviation_gyro[2]);
}
//Save the raw data to update zero by clicking the user button
//保存原始数据用于单击用户按键更新零点
Original_gyro[0] = (((uint16_t)buf[0]<<8)|buf[1]);
Original_gyro[1] = (((uint16_t)buf[2]<<8)|buf[3]);
Original_gyro[2] = (((uint16_t)buf[4]<<8)|buf[5]);
//Removes zero drift data
//去除零点漂移的数据
gyro[0] = Original_gyro[0]-Deviation_gyro[0];
gyro[1] = Original_gyro[1]-Deviation_gyro[1];
gyro[2] = Original_gyro[2]-Deviation_gyro[2];
}
}
return 0;
#else
uint8_t buf[6], res;
res = MPU_Read_Len(MPU9250_ADDR, MPU_GYRO_XOUTH_REG, 6, buf);
if (res == 0)
{
gyro[0] = ((uint16_t)buf[0] << 8) | buf[1];
gyro[1] = ((uint16_t)buf[2] << 8) | buf[3];
gyro[2] = ((uint16_t)buf[4] << 8) | buf[5];
}
g_mpu_start = 1;
return res;
#endif
}
res=MPU_Read_Len(MPU9250_ADDR,MPU_GYRO_XOUTH_REG,6,buf);
寄存器 67 到 72 陀螺仪测量
其中67 68为X轴陀螺仪的字节 H L (BE)
其中69 70为X轴陀螺仪的字节 H L
其中71 72为X轴陀螺仪的字节 H L
每次的到的gyro是消除零漂的数据,用每次读到的原始数据减去第999次的数据。
uint8_t MPU_Get_Accelerometer(short *accel)
{
uint8_t buf[6], res;
res = MPU_Read_Len(MPU9250_ADDR, MPU_ACCEL_XOUTH_REG, 6, buf);
if (res == 0)
{
accel[0] =((uint16_t)buf[0]<<8)|buf[1];
accel[1] =((uint16_t)buf[2]<<8)|buf[3];
accel[2] =((uint16_t)buf[4]<<8)|buf[5];
}
return res;
}
//得到磁力计值(原始值)
// mx,my,mz:磁力计x,y,z轴的原始读数(带符号)
// 返回值:0,设置成功, 其他,设置失败
uint8_t MPU_Get_Magnetometer(short *mag)
{
uint8_t buf[6], res;
res = MPU_Read_Len(AK8963_ADDR, MAG_XOUT_L, 6, buf);
if (res == 0)
{
mag[0] = ((uint16_t)buf[1]<<8)|buf[0];
mag[1] = ((uint16_t)buf[3]<<8)|buf[2];
mag[2] = ((uint16_t)buf[5]<<8)|buf[4];
}
MPU_Write_Byte(AK8963_ADDR, MAG_CNTL1, 0X11); // AK8963每次读完以后都需要重新设置为单次测量模式
return res;
}
同理加速度轴和磁力轴也相同。
注意磁力中是先L后H