HC-SR04超声波模块测距功能驱动程序

bitm.c

#include "./BSP/TIMER/btim.h"

/* 硬件配置 */
#define TRIG_PORT       GPIOB
#define TRIG_PIN        GPIO_PIN_5
#define ECHO_PORT       GPIOB
#define ECHO_PIN        GPIO_PIN_6

/* 全局变量 */
uint32_t g_echo_rising_time = 0;  // 上升沿时间戳
uint32_t g_echo_falling_time = 0; // 下降沿时间戳
uint8_t g_measurement_flag = 0;   // 测量状态标志
TIM_HandleTypeDef g_timx_handle;           // 定时器句柄

/* 定时器时钟配置(示例使用TIM3,72MHz主频) */
void btim_timx_int_init(void)
{
    __HAL_RCC_TIM3_CLK_ENABLE();  // 使能TIM3时钟

    g_timx_handle.Instance = TIM3;
    g_timx_handle.Init.Prescaler = 71;         // 72分频,1MHz计数频率(1us计数)
    g_timx_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    g_timx_handle.Init.Period = 0xFFFF;        // 最大计数值
    g_timx_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_Base_Init(&g_timx_handle);

    // 初始化GPIO
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* PB端口时钟使能 */
    __HAL_RCC_GPIOB_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_HIGH;
    HAL_GPIO_Init(TRIG_PORT, &GPIO_InitStruct);

    /* ECHO引脚配置 */
    GPIO_InitStruct.Pin = ECHO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;  // 双边沿触发
    GPIO_InitStruct.Pull = GPIO_PULLUP;                  // 上拉电阻
    HAL_GPIO_Init(ECHO_PORT, &GPIO_InitStruct);

    /* 配置外部中断 */
    HAL_NVIC_SetPriority(EXTI9_5_IRQn, 2, 0);  // PB5/PB6共用EXTI9_5中断
    HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
}

/**
  * @brief 触发超声波测距
  */
void Trigger_Ultrasound(void)
{
    HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_SET);
    delay_us(12);  // 精确12us高电平触发信号
    HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_RESET);
}

/**
  * @brief 外部中断服务函数
  */
void EXTI9_5_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(ECHO_PIN);  // 处理PB6引脚中断
}

/**
  * @brief 外部中断回调函数
  */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if(GPIO_Pin == ECHO_PIN)
    {
        if(HAL_GPIO_ReadPin(ECHO_PORT, ECHO_PIN))
        {
            /* 上升沿:开始计时 */
            g_echo_rising_time = __HAL_TIM_GET_COUNTER(&g_timx_handle);
            HAL_TIM_Base_Start(&g_timx_handle);  // 启动定时器
            g_measurement_flag = 1;              // 标记测量开始
        }
        else
        {
            /* 下降沿:停止计时 */
            g_echo_falling_time = __HAL_TIM_GET_COUNTER(&g_timx_handle);
            HAL_TIM_Base_Stop(&g_timx_handle);   // 停止定时器
            g_measurement_flag = 2;              // 标记测量完成
        }
    }
}

/**
  * @brief 获取测量结果(单位:厘米)
  */
float get_distance(void)
{
    uint32_t timeout = 0;
    float distance = 0;

    /* 发送触发信号 */
    Trigger_Ultrasound();

    /* 等待测量开始 */
    timeout = HAL_GetTick();
    while(g_measurement_flag < 1)
    {
        if(HAL_GetTick() - timeout > 100) return -1;  // 100ms超时
    }

    /* 等待测量完成 */
    timeout = HAL_GetTick();
    while(g_measurement_flag != 2)
    {
        if(HAL_GetTick() - timeout > 60)  // 最大测量时间60ms(对应10米)
        {
            HAL_TIM_Base_Stop(&g_timx_handle);
            g_measurement_flag = 0;
            return -2;  // 信号丢失
        }
    }

    /* 计算时间差(考虑定时器溢出)*/
    uint32_t time_diff = (g_echo_falling_time >= g_echo_rising_time) ?
                        (g_echo_falling_time - g_echo_rising_time) :
                        (0xFFFF - g_echo_rising_time + g_echo_falling_time);

    /* 计算距离:time(us) * 340m/s / 2 = (time * 0.034)/2 cm */
    distance = time_diff * 0.017f;  // 优化后的计算公式

    /* 重置测量标志 */
    g_measurement_flag = 0;

    /* 有效距离过滤(2cm-500cm)*/
    return (distance > 2 && distance < 500) ? distance : -3;
}

bitm.h

#ifndef __BTIM_H
#define __BTIM_H

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
/******************************************************************************************/
/* 基本定时器 定义 */
/* TIMX 中断定义
* 默认是针对TIM6/TIM7
* 注意: 通过修改这4个宏定义,可以支持TIM1~TIM8任意一个定时器.
*/
#define BTIM_TIMX_INT                       TIM6
#define BTIM_TIMX_INT_IRQn                  TIM6_DAC_IRQn
#define BTIM_TIMX_INT_IRQHandler            TIM6_DAC_IRQHandler
#define BTIM_TIMX_INT_CLK_ENABLE()          do{ __HAL_RCC_TIM6_CLK_ENABLE(); }while(0)  /* TIM6 时钟使能 */

/******************************************************************************************/
void btim_timx_int_init(void);
float get_distance(void);

#endif

关注我

GitHub:https://github.com/PastKing

Gitee:https://gitee.com/past-dust

公众号:

图片[1]-HC-SR04超声波模块测距功能驱动程序 - 昔尘源分享-昔尘源分享

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容