HC-SR04 超声波测距传感器

STM32F103C8T6 · HAL库开发 · GPIO+TIM3 精密测距

工作电压
5V DC
测距范围
2~500cm
通信方式
GPIO+TIM
测距角度
15°
工作频率
40kHz
向下滚动浏览 ↓

1传感器原理与功能

超声波反射测距原理 · 核心功能解析 · 引脚定义详解

1.1 工作原理

HC-SR04 超声波测距模块利用超声波在空气中传播遇到障碍物反射的物理原理来测量距离。模块内部包含两个压电超声波换能器:一个用于发射超声波信号,另一个用于接收反射回来的回波信号。

测距过程详解

① 触发阶段:STM32通过Trig引脚发送一个持续时间不少于10μs的高电平脉冲,触发模块内部电路。

② 发射阶段:模块内部发送8个40kHz的超声波脉冲,同时Echo引脚被拉高。

③ 传播阶段:超声波在空气中以约340m/s的速度向前传播,遇到障碍物后反射回来。

④ 接收阶段:接收换能器检测到回波信号后,Echo引脚被拉低。

⑤ 计算阶段:STM32通过TIM3定时器测量Echo高电平持续时间,结合声速计算距离。

声速温度补偿公式(T为环境温度℃)
v = (0.607 × T + 331.4) / 10000  (cm/μs)
距离计算公式(echo_cnt为定时器计数值,单位μs)
distance = v × echo_cnt / 2  (cm)
注:除以2是因为超声波往返传播了2倍距离

1.2 核心功能

📡

超声波发射

接收到Trig触发信号后,内部发送8个40kHz超声波脉冲,频率稳定、方向性强,有效测距角度约15°。

🎯

回波接收

接收换能器检测反射回来的超声波信号,检测到回波后Echo引脚自动输出高电平脉冲,脉宽对应传播时间。

🌡️

温度补偿

程序支持温度补偿参数输入,根据环境温度动态修正超声波传播速度,提高不同温度环境下的测量精度。

⚡

实时测距

主循环每500ms执行一次测距,通过TIM3定时器(1MHz分辨率)精确测量Echo脉宽,实时更新OLED显示。

1.3 引脚定义

引脚号 名称 类型 功能描述 STM32连接
1 VCC 电源 +5V供电引脚,为模块提供工作电源 5V电源
2 Trig 输出 触发控制端,输入≥10μs高电平脉冲触发测距 STM32 PB0 (推挽输出)
3 Echo 输入 回响输出端,输出高电平脉冲宽度对应测距时间 STM32 PB1 (上拉输入)
4 GND 电源 接地引脚,与STM32共地 GND

2模块外观展示

HC-SR04模块实物外观展示

HC-SR04外观1
HC-SR04 模块正面外观
HC-SR04外观2
HC-SR04 模块背面外观

3原理图与PCB封装

电路原理图设计与PCB封装展示

HC-SR04原理图
HC-SR04 PCB封装

引脚对应关系

Trig (PB0) — 推挽输出,STM32控制触发超声波发射

Echo (PB1) — 上拉输入,STM32读取回波脉冲宽度

OLED SCL (PB15) — OLED时钟线

OLED SDA (PB14) — OLED数据线

4程序分析

STM32 HAL库源码逐模块解析 · 核心算法详解

4.1 主程序 (main.c)

主程序逻辑概述

系统初始化后进入while(1)主循环,每500ms通过HC-SR04获取一次距离数据(传入温度25℃进行补偿),然后在OLED屏幕居中显示测距结果。使用HAL_GetTick()实现非阻塞式定时。

Core/Src/main.c — 主程序
/* USER CODE BEGIN PV */
uint32_t Time_Now;          // 系统时间戳记录
uint16_t distance;        // 测距结果(单位:cm)
/* USER CODE END PV */

int main(void)
{
    HAL_Init();                      // 初始化HAL库
    SystemClock_Config();            // 系统时钟配置(72MHz)

    MX_GPIO_Init();                 // GPIO初始化
    MX_TIM3_Init();                 // TIM3定时器初始化
    OLED_Init();                    // OLED显示屏初始化
    HC_SR04_Init();                 // HC-SR04超声波初始化

    while (1)
    {
        if(HAL_GetTick() - Time_Now >= 500)         // 500ms更新一次
        {
            distance = HC_SR04_Get_Distance(25);  // 测距(温度25℃)

            OLED_Clear();                                       // 清屏
            OLED_CenterPrintf(24, "%dcm", distance);     // 居中显示距离
            OLED_Update();                                      // 更新显示

            Time_Now = HAL_GetTick();                           // 更新时间戳
        }
    }
}

4.2 定时器配置 (tim.c)

TIM3 配置参数详解

预分频器(Prescaler) = 71:系统时钟72MHz / (71+1) = 1MHz,即每计数一次1μs

计数周期(Period) = 65535:16位定时器最大值,最大可计时65535μs ≈ 65.5ms

计数模式:向上计数(UP),从0递增到65535后溢出

时钟源:内部时钟(72MHz / 72 = 1MHz)

该配置使定时器以1μs精度计数,用于精确测量Echo引脚高电平持续时间

Core/Src/tim.c — TIM3初始化
TIM_HandleTypeDef htim3;

void MX_TIM3_Init(void)
{
    TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    TIM_MasterConfigTypeDef sMasterConfig = {0};

    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 71;                        // 预分频: 72MHz/(71+1)=1MHz → 1μs/tick
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;           // 向上计数模式
    htim3.Init.Period = 65535;                       // 自动重装载值(16位最大值)
    htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;    // 时钟分频: 不分频
    htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    HAL_TIM_Base_Init(&htim3);

    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; // 内部时钟源
    HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig);
    HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);
}

4.3 HC-SR04 驱动程序 (hc-sr04.c)

引脚宏定义

Trig → GPIOB Pin 0 (推挽输出)

Echo → GPIOB Pin 1 (上拉输入)

定时器 → TIM3 (htim3)

测距范围 → 2cm ~ 500cm

超时阈值 → 50000计数 (50ms,对应约850cm)

HAL/HC-SR04/hc-sr04.h — 宏定义
#define HC_SR04_TIM_HANDLE    htim3                    // 绑定TIM3定时器

// 触发脚(Trig)配置 — 推挽输出
#define HC_SR04_TRIG_PORT     GPIOB
#define HC_SR04_TRIG_PIN      GPIO_PIN_0
#define HC_SR04_TRIG_CLK_EN   __HAL_RCC_GPIOB_CLK_ENABLE()

// 回响脚(Echo)配置 — 上拉输入
#define HC_SR04_ECHO_PORT     GPIOB
#define HC_SR04_ECHO_PIN      GPIO_PIN_1
#define HC_SR04_ECHO_CLK_EN   __HAL_RCC_GPIOB_CLK_ENABLE()

// 辅助宏
#define HC_SR04_SET_TRIG_HIGH()  HAL_GPIO_WritePin(HC_SR04_TRIG_PORT, HC_SR04_TRIG_PIN, GPIO_PIN_SET)
#define HC_SR04_SET_TRIG_LOW()   HAL_GPIO_WritePin(HC_SR04_TRIG_PORT, HC_SR04_TRIG_PIN, GPIO_PIN_RESET)
#define HC_SR04_READ_ECHO()      HAL_GPIO_ReadPin(HC_SR04_ECHO_PORT, HC_SR04_ECHO_PIN)

// 测距参数限制
#define HC_SR04_MAX_DISTANCE     500    // 最大测距值(cm)
#define HC_SR04_MIN_DISTANCE     2      // 最小测距值(cm)
#define HC_SR04_TIMEOUT_CNT      50000  // 超时计数值

核心测距函数 HC_SR04_Get_Distance()

该函数是整个测距的核心,步骤如下:

① 根据温度计算超声波速度(温度补偿)

② 发送触发脉冲(Trig高电平1ms)

③ 等待Echo上升沿(带超时保护)

④ 等待Echo下降沿,定时器记录脉宽

⑤ 计算距离 = 声速 × 时间 / 2

⑥ 限制结果在有效范围内

HAL/HC-SR04/hc-sr04.c — 核心测距函数
uint16_t HC_SR04_Get_Distance(uint16_t temp)
{
    uint16_t echo_cnt = 0;      // 定时器计数值(Echo脉冲宽度)
    uint16_t distance = 0;      // 测距结果(cm)
    float sound_speed = 0.0f; // 超声波传播速度(cm/us)

    // 1. 温度补偿: v = (0.607*T + 331.4) / 10000 (cm/us)
    sound_speed = (0.607f * temp + 331.4f) / 10000.0f;

    // 2. 发送触发脉冲(Trig: 高电平1ms)
    HC_SR04_SET_TRIG_HIGH();
    HAL_Delay(1);
    HC_SR04_SET_TRIG_LOW();

    // 3. 等待Echo上升沿(带超时保护)
    __HAL_TIM_SET_COUNTER(&HC_SR04_TIM_HANDLE, 0);
    while(HC_SR04_READ_ECHO() == GPIO_PIN_RESET)
    {
        if(__HAL_TIM_GET_COUNTER(&HC_SR04_TIM_HANDLE) >= HC_SR04_TIMEOUT_CNT)
            return HC_SR04_MAX_DISTANCE;
    }

    // 4. 等待Echo下降沿,记录高电平持续时间
    __HAL_TIM_SET_COUNTER(&HC_SR04_TIM_HANDLE, 0);
    while(HC_SR04_READ_ECHO() == GPIO_PIN_SET)
    {
        if(__HAL_TIM_GET_COUNTER(&HC_SR04_TIM_HANDLE) >= HC_SR04_TIMEOUT_CNT)
            return HC_SR04_MAX_DISTANCE;
    }

    // 5. 获取定时器计数值
    echo_cnt = __HAL_TIM_GET_COUNTER(&HC_SR04_TIM_HANDLE);

    // 6. 计算距离: 距离 = 速度 × 时间 / 2 (往返)
    distance = (uint16_t)(sound_speed * echo_cnt / 2.0f);

    // 7. 限制测距结果范围
    if(distance > HC_SR04_MAX_DISTANCE) distance = HC_SR04_MAX_DISTANCE;
    else if(distance < HC_SR04_MIN_DISTANCE) distance = HC_SR04_MIN_DISTANCE;

    return distance;
}

4.4 数据计算解析

25℃环境温度下声速计算
v = (0.607 × 25 + 331.4) / 10000 = 0.0346 cm/μs
距离计算示例(echo_cnt = 2000μs)
distance = 0.0346 × 2000 / 2 = 34.6 cm
距离范围Echo脉宽定时器计数值状态说明
2cm(最近)~116μs~116有效最小距离
50cm~2890μs~2890正常测距
200cm~11560μs~11560正常测距
500cm(最远)~28900μs~28900有效最大距离
>500cm / 超时≥50000μs≥50000超时返回500cm

5程序流程图

主程序执行流程 · while(1)主循环结构

开始 HAL_Init() 初始化HAL库 SystemClock_Config() 配置时钟72MHz MX_GPIO_Init / MX_TIM3_Init OLED_Init() / HC_SR04_Init() while(1) 主循环 HAL_GetTick() - Time_Now ≥ 500? 否 是 distance = HC_SR04_Get_Distance(25) OLED_Clear / CenterPrintf / Update Time_Now = HAL_GetTick() 循环回退

6交互式动画演示

超声波发射与回波接收实时模拟 · 距离测量可视化

📡 超声波传感器模拟

组件说明

左侧圆形:超声波发射器(Trig触发后发射波束)

右侧矩形:障碍物(可拖动改变距离)

波纹动画:40kHz超声波传播与反射过程

🖥️ OLED显示与数据仪表

---cm
实时距离
---cm
Echo脉冲宽度
---μs
超声波传播速度 (25℃)
0.0346cm/μs

演示说明

点击"开始测距"按钮,模拟STM32每500ms执行一次测距的过程。超声波从左侧发射器发出,遇到右侧障碍物后反射回来,系统根据Echo脉冲宽度计算距离并在OLED上实时显示。

距离计算:distance = 0.0346 × echo_cnt / 2 (cm)