【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数据读取”一样,为了不让刚接触的读者感到困惑仅接受用到的寄存器及相应的位。

【005】基于STM32标准库IMU9250数据读取(二)_第1张图片

图1 AK8963寄存器列表

  Who Am I寄存器 地址0x00

  该寄存器用于告知用户当前正在访问的设备,其不受传感器状态影响,存储着固定值0x48也可以拿来判断我们的读取是否成功。

  Control 1寄存器 地址0x0A 如图2所示


图2 Control 1寄存器

  MODE[3:0]工作模式,不同工作模式对应配置如图3所示。

【005】基于STM32标准库IMU9250数据读取(二)_第2张图片

图3 不同工作模式配置

  BIT采样位数配置,此位置1则进行16位ADC输出,清0则进行14为ADC输出

  Status 1寄存器(ST1) 地址0x02 如图4所示

【005】基于STM32标准库IMU9250数据读取(二)_第3张图片

图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]);
	}

}




联系作者

你可能感兴趣的:(嵌入式开发)