1. 项目概述:超声波测距的工程价值
超声波测距作为非接触式距离检测方案,在工业自动化、智能家居和机器人导航领域具有广泛应用。HC-SR04模块因其5V TTL电平输出、2cm-400cm量程和3mm精度,成为嵌入式开发中的经典选择。本项目基于STM32 HAL库实现完整测距流程,包含CubeMX工程配置、时序控制算法和距离计算优化。
注意:HC-SR04的Trig和Echo信号线需通过电平转换电路与STM32 GPIO连接,直接连接可能损坏IO口
2. 硬件设计与CubeMX配置
2.1 硬件接口定义
HC-SR04模块四线接口中:
- VCC接5V电源(需LDO稳压)
- GND共地
- Trig接PA8(推挽输出)
- Echo接PA9(浮空输入)
实测中发现,Echo信号高电平持续时间与距离成正比,但5V电平需经分压电路处理。推荐使用1kΩ+2kΩ电阻分压,将5V降至3.3V。
2.2 CubeMX关键配置
-
时钟树配置:
- HCLK设为72MHz(影响定时器精度)
- APB1 Timer时钟保持72MHz
-
GPIO设置:
c复制// PA8配置 GPIO_InitStruct.Pin = GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // PA9配置 GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; -
定时器配置:
- TIM2用于捕获Echo高电平时间
- 时钟分频设为71(1MHz计数频率)
- 自动重装载值65535
- 输入捕获通道1上升沿触发
3. 测距算法实现
3.1 时序控制逻辑
完整测距流程包含三个阶段:
-
触发阶段:
c复制HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); delay_us(10); // 实测至少10μs高电平 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); -
回波检测阶段:
c复制// 在输入捕获中断中处理 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { if(icVal == 0) { // 上升沿 icVal = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); } else { // 下降沿 distance = (HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) - icVal) * 0.034 / 2; icVal = 0; __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); } } } -
温度补偿计算:
声速随温度变化,需动态修正:c复制float sound_speed = 331.4 + 0.6 * temperature; // m/s distance = pulse_width * sound_speed / 2e4; // cm
3.2 滤波算法优化
原始数据存在波动,采用移动平均滤波:
c复制#define FILTER_SIZE 5
static float filter_buf[FILTER_SIZE];
float ultrasonic_filter(float new_val) {
static uint8_t index = 0;
filter_buf[index++] = new_val;
if(index >= FILTER_SIZE) index = 0;
float sum = 0;
for(uint8_t i=0; i<FILTER_SIZE; i++) {
sum += filter_buf[i];
}
return sum / FILTER_SIZE;
}
4. 工程调试与问题排查
4.1 典型故障现象
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 持续返回0 | 接线错误 | 检查Trig/Echo是否反接 |
| 数值波动大 | 电源干扰 | 增加10μF去耦电容 |
| 固定值2cm | 触发时间不足 | 确保Trig脉冲≥10μs |
| 超量程返回值 | 物体超出检测范围 | 添加超时判断逻辑 |
4.2 调试技巧
-
逻辑分析仪抓包:
- 同时捕获Trig和Echo信号
- 验证高电平持续时间是否正常
-
串口打印原始数据:
c复制printf("Raw: %lu us -> %.1f cm\r\n", pulse_width, distance); -
环境干扰处理:
- 避免测量柔软表面(吸收超声波)
- 测量角度保持垂直
- 强光环境下增加遮光罩
5. 性能优化方向
5.1 低功耗模式实现
通过中断唤醒降低功耗:
- 配置Trig引脚为EXTI唤醒源
- 每次测量后进入STOP模式
- 定时器中断唤醒MCU
5.2 多传感器协同
使用硬件SPI连接多个HC-SR04:
- 74HC595扩展Trig控制
- CD4051多路复用Echo信号
- 分时测量避免相互干扰
5.3 三维定位应用
部署三个模块实现三角定位:
c复制// 根据三个距离值计算坐标
void trilateration(float d1, float d2, float d3) {
// 已知三个模块的坐标(x1,y1),(x2,y2),(x3,y3)
float A = 2*x2 - 2*x1;
float B = 2*y2 - 2*y1;
float C = d1*d1 - d2*d2 - x1*x1 + x2*x2 - y1*y1 + y2*y2;
float D = 2*x3 - 2*x2;
float E = 2*y3 - 2*y2;
float F = d2*d2 - d3*d3 - x2*x2 + x3*x3 - y2*y2 + y3*y3;
target_x = (C*E - F*B) / (E*A - B*D);
target_y = (C*D - A*F) / (B*D - A*E);
}
6. 工程文件组织建议
推荐采用模块化设计:
code复制├── Drivers
├── Inc
│ ├── ultrasonic.h // 接口定义
│ └── filter.h // 滤波算法
├── Src
│ ├── ultrasonic.c // 核心驱动
│ ├── filter.c
│ └── main.c // 业务逻辑
└── STM32CubeIDE
└── .project // 工程文件
关键头文件定义示例:
c复制// ultrasonic.h
typedef struct {
TIM_HandleTypeDef *htim;
uint32_t channel;
float temperature;
} Ultrasonic_TypeDef;
void Ultrasonic_Init(Ultrasonic_TypeDef *dev);
float Ultrasonic_Measure(Ultrasonic_TypeDef *dev);
在实测中发现,当测量频率超过20Hz时,建议在两次测量间增加50ms间隔以避免声波干扰。对于需要厘米级精度的场景,可改用TOF激光测距模块,但HC-SR04在成本敏感型应用中仍具优势。