MPU6050简介
MPU-6000(6050)为全球首例整合性6轴运动处理组件,相较于多组件方案,免除了组合陀螺仪与加速器时间轴之差的问题,减少了大量的封装空间。当连接到三轴磁强计时,MPU-60X0提供完整的9轴运动融合输出到其主I2C或SPI端口(SPI仅在MPU-6000上可用)。
寄存器查询表格
寄存器地址 | 寄存器内容 |
0X3B | X轴加速度测量值高位 |
0X3C | X轴加速度测量值低位 |
0X3D | Y轴加速度测量值高位 |
0X3E | Y轴加速度测量值低位 |
0X3F | Z轴加速度测量值高位 |
0X40 | Z轴加速度测量值低位 |
0X41 | 温度测量值高位 |
0X42 | 温度测量值低位 |
0X43 | X轴角度测量值高位 |
0X34 | X轴角度测量值低位 |
0X45 | Y轴角度测量值高位 |
0X46 | Y轴角度测量值低位 |
0X47 | Z轴角度测量值高位 |
0X48 | Z轴角度测量值低位 |
0X6B | 电源管理,典型值:0x00(正常启用) |
STM32CubeMx配置
配置使用外部高速时钟
配置调试方式
配置I2C,这里只需要选择I2C即可其余配置默认,记住自己选择的I2C引脚。
配置时钟
生成工程
代码文件
mpu6050.h文件
#ifndef __MPU6050_H #define __MPU6050_H #include "main.h" #define SMPLRT_DIV 0x19 // 采样率分频,典型值:0x07(125Hz) */ #define CONFIG 0x1A // 低通滤波频率,典型值:0x06(5Hz) */ #define GYRO_CONFIG 0x1B // 陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s) */ #define ACCEL_CONFIG 0x1C // 加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz) */ #define ACCEL_XOUT_H 0x3B // 存储最近的X轴、Y轴、Z轴加速度感应器的测量值 */ #define ACCEL_XOUT_L 0x3C #define ACCEL_YOUT_H 0x3D #define ACCEL_YOUT_L 0x3E #define ACCEL_ZOUT_H 0x3F #define ACCEL_ZOUT_L 0x40 #define TEMP_OUT_H 0x41 // 存储的最近温度传感器的测量值 */ #define TEMP_OUT_L 0x42 #define GYRO_XOUT_H 0x43 // 存储最近的X轴、Y轴、Z轴陀螺仪感应器的测量值 */ #define GYRO_XOUT_L 0x44 #define GYRO_YOUT_H 0x45 #define GYRO_YOUT_L 0x46 #define GYRO_ZOUT_H 0x47 #define GYRO_ZOUT_L 0x48 #define PWR_MGMT_1 0x6B // 电源管理,典型值:0x00(正常启用) */ #define WHO_AM_I 0x75 // IIC地址寄存器(默认数值0x68,只读) */ #define MPU6050_ADDR 0xD0 // MPU6050手册上的地址,这里也可以使用serch函数去搜索 typedef struct{ // 角速度 float Accel_X; float Accel_Y; float Accel_Z; // 角度 float Gyro_X; float Gyro_Y; float Gyro_Z; // 温度 float Temp; }MPU6050DATATYPE; extern MPU6050DATATYPE Mpu6050_Data; extern I2C_HandleTypeDef hi2c1; extern I2C_HandleTypeDef hi2c2; int16_t Sensor_I2C2_Serch(void); int8_t MPU6050_Init(int16_t Addr); int8_t Sensor_I2C2_ReadOneByte(uint16_t DevAddr, uint16_t MemAddr, uint8_t *oData); int8_t Sensor_I2C2_WriteOneByte(uint16_t DevAddr, uint16_t MemAddr, uint8_t *iData); void MPU6050_Read_Accel(void); void MPU6050_Read_Gyro(void); void MPU6050_Read_Temp(void); #endif
mpu6050.c文件
#include "mpu6050.h" static int16_t Mpu6050Addr = 0x68; MPU6050DATATYPE Mpu6050_Data; int8_t Sensor_I2C2_Read(uint16_t DevAddr, uint16_t MemAddr, uint8_t *oData, uint8_t DataLen) { return HAL_I2C_Mem_Read(&hi2c2,DevAddr,MemAddr,1,oData,DataLen,1000); } int8_t Sensor_I2C2_Write(uint16_t DevAddr, uint16_t MemAddr, uint8_t *iData, uint8_t DataLen) { return HAL_I2C_Mem_Write(&hi2c2,DevAddr,MemAddr,1,iData,DataLen,1000); } int16_t Sensor_I2C2_Serch(void) { for(uint8_t i = 1; i < 255; i++) { if(HAL_I2C_IsDeviceReady(&hi2c2, i, 1, 1000) == HAL_OK) { Mpu6050Addr = i; return i; } } return 0xD1; } int8_t MPU6050_Init(int16_t Addr) { uint8_t check; HAL_I2C_Mem_Read(&hi2c2,Addr,WHO_AM_I,1,&check,1,1000); if(check == 0x68) // 确认设备用 地址寄存器 { check = 0x00; Sensor_I2C2_Write(Addr,PWR_MGMT_1,&check, 1); // 唤醒 check = 0x07; Sensor_I2C2_Write(Addr,SMPLRT_DIV,&check, 1); // 1Khz的速率 check = 0x00; Sensor_I2C2_Write(Addr,ACCEL_CONFIG,&check, 1); // 加速度配置 check = 0x00; Sensor_I2C2_Write(Addr,GYRO_CONFIG,&check, 1); // 陀螺配置 return 0; } return -1; } void MPU6050_Read_Accel(void) { uint8_t Read_Buf[6]; // 寄存器依次是加速度X高 - 加速度X低 - 加速度Y高位 - 加速度Y低位 - 加速度Z高位 - 加速度度Z低位 Sensor_I2C2_Read(Mpu6050Addr, ACCEL_XOUT_H, Read_Buf, 6); Mpu6050_Data.Accel_X = (int16_t)(Read_Buf[0] << 8 | Read_Buf[1]); Mpu6050_Data.Accel_Y = (int16_t)(Read_Buf[2] << 8 | Read_Buf[3]); Mpu6050_Data.Accel_Z = (int16_t)(Read_Buf[4] << 8 | Read_Buf[5]); Mpu6050_Data.Accel_X = Mpu6050_Data.Accel_X / 16384.0f; Mpu6050_Data.Accel_Y = Mpu6050_Data.Accel_Y / 16384.0f; Mpu6050_Data.Accel_Z = Mpu6050_Data.Accel_Z / 16384.0f; } void MPU6050_Read_Gyro(void) { uint8_t Read_Buf[6]; // 寄存器依次是角度X高 - 角度X低 - 角度Y高位 - 角度Y低位 - 角度Z高位 - 角度Z低位 Sensor_I2C2_Read(Mpu6050Addr, GYRO_XOUT_H, Read_Buf, 6); Mpu6050_Data.Gyro_X = (int16_t)(Read_Buf[0] << 8 | Read_Buf[1]); Mpu6050_Data.Gyro_Y = (int16_t)(Read_Buf[2] << 8 | Read_Buf[3]); Mpu6050_Data.Gyro_Z = (int16_t)(Read_Buf[4] << 8 | Read_Buf[5]); Mpu6050_Data.Gyro_X = Mpu6050_Data.Gyro_X / 131.0f; Mpu6050_Data.Gyro_Y = Mpu6050_Data.Gyro_Y / 131.0f; Mpu6050_Data.Gyro_Z = Mpu6050_Data.Gyro_Z / 131.0f; } void MPU6050_Read_Temp(void) { uint8_t Read_Buf[2]; Sensor_I2C2_Read(Mpu6050Addr, TEMP_OUT_H, Read_Buf, 2); Mpu6050_Data.Temp = (int16_t)(Read_Buf[0] << 8 | Read_Buf[1]); Mpu6050_Data.Temp = 36.53f + (Mpu6050_Data.Temp / 340.0f); }
main.c文件
MPU6050_Init(Sensor_I2C2_Serch()); while(1) { HAL_Delay(500); MPU6050_Read_Accel(); MPU6050_Read_Gyro(); MPU6050_Read_Temp(); }
总结
MPU6050的数据的读取非常的简单,但是这个数据还无法直接使用,这里我只是用来联系I2C的读取,对于六轴的算法还有很多,可以转移到别的博主文章进行学习参考。