基于STM32F103C8T6驱动MPU9250传感器读取九轴数据

慧生活 20250924

  • MEMS传感器
  • 九轴惯性测量单元
  • MPU9250传感器

一、MPU9250传感器模块概述

MPU9250是一款高集成度的九轴惯性测量单元(IMU),它集成了三轴陀螺仪、三轴加速度计和三轴磁力计(通常集成的磁力计为AK8963)。由于其体积小、功耗低、性能稳定,MPU9250广泛应用于无人机、机器人、智能穿戴设备、虚拟现实以及运动追踪等领域。MPU9250采用MEMS(微机电系统)技术制造,能够同时采集角速度、线性加速度和地磁场数据,从而实现九自由度测量。模块内部还集成了数字运动处理器(DMP),用于执行复杂的传感器融合算法,从而降低了主控芯片的运算负担。

二、功能与特点

MPU9250整合了3轴加速度计、3轴陀螺仪和3轴磁力计,能够提供九轴数据。这使得系统可以实时计算出姿态、航向和运动状态,为高精度定位和运动控制提供数据支持。

  1. 低功耗设计
    采用先进的低功耗设计,适合于便携式设备和电池供电的应用场景。其工作模式可根据应用需求进行灵活配置,如休眠、低功耗待机以及全速工作模式。
  2. 高动态范围和分辨率
    陀螺仪:支持±250、±500、±1000和±2000°/s等不同的量程选择,可适应从微小角速度到大幅度旋转的测量。
    加速度计:支持±2g、±4g、±8g和±16g的量程,适用于多种运动状态检测。
    磁力计:内置AK8963磁力计,具有高分辨率,可以进行精确的地磁测量,用于航向计算和磁场干扰补偿。
  3. 数字运动处理器(DMP)
    内置DMP可以实现基本的姿态计算和传感器融合,降低主控MCU的计算负担,并实现实时的运动检测与姿态估计。
  4. 多种通信接口
    MPU9250支持I2C和SPI两种通信方式,便于在不同系统中灵活应用。标准库或HAL库均可对其进行驱动开发。
  5. 内置温度传感器
    除了三轴数据,MPU9250还内置温度传感器,用于监控芯片内部温度。虽然该温度数据主要反映芯片工作时的温度状况,但在某些应用中也可作为温度补偿参考。

三、数据校准与转换

传感器输出的原始数据通常为16位有符号数。为了获得物理意义上的数值,需要根据所选的量程进行转换。例如:

  1. 加速度计:如果选择±2g量程,则转换系数为16384 LSB/g,即原始数据除以16384后得到加速度值(单位g)。
  2. 陀螺仪:如果选择±250°/s量程,则转换系数为131 LSB/°/s,即原始数据除以131后得到角速度值(单位°/s)。
  3. 温度传感器:MPU9250的文档中未明确给出温度转换参数,温度转换公式一般参考MPU6050的公式:

温度(℃)={TEMP-OUT}/{340}+36.53

四、常用寄存器说明

1、WHO_AM_I:读取设备ID寄存器(只读不能写),MPU9250的ID默认为0x71。


其中AK8963的设备ID固定为0x48。

2、PWR_MGMT_1:电源管理1, 此寄存器用于设置用户配置电源模式和时钟源。

H_RESET:重置内部寄存器,并恢复默认设置。写一个1来设置重置位,该位将自动清除。即复位MPU9250。
SLEEP:设置MPU9250工作模式为休眠模式。
CYCLE:周期模式。当你在 PWR_MGMT_1 寄存器中设置了 CYCLE 位,同时确保 SLEEP 和 STANDBY 位没有被设置时,MPU9250 会进入一种低功耗工作模式。在这种模式下,芯片会不断地在“休眠”与“短暂唤醒采样”之间交替工作。每次唤醒时,它只会采集一个加速度计样本,而不是连续采集数据。采样的频率由 LP_ACCEL_ODR 寄存器来控制。注意:如果你通过 PWR_MGMT_2 寄存器禁用了所有加速度计的轴(也就是关闭了加速度计),那么即使启用了周期模式,芯片仍然会按照 LP_ACCEL_ODR 寄存器设定的时间间隔定时唤醒,但由于加速度计被禁用了,所以它不会采集任何数据。简单来说,就是启用周期模式时芯片周期性地从低功耗休眠状态中唤醒,采集一次数据,然后再回到休眠状态。如果禁用加速度计:芯片仍会周期性唤醒,但不会采集数据。
GYRO_STANDBY:陀螺仪待机。设置后,陀螺仪驱动器和锁相环电路将启用,但感测路径将被禁用。这是一种低功耗模式,可快速启用陀螺仪。
PD_PTAT:关闭内部 PTAT 电压发生器和 PTAT ADC
CLKSEL[2:0]:时钟选择。可选择内部8M晶振、外部晶振或陀螺仪时钟作为时钟源。设备上电默认使用内部8M晶振作为时钟,但其精度不高。官方推荐使用陀螺仪时钟或外部晶振作为时钟源,以提高稳定性,一般设置CLKSEL=001,即选择陀螺仪X轴时钟作为时钟源即可。下表为时钟源选择。

3、PWR_MGMT_2:电源管理2,使能3轴加速度和3轴陀螺仪。

4、SMPLRT_DIV:采样率分频器,用于设置传感器数据采样的速率。将设置采样速率时钟通过这个寄存器进行分频,从而得到最终的数据采样率

分频计算公式如下

5、CONFIG:配置寄存器。

FIFO_MODE:控制 FIFO(数据缓冲区)在装满后如何处理新的数据。当FIFO_MODE = 0时,一旦FIFO装满,则新数据覆盖旧数据。FIFO_MODE = 1时,一旦FIFO满,则停止存储数据。
EXT_SYNC_SET[2:0]:配置外部同步,让芯片与外部触发信号同步采集数据。以下表为选择哪个传感器数据同步,其中000为禁用同步,001为温度数据同步,010-111分别为3轴陀螺仪、3轴加速度数据同步。

DLPF_CFG[2:0]:设置数字低通滤波器,用于滤除传感器信号中的高频噪声。当 FCHOICE_B [1:0] = 00 时,DLPF 由 DLPF_CFG 配置。陀螺仪和温度传感器根据 DLPF_CFG 和 FCHOICE_B 的值进行过滤,如下表所示。

6、GYRO_CONFIG:配置陀螺仪自检和满量程


7、ACCEL_CONFIG:配置加速度自检和满量程


8、INT_PIN_CFG:中断配置寄存器,用于设置INT中断引脚的电平标准和驱动方式(推挽、开漏)等;

BYPASS_EN:配置旁路模式。读取磁力计数据可以通过两种方式读取,一种是通过配置内部I2C主控模式读取,一种是直接通过旁路模式读取,一般是开启旁路模式来访问磁力计,比较简单方便。
9、CNTL1:配置磁力计工作模式。

以下为配置模式

五、接线说明

STM32F103C8T6MPU9250 / USB转TTL
3V3MPU9250_VCC
GNDMPU9250和TTL的GND
GPIOB10MPU9250_SCL
GPIOB11MPU9250_SDA
GPIOA9TTL_RX
GPIOA10TTL_TX

六、读取MPU9250九轴数据

代码示例:

main.c

#include "stm32f10x.h"                  // Device header
#include "mpu9250.h"
#include "delay.h"
#include "usart.h"

int16_t ax, ay, az, gx, gy, gz, mx, my, mz;
float temperature;
char mpu9250ID[30], ak8963ID[30], buf[100];

int main(void)
{
	SystemInit();
	MPU9250_Init();

	USART1_Init();	// USART初始化函数
	
	sprintf(mpu9250ID, "mpu9250_id = 0x%02Xrn", MPU9250_GetID());	
	USART_SendString(USART1, mpu9250ID);
	
	sprintf(ak8963ID, "ak8963_id = 0x%02Xrnrn", AK8963_GetID());
	USART_SendString(USART1, ak8963ID);
	
	while(1)
	{
		//读取加速度和陀螺仪
		MPU9250_GetData(&ax, &ay, &az, &gx, &gy, &gz, &mx, &my, &mz);
		//读取温度
		temperature = MPU6050_GetTemperature();
		
		sprintf(buf, "ax:%d  ay:%d  az:%d    gx:%d  gy:%d  gz:%drnmx:%d  my:%d  mz:%drnTemp: %.2f℃rnrn",
                ax, ay, az, gx, gy, gz, mx, my, mz, temperature);
		
		USART_SendString(USART1, buf);

        Delay_ms(500);
	}
}

MPU9250.c

#include "MyI2C.h"
#include "MPU9250_Reg.h"
#include "delay.h"

void MPU9250_WriteReg(uint8_t DeviceAddr, uint8_t RegAddress, uint8_t Data)
{
	MyI2C_Start();
	MyI2C_SendByte(DeviceAddr);
	MyI2C_ReceiveAck();
	MyI2C_SendByte(RegAddress);
	MyI2C_ReceiveAck();
	MyI2C_SendByte(Data);
	MyI2C_ReceiveAck();
	MyI2C_Stop();
}

uint8_t MPU9250_ReadReg(uint8_t DeviceAddr, uint8_t RegAddress)
{
	uint8_t Data;
	
	MyI2C_Start();
	MyI2C_SendByte(DeviceAddr);
	MyI2C_ReceiveAck();
	MyI2C_SendByte(RegAddress);
	MyI2C_ReceiveAck();
	
	MyI2C_Start();
	MyI2C_SendByte(DeviceAddr | 0x01); //指定地址读
	MyI2C_ReceiveAck();
	Data = MyI2C_ReceiveByte();
	MyI2C_SendAck(1);
	MyI2C_Stop();
	
	return Data;
}

uint8_t MPU9250_GetID(void)
{
	return MPU9250_ReadReg(MPU9250_ADDR_WRITE, MPU9250_WHO_AM_I);
}

uint8_t AK8963_GetID(void)
{
	return MPU9250_ReadReg(AK8963_ADDR_WRITE, AK8963_WHO_AM_I);
}

void MPU9250_GetData(int16_t *ax, int16_t *ay, int16_t *az, 
					    int16_t *gx, int16_t *gy, int16_t *gz,
						int16_t *mx, int16_t *my, int16_t *mz)
{
	uint8_t AccData[7], GyroData[7], MagData[7];  // 包括6字节数据及1字节状态(ST2)
    uint8_t i;
	
	//3轴加速度
	for(i = 0; i < 7; i++){
        AccData[i] = MPU9250_ReadReg(MPU9250_ADDR_WRITE, MPU9250_ACCEL_XOUT_H + i);
    }
	*ax = (int16_t)(((int16_t)AccData[0] < < 8) | AccData[1]);
    *ay = (int16_t)(((int16_t)AccData[2] < < 8) | AccData[3]);
    *az = (int16_t)(((int16_t)AccData[4] < < 8) | AccData[5]);
	
	//3轴陀螺仪
	for(i = 0; i < 7; i++){
        GyroData[i] = MPU9250_ReadReg(MPU9250_ADDR_WRITE, MPU9250_GYRO_XOUT_H + i);
    }
	*gx = (int16_t)(((int16_t)GyroData[0] < < 8) | GyroData[1]);
    *gy = (int16_t)(((int16_t)GyroData[2] < < 8) | GyroData[3]);
    *gz = (int16_t)(((int16_t)GyroData[4] < < 8) | GyroData[5]);
	
	//3轴磁力计
	for(i = 0; i < 7; i++){
        MagData[i] = MPU9250_ReadReg(AK8963_ADDR_WRITE, AK8963_HXL + i);
    }
    /* 注意:AK8963数据寄存器采用低字节在前的格式 */
    *mx = (int16_t)(((int16_t)MagData[1] < < 8) | MagData[0]);
    *my = (int16_t)(((int16_t)MagData[3] < < 8) | MagData[2]);
    *mz = (int16_t)(((int16_t)MagData[5] < < 8) | MagData[4]);
	
	/* 可以在此检查ST2寄存器(Data[6])中的溢出标志 */
}

float MPU6050_GetTemperature(void)
{
	int16_t TempData;
	uint8_t tempH, tempL;
	
	tempH = MPU9250_ReadReg(MPU9250_ADDR_WRITE, MPU9250_TEMP_OUT_H);
	tempL = MPU9250_ReadReg(MPU9250_ADDR_WRITE, MPU9250_TEMP_OUT_L);
	
	TempData = (int16_t)(tempH < < 8) | tempL;
	
	return((float)TempData) / 340.0f + 36.53f;
}

void MPU9250_Init()
{
	MyI2C_Init();
	MPU9250_WriteReg(MPU9250_ADDR_WRITE, MPU9250_PWR_MGMT_1, 0x01);
	MPU9250_WriteReg(MPU9250_ADDR_WRITE, MPU9250_PWR_MGMT_2, 0x00);
	MPU9250_WriteReg(MPU9250_ADDR_WRITE, MPU9250_SMPLRT_DIV, 0x09);	//采样分频器
	MPU9250_WriteReg(MPU9250_ADDR_WRITE, MPU9250_CONFIG, 0x06);	//配置寄存器,配置同步时钟和低通滤波
	MPU9250_WriteReg(MPU9250_ADDR_WRITE, MPU9250_GYRO_CONFIG, 0x18); //配置陀螺仪自测和满量程
	MPU9250_WriteReg(MPU9250_ADDR_WRITE, MPU9250_ACCEL_CONFIG, 0x18);
	MPU9250_WriteReg(MPU9250_ADDR_WRITE, MPU9250_INT_PIN_CFG, 0x02);  //开启旁路模式
	MPU9250_WriteReg(AK8963_ADDR_WRITE, AK8963_CNTL1, 0x16);  //设置连续测量模式
	Delay_ms(10);
}

效果展示:

七、读取不到磁力计数据的可能原因及解决方法

获取磁力计是根据AK8963来测量,在读取磁力计数据前,先读取下AK8963设备的ID值是否返回正常。如果不正常,可能的原因有以下几点:

  1. 旁路模式未开启
    MPU9250内部连接了AK8963,只有在设置旁路模式后,外部I2C才能直接访问AK8963。如果旁路模式没有正确配置,I2C总线上可能读不到AK8963的数据。
    如果旁路模式已开启,常见原因是MPU9250内部I2C主控功能没有被关闭,导致旁路模式虽然设置了但仍然屏蔽了对AK8963的直接访问。通常在启用旁路模式之前,需要先清除MPU9250的I2C_MST_EN,以确保外部I2C能直接访问AK8963。否则,即便旁路模式配置正确,也可能读不到AK8963的寄存器,返回0x00。
    建议检查初始化流程,确保在设置INT_PIN_CFG寄存器为0x02以启用旁路模式之前,先在USER_CTRL寄存器中清除I2C主控使能位,然后再进行后续的AK8963初始化流程。
  2. I2C通信问题
    检查下I2C初始化和通讯时序是否正确。
    值得注意的是I2C地址的位宽上,AK8963的7位从地址是0x0C,如果你的I2C位操作中,传递的是8位地址。对于8位地址,写操作应使用(0x0C<<1)=0x18,而读操作应使用0x18|0x01=0x19。如果直接使用0x0C,就相当于地址错误,I2C总线读取时由于找不到设备,返回的自然就是上拉电平(0xFF)。
  3. 供电或复位问题
    如果AK8963没有正确上电或者处于复位状态,也可能返回0x00。确保传感器的电源电压和启动顺序符合要求。

总结

MPU9250作为一款集成了九轴传感器的高性能IMU,凭借其小巧的体积、低功耗和多种通信接口,成为了广泛应用于无人机、机器人、可穿戴设备和VR等领域的首选传感器模块。其内部集成的DMP不仅简化了外部数据处理,也为实现高精度姿态估计提供了强有力的支持。然而,在实际应用中,校准、磁干扰和信号完整性等问题依然需要开发者认真对待,通过软硬件设计优化实现更稳定可靠的系统。

需要源代码可收藏加关注在评论留下邮箱获取!!!

审核编辑 黄宇

查看全文

点赞

慧生活

作者最近更新

  • 反射式光电位置传感器在编码器中的应用
    慧生活
    22小时前
  • 智能焊接新实践:焊缝跟踪传感器在柴孚机器人精致钢焊接中的应用
    慧生活
    23小时前
  • 光伏电站进入“精管时代”?芯森电子AN3V如何帮运维人员盯住每一串电流?
    慧生活
    22小时前

期刊订阅

相关推荐

  • 影响MEMS传感器精度的重要参数及提升精度的办法

    2019-03-28

  • 从MEMS专利数量分析我国MEMS传感器产业现状

    2019-03-28

  • 我国建首个地下云图网:借助新型传感器助力地震预报

    2018-12-04

  • 我国开发出世界首台流体壁面剪应力测试仪

    2019-03-22

评论0条评论

×
私信给慧生活

点击打开传感搜小程序 - 速览海量产品,精准对接供需

  • 收藏

  • 评论

  • 点赞

  • 分享

收藏文章×

已选择0个收藏夹

新建收藏夹
完成
创建收藏夹 ×
取消 保存

1.点击右上角

2.分享到“朋友圈”或“发送给好友”

×

微信扫一扫,分享到朋友圈

推荐使用浏览器内置分享功能

×

关注微信订阅号

关注微信订阅号,了解更多传感器动态

  • #{faceHtml}

    #{user_name}#{created_at}

    #{content}

    展开

    #{like_count} #{dislike_count} 查看评论 回复

    共#{comment_count}条评论

    加载更多

  • #{ahtml}#{created_at}

    #{content}

    展开

    #{like_count} #{dislike_count} #{reback} 回复

  • #{ahtml}#{created_at}

    #{content}

    展开

    #{like_count} #{dislike_count} 回复

  • 关闭
      广告