基于STM32的HC_SR04模块实现超声波测距附源码
2025-08-21 06:45:51作者:咎竹峻Karen
适用场景
基于STM32的HC-SR04超声波测距项目是一个功能强大且实用的嵌入式系统应用,特别适合以下场景:
机器人避障系统:在自主导航机器人中,HC-SR04传感器能够实时检测前方障碍物距离,为路径规划提供关键数据输入。
智能停车辅助:汽车后方探测系统可以利用该方案精确测量车辆与障碍物之间的距离,提供安全预警功能。
工业自动化检测:在生产线上用于检测物体位置、测量料位高度或监控设备间距,实现自动化控制。
智能家居应用:可用于自动门禁系统、智能照明控制(感应人员距离)以及安防监控等领域。
教育实验平台:作为嵌入式系统教学的典型案例,帮助学生理解定时器、中断处理、传感器接口等核心概念。
适配系统与环境配置要求
硬件要求
- 主控芯片:STM32F103C8T6(蓝 pill)、STM32F411RE(Nucleo板)或其他STM32系列微控制器
- 超声波传感器:HC-SR04模块,工作电压5V,测量范围2cm-400cm
- 电平转换:由于HC-SR04输出5V电平而STM32为3.3V,需要电阻分压电路(推荐1kΩ和2kΩ电阻)
- 显示设备:可选SSD1306 OLED显示屏或LCD1602用于实时显示距离数据
- 电源供应:5V稳定电源,建议使用外部电源而非USB供电以确保传感器正常工作
软件环境
- 开发工具:STM32CubeIDE 1.8.0或更高版本
- 固件库:STM32 HAL库
- 编译器:ARM GCC工具链
- 调试工具:ST-Link V2调试器
系统配置
- 时钟频率:72MHz(STM32F103)或80MHz(STM32F411)
- 定时器配置:使用通用定时器(TIM1、TIM2等)的输入捕获模式
- GPIO配置:触发引脚设置为推挽输出,回波引脚设置为浮空输入
资源使用教程
1. 硬件连接
将HC-SR04模块与STM32连接:
- VCC → 5V电源
- GND → 共地
- TRIG → PA9(或其他GPIO输出引脚)
- ECHO → PA8(配置为定时器输入捕获引脚)
2. 软件配置步骤
步骤一:创建STM32CubeMX项目
- 选择目标STM32型号
- 配置系统时钟为72MHz
- 启用使用的定时器(如TIM1)
- 配置定时器为输入捕获模式,预分频器设置为71(1MHz时钟)
- 使能定时器中断和输入捕获中断
步骤二:代码实现
// 定义引脚和变量
#define TRIG_PIN GPIO_PIN_9
#define TRIG_PORT GPIOA
uint32_t IC_Val1 = 0;
uint32_t IC_Val2 = 0;
uint32_t Difference = 0;
uint8_t Is_First_Captured = 0;
float Distance = 0;
// 触发传感器函数
void HCSR04_Trigger(void)
{
HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_SET);
delay_us(10);
HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_RESET);
}
// 输入捕获回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
if (Is_First_Captured == 0)
{
IC_Val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
Is_First_Captured = 1;
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);
}
else
{
IC_Val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
__HAL_TIM_SET_COUNTER(htim, 0);
if (IC_Val2 > IC_Val1)
{
Difference = IC_Val2 - IC_Val1;
}
else
{
Difference = (0xffff - IC_Val1) + IC_Val2;
}
Distance = Difference * 0.034 / 2;
Is_First_Captured = 0;
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
}
}
}
步骤三:主循环处理
int main(void)
{
// 初始化代码
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM1_Init();
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1);
while (1)
{
HCSR04_Trigger();
HAL_Delay(100); // 每100ms测量一次
// 显示或处理距离数据
printf("Distance: %.2f cm\r\n", Distance);
}
}
3. 数据处理优化
为了提高测量精度,可以添加滤波算法:
#define FILTER_SIZE 5
float distance_buffer[FILTER_SIZE];
uint8_t buffer_index = 0;
float apply_moving_average(float new_distance)
{
distance_buffer[buffer_index] = new_distance;
buffer_index = (buffer_index + 1) % FILTER_SIZE;
float sum = 0;
for (int i = 0; i < FILTER_SIZE; i++)
{
sum += distance_buffer[i];
}
return sum / FILTER_SIZE;
}
常见问题及解决办法
1. 测量值不准确或跳动过大
问题原因:环境干扰、电源不稳定或软件定时不精确 解决方案:
- 确保使用稳定的5V电源,避免使用USB供电
- 添加软件滤波算法(移动平均或中值滤波)
- 检查定时器配置,确保1MHz时钟精度
- 在传感器VCC和GND之间添加100nF去耦电容
2. 传感器无响应或始终返回0
问题原因:电平不匹配、接线错误或传感器故障 解决方案:
- 确认ECHO引脚使用了电平转换电路(电阻分压)
- 检查TRIG引脚是否正确输出10μs脉冲
- 使用示波器验证传感器信号
- 尝试更换传感器模块
3. 中断处理异常
问题原因:中断优先级冲突或处理函数错误 解决方案:
- 设置合适的NVIC优先级
- 确保在中断回调函数中及时清除标志位
- 避免在中断中进行复杂计算
4. 测量范围受限
问题原因:代码处理超时或定时器溢出 解决方案:
- 增加超时检测机制
- 使用32位定时器以获得更大测量范围
- 添加溢出处理逻辑
5. 多传感器干扰
问题原因:超声波传感器之间的相互干扰 解决方案:
- 分时复用传感器测量
- 为每个传感器使用独立的定时器通道
- 添加物理隔离或错开测量时间
6. 温度补偿
问题原因:声速随温度变化影响测量精度 解决方案:
// 添加温度补偿函数
float get_distance_with_temp_compensation(uint32_t pulse_width, float temperature)
{
float sound_speed = 331.3 + 0.606 * temperature; // m/s
return (pulse_width * 1e-6 * sound_speed * 100) / 2; // cm
}
通过以上完整的实现方案和问题解决方案,基于STM32的HC-SR04超声波测距系统能够稳定可靠地工作,为各种嵌入式应用提供精确的距离测量功能。