MPU6050 超详细读取数据步骤
·
目录
4、将2个字节转换成1个有符号半字,用来处理寄存器的高低位数据函数:
5、读取MPU6050设备ID函数(不要这个函数也是可以的):
8.1推荐用原始数据除灵敏度来求加速度角速度。公式: 加(角)速度值 = 原始数据 / 灵敏度
👉也可通过串口发送到VOFA+,可以更加直观的观察数据的变化:
零、软件I2C配置
一、MPU6050硬件部分
二、MPU6050软件部分。
👉👉👉完整程序编写步骤:
0、MPU6050.h文件内容:
#ifndef __MPU6050_H
#define __MPU6050_H
#define MPU6050_ADDRESS 0xD0 //MPU6050的I2C从机地址
#define MPU6050_SMPLRT_DIV 0x19 //采样频率分频器
#define MPU6050_CONFIG 0x1A //配置
#define MPU6050_GYRO_CONFIG 0x1B //陀螺仪配置
#define MPU6050_ACCEL_CONFIG 0x1C //加速度计配置
#define MPU6050_ACCEL_XOUT_H 0x3B //加速度计X轴高位
#define MPU6050_ACCEL_XOUT_L 0x3C //加速度计X轴底位
#define MPU6050_ACCEL_YOUT_H 0x3D //加速度计Y轴高位
#define MPU6050_ACCEL_YOUT_L 0x3E //加速度计Y轴底位
#define MPU6050_ACCEL_ZOUT_H 0x3F //加速度计Z轴高位
#define MPU6050_ACCEL_ZOUT_L 0x40 //加速度计Z轴底位
#define MPU6050_TEMP_OUT_H 0x41 //温度测量值高位
#define MPU6050_TEMP_OUT_L 0x42 //温度测量值低位
#define MPU6050_GYRO_XOUT_H 0x43 //陀螺仪X轴高位
#define MPU6050_GYRO_XOUT_L 0x44 //陀螺仪X轴低位
#define MPU6050_GYRO_YOUT_H 0x45 //陀螺仪Y轴高位
#define MPU6050_GYRO_YOUT_L 0x46 //陀螺仪Y轴低位
#define MPU6050_GYRO_ZOUT_H 0x47 //陀螺仪Z轴高位
#define MPU6050_GYRO_ZOUT_L 0x48 //陀螺仪Z轴低位
#define MPU6050_PWR_MGMT_1 0x6B //电源管理1
#define MPU6050_PWR_MGMT_2 0x6C //电源管理2
#define MPU6050_WHO_AM_I 0x75 //设备ID
void MPU6050_Init(void); //初始化
uint8_t MPU6050_GetID(void); //读取ID
void MPU6050_GetACCEL(int16_t *ACCEL_Array); //读取加速度计原始数据
void MPU6050_GetGYRO(int16_t *GYRO_Array); //读取陀螺仪原始数据
void MPU6050_GetAccel_Value(float *Accel_Value); //读取转换后的加速度计数值
void MPU6050_GetGyro_Value(float *Gyro_Value); //读取转换后的陀螺仪数值
#endif
1、新建MPU6050.c和MPU6050.h文件:
---------------------------------------------------------------------------------------------------------------------------------
2、写MPU6050寄存器函数
2、1写单个字节:
#include "stm32f10x.h" // Device header
#include "MyI2C.h"
#include "MPU6050.h"
/**
* 函数功能:MPU6050写1个寄存器
* 入口参数:Reg: 需要操作的MPU6050地址
* 入口参数:Data:需要写入的数据
* 返 回 值:无
*/
void MPU6050_WriteReg(uint8_t Reg, uint8_t Data)
{
/*发送从机地址*/
MyI2C_Start(); //I2C起始
MyI2C_SendByte(MPU6050_ADDRESS); //发送MPU6050地址 0xD0 第0位为0是写操作,1是读操作
MyI2C_ReceiveAck(); //接收应答,我这里只接收,不作处理。
/*发送需要写操作的寄存器*/
MyI2C_SendByte(Reg);
MyI2C_ReceiveAck();
/*发送需要写入的数据*/
MyI2C_SendByte(Data);
MyI2C_ReceiveAck();
MyI2C_Stop(); //I2C终止
}
2、2连续写多个字节:
/**
* 函数功能:MPU6050写多个字节
* 入口参数:BufAddress:寄存器首地址
* 入口参数:BufData :数据首地址
* 入口参数:Length :写入的字节数量
* 返 回 值:无
*/
void MPU6050_WriteBuf(uint8_t BufAddress, uint8_t *BufData, uint8_t Length)
{
uint8_t i; //for循环次数变量
MyI2C_Start(); //起始
MyI2C_SendByte(MPU6050_ADDRESS | 0x00); //发送从机地址 | 写模式
MyI2C_ReceiveAck(); //接收应答
MyI2C_SendByte(BufAddress); //发送寄存器首地址
MyI2C_ReceiveAck(); //接收应答
for (i = 0; i < Length; i++)
{
MyI2C_SendByte(BufData[i]); //连续写入数据
MyI2C_ReceiveAck(); //接收应答
}
MyI2C_Stop(); //停止
}
3、读MPU6050寄存器函数
3、1读单个字节:
/**
* 函数功能:读取MPU6050寄存器里的数据
* 入口参数:Reg:需要读取的寄存器地址
* 返 回 值:读取到的数据
*/
uint8_t MPU6050_ReadReg(uint8_t Reg)
{
uint8_t Reg_Data; //定义保存读取到的数据变量
/*发送从机地址*/
MyI2C_Start(); //I2C起始
MyI2C_SendByte(MPU6050_ADDRESS); //MPU6050默认地址:0xD0
MyI2C_ReceiveAck(); //接收MPU6050应答位
/*发送需要读取的寄存器地址*/
MyI2C_SendByte(Reg);
MyI2C_ReceiveAck();
/*发送读取模式*/
MyI2C_Start(); //I2C起始
MyI2C_SendByte(MPU6050_ADDRESS | 0x01); //发送MPU6050地址0xD0 | 0x01 (第0位为0是写操作,1是读操作)
MyI2C_ReceiveAck();
/*开始读取从机数据*/
Reg_Data = MyI2C_ReceiveByte(); //读取MPU6050的数据
MyI2C_SendAck(1); //读取完成后,应答位给1(非应答)
MyI2C_Stop(); //I2C终止
return Reg_Data; //返回读取到的数据
}
3、2连续读多个字节:
/**
* 函数功能:连续读MPU6050寄存器
* 入口参数:BufAddress:寄存器首地址
* 入口参数:BufData :接收数据首地址
* 入口参数:Length :读取寄存器的数量
*/
void MPU6050_ReadBuf(uint8_t BufAddress, uint8_t *BufData, uint8_t Length)
{
uint8_t i; //for循环次数变量
MyI2C_Start(); //起始
MyI2C_SendByte(MPU6050_ADDRESS | 0x00); //发送从机地址 | 写模式
MyI2C_ReceiveAck(); //接收应答
MyI2C_SendByte(BufAddress); //发送寄存器地址
MyI2C_ReceiveAck(); //接收应答
MyI2C_Start(); //起始
MyI2C_SendByte(MPU6050_ADDRESS | 0x01); //发送从机地址 | 读模式
MyI2C_ReceiveAck(); //接收应答
/*连续读取数据*/
for (i = 0; i < Length; i++)
{
BufData[i] = MyI2C_ReceiveByte(); //把数据存放在i指向的变量
if( i < (Length - 1) )
{
MyI2C_SendAck(0); //发送应答
}
else
{
MyI2C_SendAck(1); //最后一个要发送非应答
}
}
MyI2C_Stop(); //停止
}
4、将2个字节转换成1个有符号半字,用来处理寄存器的高低位数据函数:
/**
* 函数功能:将2个字节转换成1个有符号半字,用来处理寄存器的高低位数据。
* 入口参数:DataL:低位字节
* 入口参数:DataH: 高位字节
* 返 回 值:转换完成后的有符号数据
*/
int16_t MPU6050_Byte_to_HalfWord(uint8_t DataL, uint8_t DataH)
{
int16_t Data;
Data = (DataH << 8) | DataL; //DataL放到低8位, DataH放到高8位
return Data; //返回转换后的数据
}
5、读取MPU6050设备ID函数(不要这个函数也是可以的):
/**
* 函数功能:读取MPU6050设备ID
* 入口参数:无
* 返 回 值:设备ID
*/
uint8_t MPU6050_GetID(void)
{
uint8_t ID = 0;
ID = MPU6050_ReadReg(MPU6050_WHO_AM_I); //读取设备ID 寄存器:0x75
return ID;
}
6、读取加速度计原始数值函数:
/**
* 函数功能:读取加速度计原始数值
* 入口参数:ACCEL_Array: X轴保存到外部的第0个元素
Y轴保存到外部的第1个元素
Z轴保存到外部的第2个元素
* 返 回 值:无
*/
void MPU6050_GetACCEL(int16_t *ACCEL_Array)
{
uint8_t DataL; //定义保存数据低位变量
uint8_t DataH; //定义保存数据高位变量
/*读取加速度计原始数值,寄存器地址含义需要翻手册的描述*/
DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L); //读取X轴低位数据到DataL
DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H); //读取X轴高位数据到DataH
ACCEL_Array[0] = MPU6050_Byte_to_HalfWord(DataL, DataH); //调用转换函数,将X轴转换结果存放到ACCEL_Array[0]
DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L); //读取Y轴低位数据到DataL
DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H); //读取Y轴高位数据到DataH
ACCEL_Array[1] = MPU6050_Byte_to_HalfWord(DataL, DataH); //调用转换函数,将Y轴转换结果存放到ACCEL_Array[1]
DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L); //读取Z轴低位数据到DataL
DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H); //读取Z轴高位数据到DataH
ACCEL_Array[2] = MPU6050_Byte_to_HalfWord(DataL, DataH); //调用转换函数,将Z轴转换结果存放到ACCEL_Array[2]
}
7、读取陀螺仪原始数值函数:
/**
* 函数功能: 读取陀螺仪原始数值
* 入口参数:ACCEL_Array: X轴保存到第0个元素
Z轴保存到第2个元素
Y轴保存到第1个元素
* 返 回 值:无
*/
void MPU6050_GetGYRO(int16_t *GYRO_Array)
{
uint8_t DataL; //定义数据低位变量
uint8_t DataH; //定义数据高位变量
DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L); //读取X轴低位数据到DataL
DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H); //读取X轴高位数据到DataH
GYRO_Array[0] = MPU6050_Byte_to_HalfWord(DataL, DataH); //调用转换函数,将X轴转换结果存放到GYRO_Array[0]
DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L); //读取Y轴低位数据到DataL
DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H); //读取Y轴高位数据到DataH
GYRO_Array[1] = MPU6050_Byte_to_HalfWord(DataL, DataH); //调用转换函数,将Y轴转换结果存放到GYRO_Array[1]
DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L); //读取Z轴低位数据到DataL
DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H); //读取Z轴高位数据到DataH
GYRO_Array[2] = MPU6050_Byte_to_HalfWord(DataL, DataH); //调用转换函数,将Z轴转换结果存放到GYRO_Array[2]
}
8、线性标度变换函数(用来将原始数据转换成我们需要的):
8.1推荐用原始数据除灵敏度来求加速度角速度。公式: 加(角)速度值 = 原始数据 / 灵敏度
1、 角速度量程对应灵敏度:
2、 加速度计量程对应灵敏度:
/**
* 函数功能:线性标度变换
* 入口参数:Sample_Value: 采样回来的原始数值
* 入口参数:URV: 量程上限
* 入口参数:LRV: 量程下限
* 返 回 值:变换后的数据
*/
float Scale_Transform(float Sample_Value, float URV, float LRV)
{
float Data; //定义用来保存变换后的数据变量
float Value_L = -32767.0; //定义采样值下限变量 MPU6050寄存器是16位的,最高位是符号位,
float Value_U = 32767.0; //定义采样值上限变量 所以寄存器输出范围是-7FFF~7FFF,对应十进制-32767~32767
/* 公式:当前数据 =(采样值 - 采样值下限)/(采样值上限 - 采样值下限)*(量程上限 - 量程下限)+ 量程下限 */
Data = (Sample_Value - Value_L) / (Value_U - Value_L) * (URV - LRV) + LRV;
return Data;
}
9、读取转换后加速度计数值函数:
/**
* 函数功能:读取转换后加速度计数值
* 入口参数:Accel_Value:加速度值转换后保存的变量
* 返 回 值:无
*/
void MPU6050_GetAccel_Value(float *Accel_Value)
{
int16_t ACCEL_Array[3]; //定义用来保存加速度计原始数值的变量
/*读取加速度计原始数值*/
MPU6050_GetACCEL(ACCEL_Array);
/*开始转换加速度值*/
Accel_Value[0] = Scale_Transform( (float)ACCEL_Array[0], 16.0, -16.0); //转换X轴
Accel_Value[1] = Scale_Transform( (float)ACCEL_Array[1], 16.0, -16.0); //转换Y轴
Accel_Value[2] = Scale_Transform( (float)ACCEL_Array[2], 16.0, -16.0); //转换Z轴
}
10、读取转换后的陀螺仪数值函数:
/**
* 函数功能:读取转换后的陀螺仪数值
* 入口参数:Gyro_Value:陀螺仪转换后保存的变量
* 返 回 值:无
*/
void MPU6050_GetGyro_Value(float *Gyro_Value)
{
/*定义用来保存陀螺仪原始数值的数组*/
int16_t GYRO_Array[3];
/*读取陀螺仪的原始数值,保存到GYRO_Array[]数组中*/
MPU6050_GetGYRO(GYRO_Array);
/*开始转换陀螺仪值*/
Gyro_Value[0] = Scale_Transform( (float)GYRO_Array[0], 2000.0, -2000.0); //转换X轴
Gyro_Value[1] = Scale_Transform( (float)GYRO_Array[1], 2000.0, -2000.0); //转换Y轴
Gyro_Value[2] = Scale_Transform( (float)GYRO_Array[2], 2000.0, -2000.0); //转换Z轴
}
11、初始化MPU6050函数:
/**
* 函数功能:初始化MPU6050
* 入口参数:无
* 返 回 值:无
*/
void MPU6050_Init(void)
{
/*调用软件I2C初始化函数*/
MyI2c_Init();
/*MPU6050寄存器初始化, 需要对照手册描述来配置*/
MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01); //电源管理1寄存器,取消睡眠模式,选择时钟源为X轴陀螺仪
MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00); //电源管理2寄存器,保持默认值,所有轴不休眠。
MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09); //采样率分频寄存器,
MPU6050_WriteReg(MPU6050_CONFIG, 0x06); //配置寄存器
MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18); //陀螺仪配置寄存器,选择满量程 ±2000°/s
MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18); //加速度计配置寄存器,选择满量程 ±16g
}
12、最后在主程序中调用两个读取函数:
#include "stm32f10x.h" // Device header
#include "MPU6050.h"
#include "OLED.h"
uint8_t MPU6050_Who = 0; //定义保存MPU6050 设备ID变量
float MPU6050_ACCEL_Value[3]; //定义保存MPU6050加速度计数据数组
float MPU6050_GYRO_Value[3]; //定义保存MPU6050陀螺仪数据数组
int main(void)
{
OLED_Init(); //OLED初始化
MPU6050_Init(); //MPU6050初始化
MPU6050_Who = MPU6050_GetID(); //读取MPU6050 ID
OLED_Printf(0, 0, OLED_8X16, "ID:%X", MPU6050_Who); //显示ID
OLED_Update();
while(1)
{
/*读取MPU6050数据*/
MPU6050_GetAccel_Value(MPU6050_ACCEL_Value); //读取加速度计的值
MPU6050_GetGyro_Value(MPU6050_GYRO_Value); //读取陀螺仪的值
/*在0.96寸OLED屏幕上显示数据*/
OLED_ShowFloatNum(0, 16, MPU6050_ACCEL_Value[0], 2, 2, OLED_8X16); //加速度X轴
OLED_ShowFloatNum(0, 32, MPU6050_ACCEL_Value[1], 2, 2, OLED_8X16); //加速度Y轴
OLED_ShowFloatNum(0, 48, MPU6050_ACCEL_Value[2], 2, 2, OLED_8X16); //加速度Z轴
OLED_ShowFloatNum(64, 16, MPU6050_GYRO_Value[0], 2, 2, OLED_8X16); //陀螺仪X轴
OLED_ShowFloatNum(64, 32, MPU6050_GYRO_Value[1], 2, 2, OLED_8X16); //陀螺仪Y轴
OLED_ShowFloatNum(64, 48, MPU6050_GYRO_Value[2], 2, 2, OLED_8X16); //陀螺仪Z轴
OLED_Update();
}
}
👉最后观察现象:
👉也可通过串口发送到VOFA+,可以更加直观的观察数据的变化:
更多推荐
已为社区贡献1条内容
所有评论(0)