【STM32】I2C练习,HAL库读取MPU6050角度陀螺仪

简介: 【STM32】I2C练习,HAL库读取MPU6050角度陀螺仪

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的读取,对于六轴的算法还有很多,可以转移到别的博主文章进行学习参考。


相关文章
|
8天前
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
36 2
|
8天前
|
存储 数据采集 数据安全/隐私保护
使用STM32F103读取TF卡并模拟U盘:使用标准库实现
通过以上步骤,你可以实现用STM32F103将TF卡内容变成U盘进行读取。这种功能在数据采集、便携式存储设备等应用中非常有用。如果你有更多的需求,可以进一步扩展此项目,例如添加文件管理功能、加密存储等。希望这篇博客能帮到你,如果有任何问题,欢迎在评论区留言讨论!
14 1
|
8天前
|
IDE 开发工具
使用STM32F103标准库实现自定义键盘
通过本文,我们学习了如何使用STM32F103标准库实现一个简单的自定义键盘。我们首先初始化了GPIO引脚,然后实现了一个扫描函数来检测按键状态。这个项目不仅能够帮助我们理解STM32的GPIO配置和按键扫描原理,还可以作为进一步学习中断处理和低功耗设计的基础。希望本文对你有所帮助,祝你在嵌入式开发的道路上不断进步!
18 4
|
9天前
|
传感器
【经典案例】STM32F407使用HAL库配置I2C详解
STM32F407是一个强大的微控制器,广泛应用于嵌入式系统中。在许多应用中,我们需要使用I2C总线来与传感器、EEPROM、显示屏等外设进行通信。本文将详细介绍如何使用STM32 HAL库来配置和使用I2C接口。
19 2
|
9天前
|
开发者
【经典案例】使用HAL库配置STM32F407的SPI外设
在嵌入式系统开发中,STM32F407是一款广泛应用的微控制器,而SPI(Serial Peripheral Interface)是一种常用的通信接口。本文将详细介绍如何使用STM32的硬件抽象层(HAL)库配置STM32F407的SPI外设,并提供完整的代码示例。
22 1
|
1月前
|
缓存 网络协议 算法
[蓝桥杯嵌入式]hal库 stm32 PWM的使用(随时修改占空比,随时修改频率)
[蓝桥杯嵌入式]hal库 stm32 PWM的使用(随时修改占空比,随时修改频率)
|
1月前
【STM32】基于HAL库的360度编码器、摇杆代码编写
【STM32】基于HAL库的360度编码器、摇杆代码编写
|
1月前
|
传感器
|
1月前
|
传感器 存储 缓存