【005】基于STM32标准库IMU9250数据读取(二)
基于STM32标准库的IMU9250数据读取(二)
关键词:MPU9250,STM32,磁力计,I2C,MPU6050
在“【004】基于STM32标准库的IMU9250数据读取”一文中着重介绍了MPU9250的组成以及加速度计、陀螺仪原始数据的获取。然而由于磁力计AK8963仅仅是与MPU6050封装在一起构成MPU9250,读取MPU9250中磁力计数据,的设置方式也有所不同,本文主要介绍磁力计数据的读取。
AK8963简介
AK8963是一个三轴的霍尔传感器,主要用来为手机及其他便携设备提供导航信息。AK8963测量范围±4900uT,可编程配置支持14位或者16位AD输出,支持I2C以及SPI通信方式,采样速率可配置,设备地址为0x0C。
AK8963基本寄存器
图1为AK8963寄存器,与“【004】基于STM32标准库的IMU9250数据读取”一样,为了不让刚接触的读者感到困惑仅接受用到的寄存器及相应的位。
图1 AK8963寄存器列表
Who Am I寄存器 地址0x00
该寄存器用于告知用户当前正在访问的设备,其不受传感器状态影响,存储着固定值0x48也可以拿来判断我们的读取是否成功。
Control 1寄存器 地址0x0A 如图2所示
图2 Control 1寄存器
MODE[3:0]工作模式,不同工作模式对应配置如图3所示。
图3 不同工作模式配置
BIT采样位数配置,此位置1则进行16位ADC输出,清0则进行14为ADC输出
Status 1寄存器(ST1) 地址0x02 如图4所示
图4 Status 1寄存器
DRDY数据采集完成位,此位为1说明数据采集完成可以进行读取,此位为0说明数据采集尚未完成。在进行数据读取前,我们需要先读取该位确保数据已经采集完成。
Status 2寄存器(ST2) 地址0x09
对该寄存器的读取仅仅是为了满足AK8963的数据读取流程。
AK8963数据读取流程
a. 读取ST1寄存器,判断DRDY位是否为1,若为1则转步骤b,否则重复执行步骤a
b. 读取AK8963三轴磁力计数据
c. 读取ST2寄存器
与AK8963进行I2C通信有两种方式:一是,使用MCU与AK8963直接通信;二是,将AK8963设置为MPU9250的从设备,通过MPU9250进行通信。方式1更为直接,易于控制,方式2效率较高,能够降低功耗。这里为便于理解我们采用方式1。需要对MPU9250进行设置,使得I2C信号能够到达AK8963。
INT Pin/Bypass Enable Configuration 寄存器 地址0x37
[1]BYPASS_EN,此位置一AK8963的SCL、SDA线与MPU9250的SCL、SDA线连通,即可使用MCU直接对AK8963进行设置和读取。
对于AK8963的代码与“【004】基于STM32标准库的IMU9250数据读取”中加速度计和陀螺仪的原始数据代码整合在一起如下:
uint8_t MPU6050_Init()
{
MPU6050_USART_Init();
MPU6050_I2C_Init();
RawDataQueueBuffer_Init();
USART_QueueBuffer_Init();
uint8_t RegisterValue = 0;
RegisterValue = MPU6050_I2C_Read_OneByte(MPU6050_ADDR, MPU9250_WHO_AM_I);
if (RegisterValue != 0x71) // Check read who am i register value
{
return 255;
}
MPU6050_I2C_Write_OneByte(MPU6050_ADDR, MPU9250_PWR_MGMT_1, MPU9250_H_RESET_MASK); //Reset all internal registers value by default
Wait_nms(500);
MPU6050_I2C_Write_OneByte(MPU6050_ADDR, MPU9250_PWR_MGMT_1, 0x01); //Choose internal clock
//Set MPU9250 out date rate gyro 20Hz Accel 20Hz
MPU6050_I2C_Write_OneByte(MPU6050_ADDR, MPU9250_SMPLRT_DIV, 0x31);
MPU6050_I2C_Write_OneByte(MPU6050_ADDR, MPU9250_CONFIG, (0x01 << 0) & MPU9250_DLPF_CFG_MASK);
MPU6050_I2C_Write_OneByte(MPU6050_ADDR, MPU9250_GYRO_CONFIG, MPU9250_GYRO_FULL_SCALE_500DPS);
MPU6050_I2C_Write_OneByte(MPU6050_ADDR, MPU9250_ACCEL_CONFIG, MPU9250_FULL_SCALE_2G);
MPU6050_I2C_Write_OneByte(MPU6050_ADDR, MPU9250_INT_PIN_CFG, MPU9250_LATCH_INT_EN_MASK | MPU9250_INT_ANYRD_2CLEAR_MASK | MPU9250_BYPASS_EN_MASK);
MPU6050_I2C_Write_OneByte(MPU6050_ADDR, MPU9250_INT_ENABLE, MPU9250_RAW_RDY_EN_MASK); //Enable interrupt when data is ready
RegisterValue = MPU6050_I2C_Read_OneByte(AK8963_ADDR, MPU9250_MAG_WIA);
if (RegisterValue != 0x48) // Check read who am i register value
{
return 255;
}
MPU6050_I2C_Write_OneByte(AK8963_ADDR, MPU9250_MAG_CNTL, 0x16); //magmeter output rate 100Hz, 16bit
TaskFlag_GetData = 0;
TaskFlag_CheckData = 0;
MPU6050_GPIO_Init();
return 0;
}
void MPU6050_Get_RawData()
{
uint8_t TempBuffer[14];
uint8_t MPU_Status = 0;
uint8_t BufferCnt = 0;
MPU_Status = MPU6050_I2C_Read_OneByte(MPU6050_ADDR, MPU9250_INT_STATUS);
if ((MPU_Status & MPU9250_RAW_DATA_RDY_INT_MASK) == MPU9250_RAW_DATA_RDY_INT_MASK)
{
//ACC X Y Z TEMP GYRO X Y Z
MPU6050_I2C_Read_nByte(MPU6050_ADDR, MPU9250_ACCEL_XOUT_H, TempBuffer, 14);
for (BufferCnt = 0; BufferCnt < 14; BufferCnt++)
{
PushQueue(TempBuffer[BufferCnt]);
}
}
MPU_Status = MPU6050_I2C_Read_OneByte(AK8963_ADDR, MPU9250_MAG_ST1);
if ((MPU_Status & 0x01) == 0x01)
{
MPU6050_I2C_Read_nByte(AK8963_ADDR, MPU9250_MAG_XOUT_L, TempBuffer, 6);
MPU6050_I2C_Read_OneByte(AK8963_ADDR, MPU9250_MAG_ST2);
PushQueue(TempBuffer[1]);
PushQueue(TempBuffer[0]);
PushQueue(TempBuffer[3]);
PushQueue(TempBuffer[2]);
PushQueue(TempBuffer[5]);
PushQueue(TempBuffer[4]);
}
}
上一篇: 美团walle多渠道打包
下一篇: 前端工具库浏览器判断