当前位置: 首页 > news >正文

STM32 HAL驱动MPU6050传感器

STM32 HAL驱动MPU6050传感器

项目概述

本项目实现了基于STM32 HAL库的MPU6050传感器驱动,可以读取加速度计和陀螺仪数据。项目使用I2C接口与MPU6050通信,并通过UART接口输出数据。

项目仓库地址:STM32_Sensor_Drives

硬件连接

在这里插入图片描述

MPU6050 I2C接口

PB10 ------> I2C2_SCL
PB11 ------> I2C2_SDA

UART调试接口

PA2 ------> USART2_TX
PA3 ------> USART2_RX

代码结构

项目主要包含以下文件:

  • main.c: 主程序入口,初始化外设并循环读取MPU6050数据
  • i2c.c/h: I2C配置和MPU6050驱动函数
  • usart.c/h: UART配置和printf重定向
  • gpio.c/h: GPIO配置

MPU6050驱动实现

数据结构定义

i2c.h中定义了MPU6050数据结构:

typedef struct _mpu6050_data{double ACCEL_X ,ACCEL_Y ,ACCEL_Z;double GYRO_X ,GYRO_Y ,GYRO_Z;
}mpu6050_data;

初始化函数

i2c.c中实现了MPU6050初始化函数:

void MPU6050_start(void)
{uint8_t SendAddress = 0x6b;uint8_t SendData  = 0x00; //解除休眠状态HAL_I2C_Mem_Write(&hi2c2,0xD1,SendAddress,1,&SendData,1,0xff);SendAddress = 0x19;//采样率分频器SendData = 0x07;HAL_I2C_Mem_Write(&hi2c2,0xD1,SendAddress,1,&SendData,1,0xff);SendAddress = 0x1A;//低通滤波器SendData = 0x06;HAL_I2C_Mem_Write(&hi2c2,0xD1,SendAddress,1,&SendData,1,0xff);SendAddress = 0x1B;//陀螺仪SendData = 0x08;   //± 500 °/sHAL_I2C_Mem_Write(&hi2c2,0xD1,SendAddress,1,&SendData,1,0xff);SendAddress = 0x1C;//加速度计SendData = 0x00;   //± 2gHAL_I2C_Mem_Write(&hi2c2,0xD1,SendAddress,1,&SendData,1,0xff);   
}

初始化步骤:

  1. 解除MPU6050休眠状态(寄存器0x6B)
  2. 设置采样率分频器(寄存器0x19)
  3. 配置低通滤波器(寄存器0x1A)
  4. 配置陀螺仪量程为±500°/s(寄存器0x1B)
  5. 配置加速度计量程为±2g(寄存器0x1C)

数据读取函数

i2c.c中实现了MPU6050数据读取函数:

void get_i2c_mpu6050(mpu6050_data *data){uint8_t MPU_Data[] = {0X00, 0X00,0X00, 0X00,0X00, 0X00,0X00, 0X00,0X00, 0X00,0X00, 0X00,0X00, 0X00};uint8_t preg1_Data  = 0x3B;HAL_I2C_Mem_Read(&hi2c2, 0xD1,preg1_Data,I2C_MEMADD_SIZE_8BIT,MPU_Data,14,50);float Temp = (MPU_Data[6]<<8)|MPU_Data[7];if(Temp>32768) Temp-=65536;Temp=(36.53+Temp/340);short int ACCEL_XOUT1 = ((MPU_Data[0]<<8)|MPU_Data[1]);data->ACCEL_X = (double)ACCEL_XOUT1/16384;short int ACCEL_YOUT1 = ((MPU_Data[2]<<8)|MPU_Data[3]);data->ACCEL_Y = (double)ACCEL_YOUT1/16384;short int ACCEL_ZOUT1 = ((MPU_Data[4]<<8)|MPU_Data[5]);data->ACCEL_Z = (double)ACCEL_ZOUT1/16384;short int GYRO_XOUT1 = ((MPU_Data[8]<<8)|MPU_Data[9]);data->GYRO_X = (double)GYRO_XOUT1/65.5;short int GYRO_YOUT1 = ((MPU_Data[10]<<8)|MPU_Data[11]);data->GYRO_Y = (double)GYRO_YOUT1/65.5;short int GYRO_ZOUT1 = ((MPU_Data[12]<<8)|MPU_Data[13]);data->GYRO_Z = (double)GYRO_ZOUT1/65.5;
}

数据读取步骤:

  1. 从寄存器0x3B开始,连续读取14个字节的数据
  2. 处理温度数据(虽然在本例中未使用)
  3. 处理加速度数据(前6个字节)
    • X轴加速度:字节0-1
    • Y轴加速度:字节2-3
    • Z轴加速度:字节4-5
    • 除以16384转换为g单位(±2g量程下)
  4. 处理陀螺仪数据(后6个字节)
    • X轴角速度:字节8-9
    • Y轴角速度:字节10-11
    • Z轴角速度:字节12-13
    • 除以65.5转换为°/s单位(±500°/s量程下)

I2C配置

I2C配置在i2c.c中实现:

void MX_I2C2_Init(void)
{hi2c2.Instance = I2C2;hi2c2.Init.ClockSpeed = 100000;hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;hi2c2.Init.OwnAddress1 = 0;hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;hi2c2.Init.OwnAddress2 = 0;hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;if (HAL_I2C_Init(&hi2c2) != HAL_OK){Error_Handler();}
}

主要配置:

  • 时钟速度:100kHz
  • 7位地址模式
  • 禁用时钟拉伸

UART配置与printf重定向

UART配置在usart.c中实现:

void MX_USART2_UART_Init(void)
{huart2.Instance = USART2;huart2.Init.BaudRate = 115200;huart2.Init.WordLength = UART_WORDLENGTH_8B;huart2.Init.StopBits = UART_STOPBITS_1;huart2.Init.Parity = UART_PARITY_NONE;huart2.Init.Mode = UART_MODE_TX_RX;huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart2.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart2) != HAL_OK){Error_Handler();}
}

为了支持printf函数,重定向了fputc函数:

int fputc(int ch, FILE *f)
{if (f == stdout)  // 仅处理标准输出{HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 100);  // 阻塞发送if (ch == '\n')  // 发送\n时自动补充\rHAL_UART_Transmit(&huart2, (uint8_t *)"\r", 1, 100);}return ch;
}

主程序

主程序在main.c中实现:

int main(void)
{/* 初始化代码省略 */MX_GPIO_Init();MX_USART2_UART_Init();MX_I2C2_Init();/* USER CODE BEGIN 2 */MPU6050_start();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */printf("System will start while\n");while (1){mpu6050_data data = {0};get_i2c_mpu6050(&data);printf("ax: %.3f--ay: %.3f--az: %.3f--gx: %.3f--gy: %.3f--gz: %.3f\n", data.ACCEL_X, data.ACCEL_Y, data.ACCEL_Z, data.GYRO_X, data.GYRO_Y, data.GYRO_Z);HAL_Delay(200);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

主程序流程:

  1. 初始化GPIO、UART和I2C外设
  2. 初始化MPU6050传感器
  3. 进入主循环
    • 读取MPU6050数据
    • 通过UART打印数据
    • 延时200ms

MPU6050寄存器说明

寄存器地址名称功能
0x6BPWR_MGMT_1电源管理1,用于设备复位、睡眠模式、时钟源等
0x19SMPLRT_DIV采样率分频器
0x1ACONFIG配置寄存器,主要用于配置DLPF(数字低通滤波器)
0x1BGYRO_CONFIG陀螺仪配置,设置量程等
0x1CACCEL_CONFIG加速度计配置,设置量程等
0x3B-0x40ACCEL_XOUT_H至ACCEL_ZOUT_L加速度计输出数据
0x41-0x42TEMP_OUT_H和TEMP_OUT_L温度传感器输出数据
0x43-0x48GYRO_XOUT_H至GYRO_ZOUT_L陀螺仪输出数据

注意事项

  1. MPU6050的I2C地址为0x68(二进制:1101000),但在代码中使用的是0xD1(二进制:11010001)。这是因为HAL库的I2C函数需要在7位地址后添加读/写位(0表示写,1表示读)。

  2. 加速度计和陀螺仪的原始数据都是16位有符号整数,需要进行转换才能得到实际的物理量:

    • 加速度计:在±2g量程下,除以16384得到以g为单位的加速度
    • 陀螺仪:在±500°/s量程下,除以65.5得到以°/s为单位的角速度
  3. 温度传感器的数据转换公式为:温度(°C) = 36.53 + (原始数据/340)

http://www.xdnf.cn/news/1278613.html

相关文章:

  • TradingAgents-CN: 基于多智能体的中文金融交易决策框架
  • 基于深度学习的异常检测算法在时间序列数据中的应用
  • 【深度学习3】向量化(Vectorization)
  • 广州建筑矢量数据分享,带高度,矢量文件
  • Day118 Spring Security
  • 论文阅读:Aircraft Trajectory Prediction Model Based on Improved GRU Structure
  • LabVIEW模糊逻辑控制车辆停靠
  • 视觉相机偏移补偿
  • .NET Core MVC中CSHTML
  • 嵌入式硬件中AI硬件设计方法与技巧
  • 18.WEB 服务器
  • docker compose和docker-compose命令的区别
  • Vue2篇——第二章 Vue从指令修饰符到侦听器的全面解析(重点)
  • MATLAB绘制水的蒸汽压曲线(Antoine方程)
  • jdk17下载安装教程【超详细图文】
  • 《设计模式》策略模式
  • vue3-基础语法
  • JUC学习笔记-----ReentrantLock
  • TC39x STM(System Timer)学习记录
  • 机器学习数学基础:46.Mann-Kendall 序贯检验(Sequential MK Test)
  • Spring Boot - 内置的9个过滤器用法
  • Day 9-2: Transformer翻译实例演示 - 翻译的基础设施
  • AI大模型 教师方向应用探索
  • Audio Flamingo
  • 第4章 程序段的反复执行4 多重循环练习(题及答案)
  • Python day40
  • C++ list类
  • 【深度学习新浪潮】遥感图像风格化迁移研究工作介绍
  • JS中typeof与instanceof的区别
  • 腾讯云EdgeOne KV存储在游戏资源发布中的技术实践与架构解析