单片机:实现HC-SR04超声波测距(附带源码)

使用单片机实现 HC-SR04 超声波测距模块 的功能,通常用于测量物体与超声波传感器之间的距离。HC-SR04 模块通过发射超声波信号并测量其返回时间来计算距离。单片机(如 STM32、51 系列、Arduino 等)可用来控制该模块的工作,并处理返回的脉冲信号。

下面我会提供一个基于单片机的 HC-SR04 超声波测距实现方案,并详细阐述每个步骤的设计思路和代码实现。

1. HC-SR04 超声波模块工作原理

HC-SR04 模块通过发送一系列声波脉冲来测量与目标物体的距离。模块由两部分组成:

  • 发射部分(Trigger):用来发送 10 微秒的脉冲,激发超声波信号的发送。
  • 接收部分(Echo):接收从目标物体反射回来的超声波脉冲,产生一个持续高电平的信号,持续时间等于声波往返的时间。
  • 计算公式:

    距离 = (回波时间 × 声速) / 2

  • 声速约为 340 m/s(即 0.034 cm/μs),所以计算的公式为:

    上式中,回波时间指的是从发送脉冲到接收到返回信号的时间。

  • 2. 硬件连接

    HC-SR04 模块有四个引脚:

  • VCC:电源(通常为 5V)
  • GND:地线
  • Trig:触发引脚(用于发射超声波脉冲)
  • Echo:回声引脚(接收返回的超声波脉冲)
  • 单片机的引脚连接方式:

  • Trig:连接到单片机的一个 GPIO 引脚,用于触发超声波发射。
  • Echo:连接到单片机的另一个 GPIO 引脚,用于接收回声信号。
  • 3. 设计思路

    本设计采用单片机控制 HC-SR04 模块,通过控制 Trig 引脚生成超声波触发脉冲,并通过 Echo 引脚测量回波信号的持续时间。具体的步骤包括:

    1. 触发超声波信号:通过向 Trig 引脚输出一个 10 微秒的高电平脉冲,激发 HC-SR04 发射超声波。
    2. 测量回波时间:通过读取 Echo 引脚的高电平持续时间来计算回波时间。单片机根据此时间计算距离。
    3. 计算距离:根据回波时间和声速公式计算物体到传感器的距离。

    4. 软件设计

    以 STM32 微控制器为例,介绍如何实现该功能。可以使用 STM32 的 HAL 库来实现超声波测距。

    4.1 初始化 GPIO

    首先需要初始化 GPIO 引脚:

  • Trig 引脚配置为输出模式,用于发射触发脉冲。
  • Echo 引脚配置为输入模式,用于接收回波信号。
  • #include "stm32f4xx_hal.h"
    #include <stdio.h>
    
    #define TRIG_PIN        GPIO_PIN_0   // Trig 引脚
    #define ECHO_PIN        GPIO_PIN_1   // Echo 引脚
    #define GPIO_PORT       GPIOA        // 假设使用 GPIOA 端口
    
    void SystemClock_Config(void);
    void GPIO_Init(void);
    void trigger_ultrasonic_pulse(void);
    uint32_t read_echo_pulse(void);
    float calculate_distance(uint32_t pulse_width);
    
    int main(void)
    {
        HAL_Init();  // 初始化 HAL 库
        SystemClock_Config();  // 配置系统时钟
        GPIO_Init();  // 初始化 GPIO 引脚
    
        while (1)
        {
            trigger_ultrasonic_pulse();  // 触发超声波信号
            uint32_t pulse_time = read_echo_pulse();  // 获取回波时间
            float distance = calculate_distance(pulse_time);  // 计算距离
    
            // 可以通过串口输出距离值,或者在 LCD 上显示
            printf("Distance: %.2f cm\n", distance);
    
            HAL_Delay(500);  // 每 500 毫秒测量一次
        }
    }
    
    // 系统时钟配置函数(根据具体硬件配置)
    void SystemClock_Config(void)
    {
        // 这里可以根据需要配置时钟,一般不需要修改
    }
    
    // GPIO 初始化:配置 Trig 为输出,Echo 为输入
    void GPIO_Init(void)
    {
        GPIO_InitTypeDef GPIO_InitStruct = {0};
    
        // 启用 GPIO 时钟
        __HAL_RCC_GPIOA_CLK_ENABLE();
    
        // 初始化 Trig 引脚(输出)
        GPIO_InitStruct.Pin = TRIG_PIN;
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
        HAL_GPIO_Init(GPIO_PORT, &GPIO_InitStruct);
    
        // 初始化 Echo 引脚(输入)
        GPIO_InitStruct.Pin = ECHO_PIN;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIO_PORT, &GPIO_InitStruct);
    }
    
    // 触发超声波信号:生成 10 微秒的脉冲
    void trigger_ultrasonic_pulse(void)
    {
        HAL_GPIO_WritePin(GPIO_PORT, TRIG_PIN, GPIO_PIN_SET);  // Trig 引脚置高
        HAL_Delay(0);  // 保持高电平至少 10 微秒
        HAL_GPIO_WritePin(GPIO_PORT, TRIG_PIN, GPIO_PIN_RESET);  // Trig 引脚置低
    }
    
    // 读取 Echo 引脚的高电平持续时间(脉冲宽度)
    uint32_t read_echo_pulse(void)
    {
        uint32_t pulse_width = 0;
        
        // 等待 Echo 引脚为高电平
        while (HAL_GPIO_ReadPin(GPIO_PORT, ECHO_PIN) == GPIO_PIN_RESET);
    
        // 计数 Echo 引脚高电平的持续时间
        while (HAL_GPIO_ReadPin(GPIO_PORT, ECHO_PIN) == GPIO_PIN_SET)
        {
            pulse_width++;  // 每次延时 1 毫秒
            HAL_Delay(1);   // 延时 1 毫秒,计数单位是毫秒
        }
    
        return pulse_width;  // 返回脉冲宽度(单位:毫秒)
    }
    
    // 根据回波时间计算距离(单位:cm)
    float calculate_distance(uint32_t pulse_width)
    {
        // 使用公式:距离 (cm) = (回波时间 (微秒) * 0.034) / 2
        // 由于我们在 read_echo_pulse 函数中每次延时 1 毫秒,pulse_width 其实已经是毫秒单位。
        float distance = pulse_width * 0.034 / 2.0;  // 公式:距离 = 时间 * 声速 / 2
        return distance;
    }
    

    代码解读

    1. 初始化 GPIO

    2. GPIO_Init() 函数初始化了两个 GPIO 引脚:
    3. Trig 引脚(GPIO_PIN_0):用于触发超声波发射,配置为推挽输出模式。
    4. Echo 引脚(GPIO_PIN_1):用于接收超声波回波信号,配置为输入模式。
    5. 触发超声波发射信号

    6. trigger_ultrasonic_pulse() 函数通过在 Trig 引脚输出一个 10 微秒的高电平脉冲来激发 HC-SR04 模块发射超声波信号。
    7. 测量回波时间

    8. read_echo_pulse() 函数通过读取 Echo 引脚的高电平持续时间来获取回波信号的时长。通过 pulse_width 计数,记录回波信号持续的时间。
    9. 计算距离

    10. calculate_distance() 函数根据回波信号的时长(pulse_width)和声速公式来计算物体与传感器的距离:
    11. \text{距离 (cm)} = \frac{\text{回波时间 (毫秒)} \times 0.034}{2} ] 其中,0.034 为声速(单位:cm/μs)。

    12. 主循环

    13. main() 函数中,程序会不断触发超声波信号,并读取回波时间,通过计算得到距离,最后打印出距离值。每次测量之间有 500 毫秒的延时。

    5. 项目总结

    5.1 硬件总结
    1. HC-SR04 超声波模块:通过发射和接收超声波信号来测量距离,连接到单片机的 GPIO 引脚(TrigEcho)。
    2. 单片机:负责控制 Trig 引脚生成脉冲,并读取 Echo 引脚的高电平持续时间,计算并输出距离。
    5.2 软件总结
    1. GPIO 初始化:配置 Trig 为输出,Echo 为输入。
    2. 触发超声波信号:通过给 Trig 引脚发送 10 微秒的高电平脉冲来激发 HC-SR04 发射超声波。
    3. 回波时间测量:通过读取 Echo 引脚的高电平持续时间,计算超声波往返所需的时间。
    4. 距离计算:根据回波时间和声速公式计算距离,并输出测量结果。
    5.3 优化与扩展
    1. 更高精度:为了获得更高精度的距离,可以增加计时的精度(例如,使用定时器或更高分辨率的计时方法)。
    2. 多次测量平均值:可以通过多次测量距离并取平均值来提高测量的稳定性和精度。
    3. 串口输出:通过串口将测量的距离数据发送到 PC 或其他设备进行显示。
    4. 电源管理:对于电池供电的系统,可以在不需要测量时关闭超声波模块,以节省电量。

    通过以上设计,我们成功实现了使用单片机控制 HC-SR04 超声波模块进行测距的功能,并能够在不同的应用场景下测量距离。

    作者:Katie。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 单片机:实现HC-SR04超声波测距(附带源码)

    发表回复