news 2026/5/30 8:41:02

【STM32】基于HAL库的HC-SR04超声波测距:定时器输入捕获与温度补偿实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【STM32】基于HAL库的HC-SR04超声波测距:定时器输入捕获与温度补偿实战

1. HC-SR04超声波测距模块基础

HC-SR04是市面上最常见的低成本超声波测距模块,价格通常在10元以内,但测距效果却相当可靠。我第一次用这个模块是在大学做智能小车项目,当时就被它简单的四线接口和稳定的性能惊艳到了。

模块正面有两个金属圆筒,一个是发射器(T),一个是接收器(R)。工作时,发射器会发出40kHz的超声波脉冲,遇到障碍物反射后被接收器检测到。模块背面有四个引脚:

  • VCC:接3.3V或5V电源(实测5V时测距更远)
  • Trig:触发信号输入,给10us以上高电平启动测距
  • Echo:回响信号输出,高电平持续时间对应距离
  • GND:接地

工作时序特别简单:给Trig脚一个10us以上的高电平脉冲,模块就会自动发射8个40kHz的超声波脉冲,然后Echo脚会输出一个高电平,这个高电平的持续时间就是从发射到接收的时间差t。距离计算公式为:距离 = (t × 声速)/2。这里的除以2是因为声波是往返时间。

2. STM32硬件连接与CubeMX配置

我用的是STM32F103C8T6最小系统板,成本不到20元,完全够用。连接方式如下:

  • VCC → 5V
  • Trig → PA1(任意GPIO均可)
  • Echo → PA0(必须连接支持输入捕获的定时器通道)
  • GND → GND

在CubeMX中的配置步骤:

  1. 启用TIM2定时器,选择内部时钟源
  2. 配置通道1为输入捕获模式
  3. 设置预分频器(PSC)为71,ARR为65535(72MHz主频下得到1MHz计数频率,1us分辨率)
  4. 开启TIM2全局中断和捕获中断
  5. 配置PA1为GPIO输出模式
  6. 启用USART1用于调试输出

关键点在于定时器配置。我选择TIM2是因为它是最基础的通用定时器,所有STM32型号都有。输入捕获模式可以精确测量Echo高电平的持续时间,1us的分辨率对于超声波测距完全够用。

3. HAL库输入捕获实现

HAL库的输入捕获流程比标准库更抽象,但用熟练后反而更简单。主要逻辑都在回调函数中处理:

// 定义测量结构体 typedef struct { uint16_t start_val; uint16_t end_val; float distance; uint8_t capture_flag; } SR04_TypeDef; SR04_TypeDef hcsr04; // 输入捕获回调函数 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM2) { if(hcsr04.capture_flag == 0) { // 捕获上升沿 hcsr04.start_val = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); hcsr04.capture_flag = 1; } else { // 捕获下降沿 hcsr04.end_val = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); hcsr04.capture_flag = 0; // 计算距离 uint16_t pulse_width = (hcsr04.end_val > hcsr04.start_val) ? (hcsr04.end_val - hcsr04.start_val) : (65535 - hcsr04.start_val + hcsr04.end_val); hcsr04.distance = pulse_width * 0.0343 / 2; // 单位cm } } }

这个实现有几个关键点:

  1. 使用结构体保存测量状态,避免全局变量混乱
  2. 在上升沿捕获时立即切换为下降沿捕获,确保能测量完整脉冲宽度
  3. 处理定时器计数器溢出的情况(end_val < start_val时)
  4. 计算距离时使用0.0343cm/us的声速(25℃标准值)

4. 温度补偿算法实现

标准声速是25℃下的343m/s,但实际环境中温度变化很大。温度每升高1℃,声速增加约0.6m/s。我在项目中增加了DS18B20温度传感器,接线如下:

  • VCC → 3.3V
  • DQ → PB0(需接4.7K上拉电阻)
  • GND → GND

温度补偿代码:

float Get_Speed_By_Temp(float temp) { return 331.5 + 0.6 * temp; // 声速与温度关系公式 } void Update_Distance_With_Temp(float temp) { float speed = Get_Speed_By_Temp(temp); uint16_t pulse_width = (hcsr04.end_val > hcsr04.start_val) ? (hcsr04.end_val - hcsr04.start_val) : (65535 - hcsr04.start_val + hcsr04.end_val); hcsr04.distance = pulse_width * (speed / 10000) / 2; // 转换为cm单位 }

实测发现,在冬季(约5℃)和夏季(约35℃)时,补偿前后的测距误差可以从±3cm降低到±1cm以内。对于需要精确测距的场景(如自动泊车),这个改进非常关键。

5. 完整工作流程与优化技巧

主程序的工作流程如下:

int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM2_Init(); MX_USART1_UART_Init(); // 初始化HC-SR04 HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); while (1) { // 触发测距 HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET); delay_us(20); HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET); // 读取温度并更新距离 float temp = DS18B20_GetTemp(); Update_Distance_With_Temp(temp); // 串口输出 printf("距离: %.1fcm 温度: %.1f℃\r\n", hcsr04.distance, temp); HAL_Delay(100); // 两次测量间隔至少60ms } }

几个优化点值得注意:

  1. 触发脉冲严格控制在20us,既满足模块要求又不会过长
  2. 测量间隔大于60ms,避免上次测量的回波干扰
  3. 使用printf重定向输出调试信息,方便观察数据
  4. 加入超时判断,防止因物体超出量程导致程序卡死

6. 常见问题与解决方法

在实际调试中遇到过几个典型问题:

问题1:测量值跳动大解决方法:

  • 在软件中加入滑动平均滤波(如取最近5次测量的平均值)
  • 确保电源稳定,我在VCC脚加了100uF电容后明显改善
  • 检查物体表面是否平整,粗糙表面会导致回波散射

问题2:短距离测量不准原因:HC-SR04有2cm左右的盲区 解决方法:

  • 程序中对小于3cm的结果直接过滤
  • 改用盲区更小的US-015模块(约0.5cm)

问题3:高温环境下异常原因:温度超过DS18B20量程(-55~125℃) 解决方法:

  • 加入温度范围检查,超限时使用默认声速
  • 改用防水型的DS18B20探头

7. 进阶应用示例

基于这个基础框架,可以扩展很多实用功能。比如我在智能小车上实现的自动避障:

void Auto_Avoidance(void) { Get_Distance(); // 获取前方距离 if(hcsr04.distance < 20.0) { // 20cm内障碍物 Stop_Car(); HAL_Delay(500); Turn_Right(90); // 右转90度 Get_Distance(); // 再次测距 if(hcsr04.distance < 30.0) { // 右侧也有障碍 Turn_Left(180); // 掉头 } } else { Move_Forward(); // 安全距离,继续前进 } }

这个简单的逻辑配合超声波模块,就能实现基本的避障功能。如果需要更复杂的应用,可以结合多路超声波模块实现环境建模。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/21 5:18:06

AI魔法修图师体验:一句话让照片中的人变老变年轻

AI魔法修图师体验&#xff1a;一句话让照片中的人变老变年轻 你有没有试过盯着一张旧照片想&#xff1a;“要是能看到爷爷年轻时的样子该多好&#xff1f;”或者对着自拍嘀咕&#xff1a;“这张脸要是再成熟五岁&#xff0c;会不会更显稳重&#xff1f;”——过去这只能靠想象…

作者头像 李华
网站建设 2026/5/15 5:42:08

智能客服文本意图识别系统的性能优化实战:从算法选型到工程落地

痛点分析&#xff1a;智能客服场景下的三大瓶颈 在日均千万级对话量的智能客服平台中&#xff0c;文本意图识别模块的延迟与准确率直接决定用户体验。过去半年&#xff0c;我们通过对线上日志的采样分析&#xff0c;发现以下典型痛点&#xff1a; 长尾意图覆盖不足 头部20%的意…

作者头像 李华
网站建设 2026/5/23 9:51:49

Qwen2.5-Coder-1.5B镜像免配置:内置CUDA 12.1+cuDNN 8.9,开箱即跑

Qwen2.5-Coder-1.5B镜像免配置&#xff1a;内置CUDA 12.1cuDNN 8.9&#xff0c;开箱即跑 你是不是也经历过这样的时刻&#xff1a;想试试最新的代码大模型&#xff0c;结果光是装驱动、配环境、编译依赖就耗掉一整个下午&#xff1f;显卡明明在那儿&#xff0c;却卡在torch no…

作者头像 李华
网站建设 2026/5/30 0:39:13

Kook Zimage真实幻想Turbo入门指南:Z-Image-Turbo架构优势解析

Kook Zimage真实幻想Turbo入门指南&#xff1a;Z-Image-Turbo架构优势解析 1. 为什么幻想风格创作需要“真实感”&#xff1f; 你有没有试过输入“精灵少女站在月光森林里”&#xff0c;结果生成的图要么像AI涂鸦&#xff0c;要么人物僵硬、光影假得一眼看穿&#xff1f;幻想…

作者头像 李华
网站建设 2026/5/29 13:44:32

YOLO X Layout部署教程:低配服务器(4GB RAM)运行YOLOX Tiny实测

YOLO X Layout部署教程&#xff1a;低配服务器&#xff08;4GB RAM&#xff09;运行YOLOX Tiny实测 1. 这个工具到底能帮你做什么&#xff1f; 你有没有遇到过这样的情况&#xff1a;手头有一堆扫描版PDF或手机拍的文档照片&#xff0c;想把里面的内容结构化提取出来——比如…

作者头像 李华
网站建设 2026/5/5 21:45:38

医疗文本分类新选择:Qwen3-0.6B实战落地

医疗文本分类新选择&#xff1a;Qwen3-0.6B实战落地 1. 为什么医疗文本分类需要新思路&#xff1f; 在医院信息科、医学AI初创公司和药企研发部门&#xff0c;我常听到类似的问题&#xff1a;“我们每天处理上千条检验报告、出院小结和随访记录&#xff0c;但用传统BERT微调做…

作者头像 李华