HC-SR04超声波测距原理与应用

HC-SR04超声波传感器模块的原理核心在于其工作时序,具体使用方法则依赖于主控芯片(如STM32)的GPIO控制与定时器输入捕获功能。以下是其详细解析与实现方案。

一、 HC-SR04 模块工作原理与时序

HC-SR04模块通过Trig引脚接收触发信号,内部电路产生超声波脉冲,并通过Echo引脚返回一个高电平脉冲,其宽度与超声波往返时间成正比。

工作时序是理解其原理的关键,具体步骤如下:

  1. 触发阶段:主控芯片向Trig引脚发送一个至少10μs的高电平脉冲信号。
  2. 模块响应:模块内部自动发射8个40kHz的超声波脉冲
  3. 回波检测:模块检测回波,并将Echo引脚拉高。
  4. 结果输出:Echo引脚高电平的持续时间(即脉冲宽度)即为超声波从发射到返回的时间 t
  5. 距离计算:根据公式 距离 = (t * 声速) / 2 计算。常温下声速约为340m/s,因此 距离(cm) ≈ (t(us) / 58)距离(cm) ≈ (t(us) * 0.034) / 2

其工作时序可概括为下表:

步骤Trig引脚Echo引脚模块内部动作
1. 初始化低电平低电平空闲状态
2. 触发≥10μs高电平低电平收到触发信号,发射8个40kHz超声波
3. 回波等待恢复低电平由低变高开始计时,等待回波
4. 回波返回保持低电平保持高电平接收到回波
5. 输出结果保持低电平由高变低输出结束,高电平持续时间即为超声波往返时间 t

二、 基于STM32与HAL库的驱动实现

以下以STM32F103C8T6为例,使用HAL库演示完整的驱动流程,包含GPIO初始化、触发信号发送和通过输入捕获模式测量Echo高电平时间。

1. 硬件连接

HC-SR04引脚STM32引脚功能说明
VCC5V供电
TrigPA0 (GPIO输出)触发信号输出
EchoPA1 (GPIO输入/定时器通道)回波信号输入
GNDGND共地

2. 代码实现

步骤一:GPIO与定时器初始化
配置Trig为推挽输出,Echo为上拉输入。同时配置一个定时器(如TIM2)用于输入捕获。

// HC_SR04.h
#ifndef __HC_SR04_H
#define __HC_SR04_H
#include "main.h"

#define TRIG_PIN GPIO_PIN_0
#define TRIG_PORT GPIOA
#define ECHO_PIN GPIO_PIN_1
#define ECHO_PORT GPIOA

void HC_SR04_Init(void);
float HC_SR04_Get_Distance(void);

#endif
// HC_SR04.c
#include "hc_sr04.h"
#include "tim.h" // 假设已配置TIM2用于输入捕获

// 初始化函数
void HC_SR04_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // 配置Trig引脚为输出
    GPIO_InitStruct.Pin = TRIG_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(TRIG_PORT, &GPIO_InitStruct);
    HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_RESET); // 初始化为低电平

    // 配置Echo引脚为输入(也可配置为定时器输入捕获通道,见下文)
    GPIO_InitStruct.Pin = ECHO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP; // 上拉,确保空闲时为高电平
    HAL_GPIO_Init(ECHO_PORT, &GPIO_InitStruct);

    // 启动定时器(以TIM2为例,1MHz计数频率,即1us计数一次)
    HAL_TIM_Base_Start(&htim2);
}

步骤二:发送触发信号与测量脉冲宽度(查询法)
一种简单的方法是使用查询方式测量Echo高电平时间。

// HC_SR04.c (续)
float HC_SR04_Get_Distance(void) {
    uint32_t start_time = 0, end_time = 0, pulse_width = 0;
    float distance_cm = 0.0;

    // 1. 发送至少10us的Trig高电平脉冲
    HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_SET);
    delay_us(12); // 延时12微秒,略大于最小值
    HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_RESET);

    // 2. 等待Echo变为高电平(超声波发射开始)
    while(HAL_GPIO_ReadPin(ECHO_PORT, ECHO_PIN) == GPIO_PIN_RESET);
    start_time = __HAL_TIM_GET_COUNTER(&htim2); // 记录开始时间戳

    // 3. 等待Echo变为低电平(回波接收结束)
    while(HAL_GPIO_ReadPin(CHO_PORT, ECHO_PIN) == GPIO_PIN_SET);
    end_time = __HAL_TIM_GET_COUNTER(&htim2); // 记录结束时间戳

    // 4. 处理定时器溢出(如果定时器是16位,如65ms溢出一次)
    if(end_time < start_time) {
        pulse_width = (0xFFFF - start_time) + end_time + 1;
    } else {
        pulse_width = end_time - start_time;
    }

    // 5. 计算距离:距离(cm) = 时间(us) / 58
    distance_cm = pulse_width / 58.0;

    // 6. 增加简单的滤波(例如,只接受2cm-400cm范围内的值)
    if(distance_cm > 400.0 || distance_cm < 2.0) {
        distance_cm = 0.0;
    }
    return distance_cm;
}

步骤三:主循环调用

// main.c
#include "hc_sr04.h"

int main(void) {
    HAL_Init();
    SystemClock_Config();
    HC_SR04_Init();

    while (1) {
        float dist = HC_SR04_Get_Distance();
        // 通过串口打印距离信息
        printf("Distance: %.2f cm
", dist);
        HAL_Delay(100); // 每100ms测量一次
    }
}

3. 进阶:使用输入捕获模式提高精度

查询法会占用CPU。更高效、精确的方法是使用定时器的输入捕获功能。配置定时器的一个通道(如TIM2_CH1)连接到Echo引脚,在上升沿和下降沿触发捕获中断,自动记录时间戳。

关键配置与代码逻辑如下:

  1. 定时器配置:将TIM2通道1配置为输入捕获模式,双边沿触发。
  2. 中断处理:在捕获回调函数中,计算两次捕获(上升沿和下降沿)的时间差。
// 在输入捕获中断回调函数中的示例逻辑
uint32_t ic_val1, ic_val2;
uint32_t difference;
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
    if(is_first_capture == 0) { // 第一次捕获,上升沿
        ic_val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
        __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);
        is_first_capture = 1;
    } else if(is_first_capture == 1) { // 第二次捕获,下降沿
        ic_val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
        __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
        if(ic_val2 > ic_val1) {
            difference = ic_val2 - ic_val1;
        } else {
            difference = (0xFFFF - ic_val1) + ic_val2;
        }
        distance_cm = difference / 58.0;
        is_first_capture = 0;
    }
}

三、 应用注意事项与优化

  1. 测量周期:两次测量之间需间隔至少60ms,以防止信号干扰。
  2. 温度补偿:声速受温度影响。为提高精度,可集成温度传感器(如DS18B20),使用公式 V = 331.4 + 0.6 * T (m/s) 动态计算声速,其中T为摄氏温度。
  3. 滤波处理:实际应用中需加入软件滤波(如中值滤波、均值滤波)以消除偶然误差。
  4. 测量范围:HC-SR04的有效测距通常为2cm至400cm,超出此范围的回波信号可能不可靠。
  5. 硬件连接:若测量不稳定,可在VCC和GND之间并联一个100uF的电解电容以稳定电源,并在Trig和Echo信号线上串联一个100-200欧姆的电阻以抑制过冲。

参考来源

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值