欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【005】基于STM32标准库IMU9250数据读取(二)

程序员文章站 2022-04-19 11:29:15
...

基于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 AK8963寄存器列表

  Who Am I寄存器 地址0x00

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

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

【005】基于STM32标准库IMU9250数据读取(二)

图2 Control 1寄存器

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

【005】基于STM32标准库IMU9250数据读取(二)

图3 不同工作模式配置

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

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

【005】基于STM32标准库IMU9250数据读取(二)

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

}




联系作者