STM32F103C8T6 · HAL库开发 · GPIO+TIM3 精密测距
超声波反射测距原理 · 核心功能解析 · 引脚定义详解
HC-SR04 超声波测距模块利用超声波在空气中传播遇到障碍物反射的物理原理来测量距离。模块内部包含两个压电超声波换能器:一个用于发射超声波信号,另一个用于接收反射回来的回波信号。
① 触发阶段:STM32通过Trig引脚发送一个持续时间不少于10μs的高电平脉冲,触发模块内部电路。
② 发射阶段:模块内部发送8个40kHz的超声波脉冲,同时Echo引脚被拉高。
③ 传播阶段:超声波在空气中以约340m/s的速度向前传播,遇到障碍物后反射回来。
④ 接收阶段:接收换能器检测到回波信号后,Echo引脚被拉低。
⑤ 计算阶段:STM32通过TIM3定时器测量Echo高电平持续时间,结合声速计算距离。
接收到Trig触发信号后,内部发送8个40kHz超声波脉冲,频率稳定、方向性强,有效测距角度约15°。
接收换能器检测反射回来的超声波信号,检测到回波后Echo引脚自动输出高电平脉冲,脉宽对应传播时间。
程序支持温度补偿参数输入,根据环境温度动态修正超声波传播速度,提高不同温度环境下的测量精度。
主循环每500ms执行一次测距,通过TIM3定时器(1MHz分辨率)精确测量Echo脉宽,实时更新OLED显示。
| 引脚号 | 名称 | 类型 | 功能描述 | STM32连接 |
|---|---|---|---|---|
| 1 | VCC | 电源 | +5V供电引脚,为模块提供工作电源 | 5V电源 |
| 2 | Trig | 输出 | 触发控制端,输入≥10μs高电平脉冲触发测距 | STM32 PB0 (推挽输出) |
| 3 | Echo | 输入 | 回响输出端,输出高电平脉冲宽度对应测距时间 | STM32 PB1 (上拉输入) |
| 4 | GND | 电源 | 接地引脚,与STM32共地 | GND |
HC-SR04模块实物外观展示
电路原理图设计与PCB封装展示
Trig (PB0) — 推挽输出,STM32控制触发超声波发射
Echo (PB1) — 上拉输入,STM32读取回波脉冲宽度
OLED SCL (PB15) — OLED时钟线
OLED SDA (PB14) — OLED数据线
STM32 HAL库源码逐模块解析 · 核心算法详解
系统初始化后进入while(1)主循环,每500ms通过HC-SR04获取一次距离数据(传入温度25℃进行补偿),然后在OLED屏幕居中显示测距结果。使用HAL_GetTick()实现非阻塞式定时。
/* 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(); // 更新时间戳 } } }
预分频器(Prescaler) = 71:系统时钟72MHz / (71+1) = 1MHz,即每计数一次1μs
计数周期(Period) = 65535:16位定时器最大值,最大可计时65535μs ≈ 65.5ms
计数模式:向上计数(UP),从0递增到65535后溢出
时钟源:内部时钟(72MHz / 72 = 1MHz)
该配置使定时器以1μs精度计数,用于精确测量Echo引脚高电平持续时间
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); }
Trig → GPIOB Pin 0 (推挽输出)
Echo → GPIOB Pin 1 (上拉输入)
定时器 → TIM3 (htim3)
测距范围 → 2cm ~ 500cm
超时阈值 → 50000计数 (50ms,对应约850cm)
#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 // 超时计数值
该函数是整个测距的核心,步骤如下:
① 根据温度计算超声波速度(温度补偿)
② 发送触发脉冲(Trig高电平1ms)
③ 等待Echo上升沿(带超时保护)
④ 等待Echo下降沿,定时器记录脉宽
⑤ 计算距离 = 声速 × 时间 / 2
⑥ 限制结果在有效范围内
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; }
主程序执行流程 · while(1)主循环结构
超声波发射与回波接收实时模拟 · 距离测量可视化
左侧圆形:超声波发射器(Trig触发后发射波束)
右侧矩形:障碍物(可拖动改变距离)
波纹动画:40kHz超声波传播与反射过程
点击"开始测距"按钮,模拟STM32每500ms执行一次测距的过程。超声波从左侧发射器发出,遇到右侧障碍物后反射回来,系统根据Echo脉冲宽度计算距离并在OLED上实时显示。
距离计算:distance = 0.0346 × echo_cnt / 2 (cm)