文章目录
-
- 一、前言
-
- [1.1 技术背景](#1.1 技术背景)
- [1.2 本文目标](#1.2 本文目标)
- [1.3 技术栈](#1.3 技术栈)
- 二、环境准备
-
- [2.1 硬件连接](#2.1 硬件连接)
- [2.2 STM32CubeMX配置](#2.2 STM32CubeMX配置)
-
- [2.2.1 GPIO配置](#2.2.1 GPIO配置)
- [2.2.2 定时器配置](#2.2.2 定时器配置)
- [2.2.3 I2C配置](#2.2.3 I2C配置)
- 三、核心实现
-
- [3.1 项目文件结构](#3.1 项目文件结构)
- [3.2 HC-SR04驱动实现](#3.2 HC-SR04驱动实现)
- [3.3 倒车雷达系统实现](#3.3 倒车雷达系统实现)
- [3.4 蜂鸣器控制](#3.4 蜂鸣器控制)
- [3.5 主程序实现](#3.5 主程序实现)
- 四、系统流程
-
- [4.1 测距流程图](#4.1 测距流程图)
- 五、测试验证
-
- [5.1 单传感器测试](#5.1 单传感器测试)
- [5.2 多传感器测试](#5.2 多传感器测试)
- [5.3 报警功能测试](#5.3 报警功能测试)
- 六、故障排查
-
- [6.1 测距不准确](#6.1 测距不准确)
- [6.2 捕获失败](#6.2 捕获失败)
- [6.3 多传感器干扰](#6.3 多传感器干扰)
- 七、总结
-
- [7.1 核心知识点](#7.1 核心知识点)
- [7.2 扩展方向](#7.2 扩展方向)
- [7.3 学习资源](#7.3 学习资源)
一、前言
1.1 技术背景
超声波测距技术广泛应用于倒车雷达、机器人避障、液位检测等场景。HC-SR04是一款经济实用的超声波测距模块,测量范围2cm-400cm,精度可达3mm,通过简单的触发和回响信号即可完成测距。
超声波测距原理:
- 发送40kHz超声波脉冲
- 超声波遇到障碍物反射回来
- 接收回响信号
- 根据时间差计算距离:距离 = (声速 × 时间) / 2
本文将实现一个完整的倒车雷达系统,包括多传感器测距、蜂鸣器报警、OLED显示、LED指示等功能。
1.2 本文目标
通过本文,你将学习到:
- HC-SR04超声波模块的工作原理
- STM32定时器捕获功能的使用
- 多传感器轮询测距策略
- 分级报警逻辑设计
- 系统集成与优化
完成本文学习后,你将能够构建一个实用的倒车雷达系统,可直接应用于智能小车、机器人等项目。
1.3 技术栈
硬件平台:
- 主控:STM32F103C8T6(Blue Pill)
- 传感器:HC-SR04超声波模块 × 4(前后左右)
- 显示:0.96寸OLED(I2C)
- 报警:蜂鸣器、LED × 4
- 调试:ST-Link V2
软件环境:
- IDE:STM32CubeIDE 1.13.0+
- 固件库:STM32CubeF1 HAL库
- 算法:中值滤波、卡尔曼滤波(可选)
二、环境准备
2.1 硬件连接
HC-SR04与STM32连接(以前方传感器为例):
| HC-SR04引脚 | STM32引脚 | 说明 |
|---|---|---|
| VCC | 5V | 供电 |
| GND | GND | 地 |
| Trig | PA0 | 触发信号(输出) |
| Echo | PA1 (TIM2_CH2) | 回响信号(输入捕获) |
多传感器连接:
| 位置 | Trig引脚 | Echo引脚 |
|---|---|---|
| 前方 | PA0 | PA1 (TIM2_CH2) |
| 后方 | PA2 | PA3 (TIM2_CH4) |
| 左侧 | PB0 | PB1 (TIM3_CH4) |
| 右侧 | PB6 | PB7 (TIM4_CH2) |
蜂鸣器与LED:
- 蜂鸣器 → PB8(PWM输出)
- LED1(前) → PC13
- LED2(后) → PC14
- LED3(左) → PC15
- LED4(右) → PB9
2.2 STM32CubeMX配置
2.2.1 GPIO配置
Trig引脚(输出):
- PA0, PA2, PB0, PB6:GPIO_Output
Echo引脚(输入捕获):
- PA1, PA3, PB1, PB7:配置为对应定时器通道
2.2.2 定时器配置
TIM2(前后传感器):
- Clock Source:Internal Clock
- Prescaler:71(1MHz计数频率)
- Counter Period:65535
- Channel2(PA1):Input Capture direct mode
- Channel4(PA3):Input Capture direct mode
TIM3(左侧传感器):
- 配置同TIM2
- Channel4(PB1):Input Capture direct mode
TIM4(右侧传感器):
- 配置同TIM2
- Channel2(PB7):Input Capture direct mode
TIM1(蜂鸣器PWM):
- Prescaler:71
- Counter Period:999(1kHz PWM)
- Channel1:PWM Generation CH1
2.2.3 I2C配置
I2C1(OLED):
- Speed Mode:Fast Mode(400kHz)
三、核心实现
3.1 项目文件结构
UltrasonicRadar/
├── Core/
│ ├── Inc/
│ │ ├── main.h
│ │ ├── hcsr04.h
│ │ ├── radar.h
│ │ ├── oled.h
│ │ └── buzzer.h
│ └── Src/
│ ├── main.c
│ ├── hcsr04.c
│ ├── radar.c
│ ├── oled.c
│ └── buzzer.c
3.2 HC-SR04驱动实现
📄 创建文件:
Core/Inc/hcsr04.h
c
/**
* @file hcsr04.h
* @brief HC-SR04超声波测距模块驱动头文件
*
* 功能:
* - 触发测距
* - 捕获回响信号
* - 计算距离
* - 数据滤波
*/
#ifndef __HCSR04_H
#define __HCSR04_H
#include "main.h"
#include <stdint.h>
#include <stdbool.h>
/* ===================== 配置参数 ===================== */
#define HCSR04_TIMEOUT 30000 // 超时时间(us),对应最大距离约5m
#define SOUND_SPEED 340.0f // 声速(m/s),20℃时
#define HCSR04_MAX_DISTANCE 400 // 最大测量距离(cm)
#define HCSR04_MIN_DISTANCE 2 // 最小测量距离(cm)
/* ===================== 传感器位置枚举 ===================== */
typedef enum {
SENSOR_FRONT = 0, // 前方
SENSOR_REAR, // 后方
SENSOR_LEFT, // 左侧
SENSOR_RIGHT, // 右侧
SENSOR_COUNT // 传感器总数
} HCSR04_Position_t;
/* ===================== 数据结构 ===================== */
/**
* @brief 传感器配置结构
*/
typedef struct {
GPIO_TypeDef *trig_port; // Trig引脚端口
uint16_t trig_pin; // Trig引脚号
TIM_HandleTypeDef *htim; // 定时器句柄
uint32_t channel; // 定时器通道
} HCSR04_Config_t;
/**
* @brief 测距数据结构
*/
typedef struct {
uint16_t distance_cm; // 距离(cm)
uint32_t capture_time; // 捕获时间(us)
bool valid; // 数据有效标志
uint32_t timestamp; // 时间戳
} HCSR04_Data_t;
/* ===================== 函数声明 ===================== */
/**
* @brief 初始化HC-SR04
*/
void HCSR04_Init(void);
/**
* @brief 触发测距
* @param position 传感器位置
*/
void HCSR04_Trigger(HCSR04_Position_t position);
/**
* @brief 读取距离
* @param position 传感器位置
* @retval uint16_t 距离(cm),0表示无效
*/
uint16_t HCSR04_ReadDistance(HCSR04_Position_t position);
/**
* @brief 获取测距数据
* @param position 传感器位置
* @param data 输出数据结构
* @retval bool 成功返回true
*/
bool HCSR04_GetData(HCSR04_Position_t position, HCSR04_Data_t *data);
/**
* @brief 输入捕获回调(在定时器中断中调用)
* @param htim 定时器句柄
*/
void HCSR04_CaptureCallback(TIM_HandleTypeDef *htim);
#endif /* __HCSR04_H */
📄 创建文件:
Core/Src/hcsr04.c
c
/**
* @file hcsr04.c
* @brief HC-SR04超声波测距模块驱动实现
*/
#include "hcsr04.h"
#include "tim.h"
#include <stdio.h>
/* ===================== 私有变量 ===================== */
// 传感器配置表
static const HCSR04_Config_t sensor_config[SENSOR_COUNT] = {
// 前方传感器
{GPIOA, GPIO_PIN_0, &htim2, TIM_CHANNEL_2},
// 后方传感器
{GPIOA, GPIO_PIN_2, &htim2, TIM_CHANNEL_4},
// 左侧传感器
{GPIOB, GPIO_PIN_0, &htim3, TIM_CHANNEL_4},
// 右侧传感器
{GPIOB, GPIO_PIN_6, &htim4, TIM_CHANNEL_2}
};
// 测距数据
static HCSR04_Data_t sensor_data[SENSOR_COUNT];
// 捕获状态
static volatile bool capture_started[SENSOR_COUNT] = {false};
static volatile uint32_t capture_value1[SENSOR_COUNT] = {0};
static volatile uint32_t capture_value2[SENSOR_COUNT] = {0};
/* ===================== 私有函数 ===================== */
/**
* @brief 根据定时器和通道获取传感器索引
*/
static int8_t GetSensorIndex(TIM_HandleTypeDef *htim, uint32_t channel)
{
for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
if (sensor_config[i].htim == htim && sensor_config[i].channel == channel) {
return i;
}
}
return -1;
}
/**
* @brief 中值滤波(3个样本)
*/
static uint16_t MedianFilter(uint16_t *samples, uint8_t count)
{
// 简单冒泡排序
for (uint8_t i = 0; i < count - 1; i++) {
for (uint8_t j = 0; j < count - i - 1; j++) {
if (samples[j] > samples[j + 1]) {
uint16_t temp = samples[j];
samples[j] = samples[j + 1];
samples[j + 1] = temp;
}
}
}
return samples[count / 2]; // 返回中值
}
/* ===================== 公有函数实现 ===================== */
/**
* @brief 初始化HC-SR04
*/
void HCSR04_Init(void)
{
printf("[HCSR04] 初始化中...\r\n");
// 初始化数据结构
for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
sensor_data[i].distance_cm = 0;
sensor_data[i].capture_time = 0;
sensor_data[i].valid = false;
sensor_data[i].timestamp = 0;
capture_started[i] = false;
capture_value1[i] = 0;
capture_value2[i] = 0;
}
// 启动输入捕获
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_4);
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_4);
HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_2);
printf("[HCSR04] 初始化完成\r\n");
}
/**
* @brief 触发测距
*/
void HCSR04_Trigger(HCSR04_Position_t position)
{
if (position >= SENSOR_COUNT) {
return;
}
const HCSR04_Config_t *config = &sensor_config[position];
// 重置捕获状态
capture_started[position] = false;
capture_value1[position] = 0;
capture_value2[position] = 0;
// 发送10us高电平触发信号
HAL_GPIO_WritePin(config->trig_port, config->trig_pin, GPIO_PIN_SET);
HAL_Delay_us(10); // 需要实现微秒延时
HAL_GPIO_WritePin(config->trig_port, config->trig_pin, GPIO_PIN_RESET);
}
/**
* @brief 读取距离
*/
uint16_t HCSR04_ReadDistance(HCSR04_Position_t position)
{
if (position >= SENSOR_COUNT) {
return 0;
}
// 触发测距
HCSR04_Trigger(position);
// 等待捕获完成(最多等待50ms)
uint32_t start_time = HAL_GetTick();
while (!sensor_data[position].valid && (HAL_GetTick() - start_time) < 50) {
HAL_Delay(1);
}
if (sensor_data[position].valid) {
return sensor_data[position].distance_cm;
}
return 0; // 超时或无效
}
/**
* @brief 获取测距数据
*/
bool HCSR04_GetData(HCSR04_Position_t position, HCSR04_Data_t *data)
{
if (position >= SENSOR_COUNT || data == NULL) {
return false;
}
*data = sensor_data[position];
return data->valid;
}
/**
* @brief 输入捕获回调
*
* 工作流程:
* 1. 第一次捕获:上升沿,记录起始时间
* 2. 第二次捕获:下降沿,记录结束时间
* 3. 计算时间差,转换为距离
*/
void HCSR04_CaptureCallback(TIM_HandleTypeDef *htim)
{
// 判断是哪个通道触发
uint32_t channel = 0;
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) {
channel = TIM_CHANNEL_2;
} else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4) {
channel = TIM_CHANNEL_4;
} else {
return;
}
// 获取传感器索引
int8_t index = GetSensorIndex(htim, channel);
if (index < 0) {
return;
}
if (!capture_started[index]) {
// 第一次捕获:上升沿
capture_value1[index] = HAL_TIM_ReadCapturedValue(htim, channel);
capture_started[index] = true;
// 切换为下降沿捕获
__HAL_TIM_SET_CAPTUREPOLARITY(htim, channel, TIM_INPUTCHANNELPOLARITY_FALLING);
} else {
// 第二次捕获:下降沿
capture_value2[index] = HAL_TIM_ReadCapturedValue(htim, channel);
capture_started[index] = false;
// 计算时间差(us)
uint32_t time_diff;
if (capture_value2[index] > capture_value1[index]) {
time_diff = capture_value2[index] - capture_value1[index];
} else {
// 定时器溢出
time_diff = (0xFFFF - capture_value1[index]) + capture_value2[index];
}
// 计算距离(cm)
// 距离 = (声速 * 时间) / 2
// 声速 = 340 m/s = 0.034 cm/us
float distance = (time_diff * 0.034f) / 2.0f;
// 数据有效性检查
if (distance >= HCSR04_MIN_DISTANCE && distance <= HCSR04_MAX_DISTANCE) {
sensor_data[index].distance_cm = (uint16_t)distance;
sensor_data[index].capture_time = time_diff;
sensor_data[index].valid = true;
sensor_data[index].timestamp = HAL_GetTick();
} else {
sensor_data[index].valid = false;
}
// 切换回上升沿捕获
__HAL_TIM_SET_CAPTUREPOLARITY(htim, channel, TIM_INPUTCHANNELPOLARITY_RISING);
}
}
/**
* @brief 微秒延时(需要在main.c中实现)
*/
__weak void HAL_Delay_us(uint32_t us)
{
uint32_t start = DWT->CYCCNT;
uint32_t cycles = us * (SystemCoreClock / 1000000);
while ((DWT->CYCCNT - start) < cycles);
}
3.3 倒车雷达系统实现
📄 创建文件:
Core/Inc/radar.h
c
/**
* @file radar.h
* @brief 倒车雷达系统头文件
*
* 功能:
* - 多传感器轮询测距
* - 分级报警逻辑
* - 障碍物检测
*/
#ifndef __RADAR_H
#define __RADAR_H
#include "hcsr04.h"
/* ===================== 报警等级 ===================== */
typedef enum {
ALARM_NONE = 0, // 无报警(>100cm)
ALARM_LOW, // 低级报警(50-100cm)
ALARM_MEDIUM, // 中级报警(20-50cm)
ALARM_HIGH // 高级报警(<20cm)
} Alarm_Level_t;
/* ===================== 雷达数据结构 ===================== */
typedef struct {
uint16_t distance[SENSOR_COUNT]; // 各方向距离
Alarm_Level_t alarm[SENSOR_COUNT]; // 各方向报警等级
Alarm_Level_t max_alarm; // 最高报警等级
uint32_t timestamp;
} Radar_Data_t;
/* ===================== 函数声明 ===================== */
/**
* @brief 初始化雷达系统
*/
void Radar_Init(void);
/**
* @brief 更新雷达数据
*/
void Radar_Update(void);
/**
* @brief 获取雷达数据
* @param data 输出数据结构
*/
void Radar_GetData(Radar_Data_t *data);
/**
* @brief 获取报警等级
* @param distance 距离(cm)
* @retval Alarm_Level_t
*/
Alarm_Level_t Radar_GetAlarmLevel(uint16_t distance);
#endif /* __RADAR_H */
📄 创建文件:
Core/Src/radar.c
c
/**
* @file radar.c
* @brief 倒车雷达系统实现
*/
#include "radar.h"
#include "buzzer.h"
#include <stdio.h>
/* ===================== 私有变量 ===================== */
static Radar_Data_t radar_data;
/* ===================== 公有函数实现 ===================== */
/**
* @brief 初始化雷达系统
*/
void Radar_Init(void)
{
printf("[Radar] 初始化雷达系统\r\n");
HCSR04_Init();
Buzzer_Init();
for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
radar_data.distance[i] = 0;
radar_data.alarm[i] = ALARM_NONE;
}
radar_data.max_alarm = ALARM_NONE;
radar_data.timestamp = 0;
}
/**
* @brief 更新雷达数据
*/
void Radar_Update(void)
{
// 轮询读取各传感器
for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
uint16_t distance = HCSR04_ReadDistance(i);
if (distance > 0) {
radar_data.distance[i] = distance;
radar_data.alarm[i] = Radar_GetAlarmLevel(distance);
} else {
radar_data.distance[i] = 0;
radar_data.alarm[i] = ALARM_NONE;
}
HAL_Delay(20); // 传感器间隔20ms,避免干扰
}
// 确定最高报警等级
radar_data.max_alarm = ALARM_NONE;
for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
if (radar_data.alarm[i] > radar_data.max_alarm) {
radar_data.max_alarm = radar_data.alarm[i];
}
}
radar_data.timestamp = HAL_GetTick();
// 控制蜂鸣器
Buzzer_SetAlarm(radar_data.max_alarm);
// 打印数据
printf("[Radar] 前:%3dcm 后:%3dcm 左:%3dcm 右:%3dcm | 报警:%d\r\n",
radar_data.distance[SENSOR_FRONT],
radar_data.distance[SENSOR_REAR],
radar_data.distance[SENSOR_LEFT],
radar_data.distance[SENSOR_RIGHT],
radar_data.max_alarm);
}
/**
* @brief 获取雷达数据
*/
void Radar_GetData(Radar_Data_t *data)
{
if (data != NULL) {
*data = radar_data;
}
}
/**
* @brief 获取报警等级
*/
Alarm_Level_t Radar_GetAlarmLevel(uint16_t distance)
{
if (distance == 0 || distance > 100) {
return ALARM_NONE;
} else if (distance > 50) {
return ALARM_LOW;
} else if (distance > 20) {
return ALARM_MEDIUM;
} else {
return ALARM_HIGH;
}
}
3.4 蜂鸣器控制
📄 创建文件:
Core/Inc/buzzer.h
c
/**
* @file buzzer.h
* @brief 蜂鸣器控制头文件
*/
#ifndef __BUZZER_H
#define __BUZZER_H
#include "main.h"
#include "radar.h"
/**
* @brief 初始化蜂鸣器
*/
void Buzzer_Init(void);
/**
* @brief 设置报警
* @param level 报警等级
*/
void Buzzer_SetAlarm(Alarm_Level_t level);
/**
* @brief 蜂鸣器鸣叫
* @param duration_ms 持续时间(ms)
*/
void Buzzer_Beep(uint16_t duration_ms);
#endif /* __BUZZER_H */
📄 创建文件:
Core/Src/buzzer.c
c
/**
* @file buzzer.c
* @brief 蜂鸣器控制实现
*/
#include "buzzer.h"
#include "tim.h"
/* ===================== 私有变量 ===================== */
static uint32_t last_beep_time = 0;
/**
* @brief 初始化蜂鸣器
*/
void Buzzer_Init(void)
{
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 0); // 初始关闭
}
/**
* @brief 设置报警
*/
void Buzzer_SetAlarm(Alarm_Level_t level)
{
uint32_t current_time = HAL_GetTick();
uint16_t interval = 0;
switch (level) {
case ALARM_NONE:
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 0); // 关闭
break;
case ALARM_LOW:
interval = 1000; // 1秒间隔
break;
case ALARM_MEDIUM:
interval = 500; // 0.5秒间隔
break;
case ALARM_HIGH:
interval = 200; // 0.2秒间隔
break;
}
if (level != ALARM_NONE && (current_time - last_beep_time) >= interval) {
Buzzer_Beep(100);
last_beep_time = current_time;
}
}
/**
* @brief 蜂鸣器鸣叫
*/
void Buzzer_Beep(uint16_t duration_ms)
{
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 500); // 50%占空比
HAL_Delay(duration_ms);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 0);
}
3.5 主程序实现
📝 修改文件:
Core/Src/main.c
c
/**
* @brief 主函数
*/
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM1_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_TIM4_Init();
MX_I2C1_Init();
MX_USART1_UART_Init();
// 使能DWT用于微秒延时
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
printf("\r\n========================================\r\n");
printf(" 倒车雷达系统\r\n");
printf("========================================\r\n");
// 初始化雷达系统
Radar_Init();
// 初始化OLED
OLED_Init();
OLED_Clear();
OLED_ShowString(0, 0, "Parking Radar");
OLED_Refresh();
HAL_Delay(2000);
Radar_Data_t radar_data;
while (1)
{
// 更新雷达数据
Radar_Update();
// 获取数据
Radar_GetData(&radar_data);
// OLED显示
OLED_Clear();
// 显示各方向距离
OLED_ShowString(0, 0, "F:");
OLED_ShowNum(16, 0, radar_data.distance[SENSOR_FRONT], 3);
OLED_ShowString(40, 0, "cm");
OLED_ShowString(0, 2, "R:");
OLED_ShowNum(16, 2, radar_data.distance[SENSOR_REAR], 3);
OLED_ShowString(40, 2, "cm");
OLED_ShowString(0, 4, "L:");
OLED_ShowNum(16, 4, radar_data.distance[SENSOR_LEFT], 3);
OLED_ShowString(40, 4, "cm");
OLED_ShowString(0, 6, "R:");
OLED_ShowNum(16, 6, radar_data.distance[SENSOR_RIGHT], 3);
OLED_ShowString(40, 6, "cm");
// 显示报警状态
const char *alarm_str[] = {"SAFE", "WARN", "ALERT", "DANGER"};
OLED_ShowString(64, 3, alarm_str[radar_data.max_alarm]);
OLED_Refresh();
// 控制LED指示
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13,
radar_data.alarm[SENSOR_FRONT] >= ALARM_MEDIUM ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14,
radar_data.alarm[SENSOR_REAR] >= ALARM_MEDIUM ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_15,
radar_data.alarm[SENSOR_LEFT] >= ALARM_MEDIUM ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9,
radar_data.alarm[SENSOR_RIGHT] >= ALARM_MEDIUM ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_Delay(100);
}
}
/**
* @brief 定时器输入捕获回调
*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
HCSR04_CaptureCallback(htim);
}
四、系统流程
4.1 测距流程图
是
否
开始
Trig引脚输出10us高电平
HC-SR04发送8个40kHz脉冲
Echo引脚输出高电平
定时器捕获上升沿
记录起始时间T1
超声波遇障碍物反射
Echo引脚变为低电平
定时器捕获下降沿
记录结束时间T2
计算时间差: ΔT = T2 - T1
计算距离: D = ΔT × 0.034 / 2
距离有效?
保存距离数据
标记无效
结束
五、测试验证
5.1 单传感器测试
- 在传感器前放置障碍物
- 观察串口输出距离值
- 用尺子测量实际距离对比
5.2 多传感器测试
- 在四个方向分别放置障碍物
- 验证各传感器独立工作
- 检查是否有相互干扰
5.3 报警功能测试
- 逐渐靠近障碍物
- 验证蜂鸣器报警频率变化
- 验证LED指示灯亮灭
六、故障排查
6.1 测距不准确
原因:
- 声速受温度影响
- 障碍物表面不平整
- 测量角度偏斜
解决:
- 温度补偿:声速 = 331.5 + 0.6 × 温度(℃)
- 多次测量取平均值
- 调整传感器安装角度
6.2 捕获失败
原因:
- 定时器配置错误
- 中断未启用
- Echo信号被干扰
解决:
- 检查定时器时钟配置
- 确认中断优先级
- 增加硬件滤波电容
6.3 多传感器干扰
原因: 超声波信号相互干扰
解决: 增加传感器轮询间隔(20-50ms)
七、总结
7.1 核心知识点
- HC-SR04工作原理:触发-回响机制
- 定时器输入捕获:测量脉冲宽度
- 多传感器管理:轮询策略
- 分级报警:距离阈值判断
7.2 扩展方向
- 温度补偿:集成温度传感器
- 数据融合:卡尔曼滤波
- 可视化:图形化显示障碍物位置
- 语音提示:集成语音模块
7.3 学习资源
官方文档: