当前位置: 首页 > 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.dtcms.com/a/326097.html

相关文章:

  • p6spy和p6spy-spring-boot-starter的SpringBoot3集成配置
  • 高性能Web服务器
  • java基础概念(二)----变量(附练习题)
  • Go 语言三大核心数据结构深度解析:数组、切片(Slice)与映射(Map)
  • Unity插件DOTween使用
  • 【GPT入门】第45课 无梯子,linux/win下载huggingface模型方法
  • 如何避免团队文件同步过程中版本信息的丢失?
  • GAI 与 Tesla 机器人的具体联动机制
  • 变频器与伺服系统的工作原理,干扰来源及治理方式
  • 软件测试关于搜索方面的测试用例
  • [AI 生成] kafka 面试题
  • 是否有必要使用 Oracle 向量数据库?
  • 【图像处理基石】UE输出渲染视频,有哪些画质相关的维度和标准可以参考?
  • OmniHuman:字节推出的AI项目,支持单张照片生成逼真全身动态视频
  • 不同FPGA开发板系统移植步骤
  • 《C++中 type_traits 的深入解析与应用》
  • 【Docker实战进阶】Docker 实战命令大全
  • “底层闭源 + Lua 脚本” 开发模式
  • 缺省路由的内容
  • 基于51单片机指纹识别管理门禁密码锁系统设计
  • “鱼书”深度学习进阶笔记(3)第四章
  • Spring Boot文件下载功能实现详解
  • Spring Boot 2.6.0+ 循环依赖问题及解决方案
  • C#高级语法_泛型
  • ClickHouse列式数据库的使用场景与基本优化手段
  • Jmeter使用第二节-接口测试(Mac版)
  • ​费马小定理​
  • jmeter 设置随机数
  • 爬虫与数据分析结合:中国大学排名案例学习报告
  • 【FAQ】Win11创建资源不足绕开微软账号登录