STM32超声波模块(HC-SR04)HAL库实战指南

一、工作原理

HC-SR04超声波模块的工作原理(简洁版):

  1. 触发信号(Trig)

  2. 向Trig引脚发送 10µs的高电平脉冲,触发模块发射超声波。

  3. 超声波发射与接收

  4. 模块自动发射 8个40kHz的超声波脉冲,并等待回波(障碍物反射的超声波)。

  5. 回波信号(Echo)

  6. 当模块接收到回波时,Echo引脚输出 高电平脉冲,脉冲宽度与超声波往返时间成正比。

  7. 距离计算

  8. 测量Echo高电平时间(记为t,单位µs),距离公式:
    距离(cm) = (t × 声速) / 2
    (声速按340m/s,即 0.0343cm/µs,除以2因时间为往返)

 (1)工作原理图

触发信号就是拉高Trig引脚10us,当模块接收到这个信号就会回传超声波,此时Echo引脚被拉高,记录此时的实现为start时间,当Echo引脚被拉低后记录此时的时间为end_time。

二、代码 

我们将以STM32F103C8T6,HCSR04,并以HAL库为例展示代码。

首先配置CUBEMX,配置TRGI口为输出模式。开启TIM3的输入捕获功能。

开启TIM3后会自动捕获PB0(ECHO)口的电平变化。并在NVIC中开启TIM3的中断。

代码的具体流程如下图所示:

 

#ifndef HC_SR04_H
#define HC_SR04_H

#include "stm32f1xx_hal.h"

typedef struct {
    TIM_HandleTypeDef *htim;  // 定时器句柄
    uint16_t trig_pin;        // Trig引脚
    GPIO_TypeDef *trig_port;  // Trig端口
    float distance_cm;        // 测量距离(cm)
} HC_SR04;

void HC_SR04_Init(HC_SR04 *sensor, TIM_HandleTypeDef *htim, GPIO_TypeDef *trig_port, uint16_t trig_pin);
void HC_SR04_StartMeasurement(HC_SR04 *sensor);
float HC_SR04_GetDistance(HC_SR04 *sensor);

#endif
#include "hc_sr04.h"

volatile uint32_t rising_time = 0;
volatile uint32_t pulse_width = 0;
volatile uint8_t measurement_done = 0;

void HC_SR04_Init(HC_SR04 *sensor, TIM_HandleTypeDef *htim, GPIO_TypeDef *trig_port, uint16_t trig_pin) {
    sensor->htim = htim;
    sensor->trig_port = trig_port;
    sensor->trig_pin = trig_pin;
    sensor->distance_cm = 0.0;
    HAL_TIM_IC_Start_IT(sensor->htim, TIM_CHANNEL_1); // 启动输入捕获中断
}

void HC_SR04_StartMeasurement(HC_SR04 *sensor) {
    // 发送10us高电平触发信号
    HAL_GPIO_WritePin(sensor->trig_port, sensor->trig_pin, GPIO_PIN_SET);
    delay_us(10);  // 10us高电平 触发信号
    HAL_GPIO_WritePin(sensor->trig_port, sensor->trig_pin, GPIO_PIN_RESET);
    measurement_done = 0;
}

float HC_SR04_GetDistance(HC_SR04 *sensor) {
    if (measurement_done) {
        // 计算距离(声速340m/s,时间单位为µs)
        sensor->distance_cm = (pulse_width * 0.0343) / 2; // 单位cm
        measurement_done = 0;
        return sensor->distance_cm;
    }
    return -1.0; // 测量未完成
}

// 定时器输入捕获中断回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
    if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
        if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) { // 上升沿
            rising_time = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
            __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); // 改为下降沿捕获
        } else { // 下降沿
            uint32_t falling_time = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
            pulse_width = falling_time - rising_time;
            measurement_done = 1;
            __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); // 恢复上升沿捕获
        }
    }
}

 实例:

#include "main.h"
#include "hc_sr04.h"

HC_SR04 us_sensor;

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_TIM2_Init();

    HC_SR04_Init(&us_sensor, &htim2, GPIOA, GPIO_PIN_1); // Trig引脚PA1

    while (1) {
        HC_SR04_StartMeasurement(&us_sensor);
        HAL_Delay(100); // 测量间隔至少60ms
        float distance = HC_SR04_GetDistance(&us_sensor);
        if (distance > 0) {
            // 通过串口输出距离(需自行实现printf)
            printf("Distance: %.2f cm\r\n", distance);
        }
    }
}

 可以用串口打印输出效果。

 

作者:m0_63127436

物联沃分享整理
物联沃-IOTWORD物联网 » STM32超声波模块(HC-SR04)HAL库实战指南

发表回复