0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

jf_88434166 来源:jf_88434166 作者:jf_88434166 2025-09-24 16:14 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、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不仅简化了外部数据处理,也为实现高精度姿态估计提供了强有力的支持。然而,在实际应用中,校准、磁干扰和信号完整性等问题依然需要开发者认真对待,通过软硬件设计优化实现更稳定可靠的系统。

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

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 传感器
    +关注

    关注

    2574

    文章

    54452

    浏览量

    786550
  • STM32F
    +关注

    关注

    1

    文章

    42

    浏览量

    18713
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    零知开源——STM32F103RBT6驱动 ICM20948 传感器及 vofa + 上位机可视化教程

    本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948传感器,实现
    的头像 发表于 06-09 14:01 1259次阅读
    零知开源——<b class='flag-5'>STM32F103RBT6</b><b class='flag-5'>驱动</b> ICM20948 <b class='flag-5'>九</b><b class='flag-5'>轴</b><b class='flag-5'>传感器</b>及 vofa + 上位机可视化教程

    基于stm32mpu9250的usb hid键盘、鼠标、游戏控制实例打包下载

    基于stm32mpu9250的usb hid键盘、鼠标、游戏控制实例打包,推荐下载!
    发表于 05-29 21:44

    基于stm32mpu9250的usb hid键盘、鼠标、游戏控制

    基于stm32mpu9250的usb hid键盘、鼠标、游戏控制 项目实例下载! 纯分享帖,需要者可点击附件免费获取完整资料~~~【免责声明】本文系网络转载,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请
    发表于 05-23 20:53

    STM32F103C6T6 DCAC逆变器原理图

    STM32F103C6T6 DCAC逆变器原理图
    发表于 05-19 17:48 2次下载

    stm32f103c8t6主控芯片无人机原理图

    stm32f103c8t6主控芯片无人机原理图
    发表于 04-29 17:02 2次下载

    STM32F103C8T6无法选择外部晶振怎么解决?

    我从网上购入了STM32F103C8T6的核心板,板上有外部晶振。但我使用STM32CubeMX生成项目时,却无法选择外部晶振(如下图)。请问要在哪里设置才能选择外部晶振呀?
    发表于 04-28 07:03

    基于STM32F103C8T6控制多路VL53L0X激光测距传感器

    使用STM32F103C8T6的一条IIC总线控制4个激光测距传感器,我使用的激光测距传感器是亚博智能的 地址相同改不了,我要怎么控制多路,求指点
    发表于 04-23 18:23

    STM32F103C8T6开发板最小系统原理图

    电子发烧友网站提供《STM32F103C8T6开发板最小系统原理图》资料免费下载
    发表于 03-24 09:09 83次下载

    使用iic对mpu9250进行读取数据读取磁力计数据时采用的是主控iic方式,但是读取的速度特别慢,为什么?

    使用iic对mpu9250进行读取数据读取磁力计数据时采用的是主控iic方式,但是读取的速度特
    发表于 03-14 07:40

    stm32f103c8t6没有对flash进行任何操作,flash的内容发生变化了,是哪些原因?

    stm32f103c8t6:没有对flash进行任何操作,flash的内容发生变化了。具体是哪些原因?如何调试排查原因。
    发表于 03-14 07:14

    stm32f103c8t6编码模式在keil的debug调试时遇到的问题求解

    stm32f103c8t6编码模式在keil的debug调试时,手动把编码的计数置为一个数500(比如计数溢出值是4000),然后在
    发表于 03-14 06:06

    STM32F103C8T6 PA2无PWM输出怎么解决?

    STM32F103C8T6最小系统PA0/PA1/PA2/PA3为PWM输出控制舵机,配置相同,PA2始终无输出,PA0/PA1/PA3输出正常;用试验软件对STM32F103C8T6最小系统PA2口验证能输出高/低电平。
    发表于 02-27 08:13

    基于STM32F103V8T6的智能水处理系统设计与实现

    基于 STM32F103V8T6 的智能水处理装置设计 摘要 : 本文基于 STM32F103V8T6 微控制,设计并实现了一款智能水处理装置。该装置集多种传感器与电源管理模块于一体
    的头像 发表于 02-19 14:16 1182次阅读
    基于<b class='flag-5'>STM32F103V8T6</b>的智能水处理系统设计与实现

    基于STM32F103C8T6 ADXL345 加速度传感器的计步器设计指南和代码

    基于 STM32F103C8T6 微控制和 ADXL345 加速度传感器的计步器设计相关内容,包括 ADXL345 传感器的工作原理、初始化与数据
    的头像 发表于 01-17 17:38 2707次阅读

    STM32单片机+MPU6050设计一个电子水平仪

    本项目基于STM32F103C8T6单片机设计一款电子水平仪。STM32F103C8T6作为一种性能强大的微控制,具有较高的计算能力和丰富的外设接口,能够满足项目对实时数据处理和显示
    的头像 发表于 01-09 11:14 2667次阅读
    <b class='flag-5'>STM32</b>单片机+<b class='flag-5'>MPU</b>6050设计一个电子水平仪