SR05超声波测距原理与中断式实现方案

SR05(行业通用型号为HC-SR05,以下统称HC-SR05)是一款低成本、高性价比的超声波测距模块,核心通过超声波的发射、空气传播、障碍物反射与接收,结合声波在空气中的传播速度,计算模块与目标物体的直线距离。其工作逻辑可拆解为“信号触发-声波传播-回波接收-距离计算”四大核心环节,兼具原理简洁性与工程实用性,广泛应用于嵌入式系统测距场景。

SR05模块超声波时序图

一、核心物理基础:超声波特性与声速校准

HC-SR05的测距逻辑依赖超声波的物理特性,其中声速的稳定性直接决定测量精度,需重点关注环境因素对声速的影响:

1. 超声波定义与关键特性

超声波是频率高于20kHz的机械纵波(人耳听觉上限约20kHz),具备两大核心特性:

  • 定向传播性:40kHz(HC-SR05工作频率)超声波的波束角较小(约15°-30°),能量集中,适合短距离定向测距;
  • 强反射性:遇到密度差异较大的介质界面(如空气-金属、空气-液体)时,会发生明显反射,形成可被检测的“回波”,这是测距的核心前提。

2. 声速的计算与环境校准

超声波在空气中的传播速度并非恒定值,受温度、湿度、气压影响(其中温度影响最显著),需根据实际环境校准:

  • 标准声速:在标准大气压(101.325kPa)、干燥空气、25℃ 条件下,声速约为 346m/s(常见简化值340m/s适用于精度要求较低的场景);
  • 温度校准公式:精确计算时,声速 ( v )(单位:m/s)与环境温度 ( t )(单位:℃,指空气温度,非模块表面温度)的关系为:
    v=331.4+0.607×t v = 331.4 + 0.607 \times t v=331.4+0.607×t
  • 湿度与气压影响:湿度每增加10%,声速约增加0.1-0.3m/s;气压每变化1kPa,声速约变化0.6m/s,通常在室内环境中可忽略,户外高精度场景需额外校准。

二、HC-SR05模块结构与工作流程

HC-SR05模块由超声波发射器(TXR)、超声波接收器(RXR)、内部控制MCU、电源滤波电路四部分组成(部分简化版省略滤波电路,但核心功能一致),完整工作流程需外部控制器(如单片机)与模块协同完成,共5个步骤:

1. 外部触发:向TRIG引脚输入触发信号

外部控制器需向模块的 TRIG引脚 发送一个 持续时间≥10μs的高电平信号,触发模块进入测距模式:

  • 信号要求:高电平持续时间需严格控制(建议10-20μs),过短(<10μs)会导致模块无法识别触发指令,过长(>50μs)可能引发内部MCU误判;
  • 示例:STM32单片机通过GPIO口输出15μs高电平,可稳定触发HC-SR05。

2. 声波发射:TXR输出40kHz超声波脉冲

模块内部MCU接收到TRIG触发信号后,会驱动发射器(TXR,通常为压电陶瓷换能器)输出 8个连续的40kHz正弦波脉冲

  • 频率选择原因:40kHz是“测距距离”与“抗干扰能力”的平衡点——低于30kHz易受环境噪音(如电机、风扇)干扰,高于50kHz会导致声波衰减过快(传播距离缩短);
  • 脉冲数量:8个脉冲可确保接收器能准确识别“有效信号”,避免单脉冲因环境干扰被误判为噪音。

3. 声波传播与回波接收:RXR捕获反射信号

  • 传播阶段:40kHz超声波以球面波形式在空气中传播,遇到障碍物(如墙面、金属板、液体表面)时,部分能量被反射形成“回波”;
  • 接收阶段:回波传播至模块时,接收器(RXR,与TXR结构相同,功能为“声-电转换”)将机械波信号转换为微弱的电信号,经内部放大电路(通常为运算放大器)放大后,传递给内部MCU。

4. 回波反馈:ECHO引脚输出高电平计时信号

模块内部MCU检测到放大后的回波电信号后,立即控制 ECHO引脚 输出高电平,直至回波信号消失(或内部超时):

  • 高电平持续时间意义:ECHO引脚高电平的 总持续时间 ( t ),等于“超声波从TXR发射到RXR接收”的往返时间(即声波从模块到障碍物再返回模块的总时间);
  • 超时机制:若模块在发射声波后 38ms内未接收到回波(对应最大测距距离约6.5m,远超模块标称的4m上限),ECHO引脚会自动拉低,避免长期占用外部控制器资源。

5. 距离计算:外部控制器计算单程距离

外部控制器通过定时器(或中断)读取ECHO引脚高电平的持续时间 ( t ),结合校准后的声速 ( v ),计算模块与障碍物的 单程距离 ( d )

  • 公式推导:声波往返距离 = 声速 × 往返时间 → 单程距离
    d=v×t2 d = \frac{v \times t}{2} d=2v×t

  • 单位换算示例(以25℃环境、声速346m/s为例):
    若ECHO高电平持续时间
    t=2000μs=2×10−3s t = 2000μs = 2×10^{-3}s t=2000μs=2×103s
    则:

    d=346×2×10−32=0.346 m=34.6 cm d = \frac{346 \times 2×10^{-3}}{2} = 0.346 \, \text{m} = 34.6 \, \text{cm} d=2346×2×103=0.346m=34.6cm

三、HC-SR05关键参数与应用限制

理解参数特性是避免工程误区的核心,HC-SR05的典型参数与限制如下表所示:

参数类别 典型值(工业标称) 详细说明与限制
有效测距范围 2cm ~ 400cm - 近距离(<2cm):回波与发射波叠加,RXR无法区分,导致测量失效;
- 远距离(>400cm):声波能量衰减严重,回波信号低于检测阈值,精度下降至±10%以上。
测量精度 ±3mm(20-100cm) - 精度受温度影响:每偏差1℃,精度误差增加约0.2%;
- 受障碍物表面影响:镜面/光滑表面(如金属板)反射效率高,精度优;多孔/吸声表面(如海绵)反射弱,误差大。
工作电压 5V DC 电压波动需控制在±0.2V内,低于4.8V可能导致发射功率不足(测距距离缩短),高于5.2V可能烧毁内部MCU。
工作电流 15mA(静态)/60mA(发射) 静态电流指模块未触发时的功耗,发射电流指TXR输出脉冲时的峰值电流,需确保外部电源能提供足够的瞬时电流。
测量周期 ≥60ms 两次触发之间需间隔≥60ms,避免前一次测距的回波(延迟回波)干扰后一次测量,导致时间计算错误。
波束角 约15°(半功率角) 仅在波束角范围内的障碍物能反射回波,超出范围的障碍物可能无法检测(如模块正前方1m处有物体,斜前方30°处物体可能被忽略)。

四、中断式测距实现方案(基于STM32)

HC-SR05的测距实现分为“轮询式”与“中断式”,其中中断式可释放CPU资源,适合实时性要求较高的系统(如智能小车避障、工业液位检测)。以下为基于STM32 HAL库的中断式实现方案,包含工作流程、硬件配置、代码实现与注意事项。

1. 实现核心逻辑

中断式实现通过外部中断检测ECHO引脚的上升沿/下降沿,结合定时器记录时间差,无需CPU轮询等待,具体流程:

  1. 外部控制器调用sonar_trigger_measurement()函数,向TRIG引脚输出触发信号;
  2. ECHO引脚检测到上升沿(回波开始),触发外部中断,记录定时器当前值(sonar_start_time),并将中断触发方式切换为“下降沿检测”;
  3. ECHO引脚检测到下降沿(回波结束),再次触发外部中断,记录定时器当前值(sonar_end_time),标记测量完成(sonar_measurement_done = 1);
  4. 外部控制器调用sonar_get_distance_mm()函数,读取时间差并计算距离(单位:mm)。

2. 硬件配置要求

需严格按照以下要求配置STM32硬件引脚与外设:

硬件模块 配置参数
TRIG引脚 - 模式:GPIO推挽输出模式;
- 初始电平:低电平(避免误触发);
- 示例:PA0(需与代码中TRIG_PORT/TRIG_PIN匹配)。
ECHO引脚 - 模式:GPIO浮空输入模式(或上拉输入,避免外部干扰);
- 中断配置:外部中断线(EXTI),初始触发方式为“上升沿触发”;
- 示例:PA15(对应EXTI15中断线,需在CubeMX中配置NVIC优先级)。
定时器(TIM) - 模式:自由运行模式(无自动重装载,ARR设为最大值0xFFFF或0xFFFFFFFF);
- 时钟频率:1MHz(即计数周期1μs,便于时间计算);
- 示例:TIM4(需确保定时器时钟已使能,且无其他中断占用)。
NVIC中断优先级 - ECHO引脚外部中断优先级:高于普通任务,低于系统紧急中断(如硬件错误中断);
- 定时器中断:无需使能(仅用于计数,不触发中断)。

3. 完整代码实现(基于STM32 HAL库)

(1)头文件定义(HR04.h)
#ifndef  __SR04_H
#define  __SR04_H

#include "main.h"
#include "tim.h"
#include "stm32f4xx_hal.h"
#include "math.h"
#include "stdio.h"

#define TRIG_PIN      GPIO_PIN_11
#define TRIG_PORT     GPIOA
#define ECHO_PIN      GPIO_PIN_12
#define ECHO_PORT     GPIOA

void sonar_init(void);
void sonar_trigger_measurement(void);
uint8_t sonar_get_distance_mm(int32_t *distance_mm);

#endif
(2)源文件实现(HR04.c)
#include "SR04.h"

volatile uint32_t sonar_start_time = 0;
volatile uint32_t sonar_end_time = 0;
volatile uint8_t sonar_measurement_done = 0;//	0:未完成 	1:完成
volatile uint8_t sonar_state = 0;  // 0: 空闲, 1: 等待下降沿

void sonar_init(void)
{
    // 确保Echo引脚已在CubeMX中配置为上升沿触发中断
    // 这里假设已在CubeMX中完成ECHO_PIN的EXTI配置
    sonar_measurement_done = 0;
}

/**
 * @brief  触发一次测距
 * @param  无
 * @retval 无
 */
void sonar_trigger_measurement(void)
{
    // 如果正在测量,则退出
    if (sonar_state != 0) {
        return;
    }
    
    // 重置状态
    sonar_measurement_done = 0;
    sonar_state = 1;
    
    // 触发Trig高电平10μs
    HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_SET);
    
    // 精确延时10μs(根据系统时钟调整循环次数)
    for(volatile uint32_t i = 0; i < 1000; i++);

    HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_RESET);
}


/**
 * @brief 获取超声波传感器测量的距离(单位:毫米)
 *
 * 此函数用于从HC-SR04超声波传感器获取测量距离,并将结果以毫米为单位存储到distance_mm指针指向的变量中。
 * 
 * @param[out] distance_mm 指向存储测量距离(单位:毫米)的变量的指针
 * 
 * @retval 0 测量成功,distance_mm中存储有效距离
 * @retval 1 测量未完成,无法获取距离
 * @retval 2 测量结果超出传感器有效范围(20mm - 4000mm)
 *
 * @note 距离计算基于声速340m/s(0.34mm/μs),并考虑定时器溢出的情况。
 */

uint8_t sonar_get_distance_mm(int32_t *distance_mm)
{
    if (!sonar_measurement_done) {
        return 1;  // 测量未完成
    }
    
    uint32_t time;
    // 处理定时器溢出
    if (sonar_end_time < sonar_start_time) {
        time = (0xFFFFFFFF - sonar_start_time) + sonar_end_time + 1;
    } else {
        time = sonar_end_time - sonar_start_time;
    }
    
    // 计算距离(单位:毫米)
    // 声速340m/s = 340mm/ms = 0.34mm/us,除以2是因为声波往返
    *distance_mm = (int32_t)(time * 0.34f / 2.0f);
    
    // 过滤超出传感器范围的值(典型范围20mm - 4000mm)
    if (*distance_mm < 20 || *distance_mm > 4000) {
        *distance_mm = -1; 
        //return 2;  // 超出范围
    }
    return 0;  
}


    
(3)中断实现(main.c)
/*!--------定时器9为1us中断,period拉满-------!*/
 HAL_TIM_Base_Start(&htim9); // 启动定时器9,用于超声波测距计时

while(1){
    if (sonar_measurement_done == 1) {
      if (sonar_get_distance_mm(&distance_mm) == 0) {
          printf("Distance: %ld mm\r\n", distance_mm);
      }
      sonar_measurement_done = 0; // 清零,等待下次测量
    }
  }
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == TIM2) //  1ms中断
  {
    if (timer_count_100ms >= 100) // 100ms
    {
      timer_count_100ms = 0;
      sonar_trigger_measurement(); // 触发超声波测距
    }	
  }

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == ECHO_PIN) {
        if (sonar_state == 1 && HAL_GPIO_ReadPin(ECHO_PORT, ECHO_PIN) == GPIO_PIN_SET) {
            // 上升沿,记录开始时间
            sonar_start_time = __HAL_TIM_GET_COUNTER(&htim9);
            sonar_state = 2;
        } 
        else if (sonar_state == 2 && HAL_GPIO_ReadPin(ECHO_PORT, ECHO_PIN) == GPIO_PIN_RESET) {
            // 下降沿,记录结束时间
            sonar_end_time = __HAL_TIM_GET_COUNTER(&htim9);
            sonar_measurement_done = 1;
            sonar_state = 0;
        }
    }
}

4. 关键技术细节与注意事项

(1)定时器计时精度的保障

定时器的计时精度直接影响距离计算误差,需重点配置以下参数:

  • 时钟频率:建议配置为1MHz(计数周期1μs),此时时间差的最小误差为1μs,对应距离误差约0.17mm(满足HC-SR05的±3mm精度要求);
  • 定时器位数:优先使用32位定时器(如TIM4),其最大计数值为0xFFFFFFFF(约4294秒),可避免短时间内溢出;若使用16位定时器(如TIM2),需在中断中处理溢出计数,否则会导致时间计算错误。
(2)特殊场景的适配

在液位检测、高温环境等特殊场景中,需额外适配:

  • 液位检测:超声波在空气-液体界面的反射率较高,但需注意液面波动(如水流冲击)会导致回波不稳定,建议增加“距离变化率过滤”(如连续两次测量的距离差≤5mm时,判定为稳定值);
  • 高温环境(>60℃):模块内部压电陶瓷换能器的频率特性会随温度变化,需每10℃重新校准声速(通过温度传感器实时采集环境温度,动态更新声速值);

五、总结

HC-SR05模块的核心优势在于低成本、易集成,其测距原理基于“超声波往返时间+声速”的物理关系,工程实现中需重点关注环境声速校准中断与定时器的协同抗干扰优化三大核心点。本文提供的中断式实现方案,通过STM32 HAL库完成了从触发、计时到距离计算的全流程,兼顾了效率与稳定性,可直接移植到智能小车、智能家居、工业检测等场景。

在实际开发中,建议先通过示波器观察TRIG触发信号和ECHO回波信号的波形(确认高电平持续时间、上升沿/下降沿是否正常),再逐步优化软件逻辑,最终实现满足项目精度要求的测距功能。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐