首页 大数据

STM32 超声波测距:从原理到实战,避坑指南分享

分类:大数据
字数: (8632)
阅读: (6197)
内容摘要:STM32 超声波测距:从原理到实战,避坑指南分享,

在嵌入式开发中,经常会遇到需要测量距离的场景。超声波测距模块以其成本低廉、使用方便等优点,成为了许多工程师的首选。本文将以 stm32之超声波测距 为例,深入探讨其原理、实现和优化,并分享实战中的一些经验教训。

超声波测距模块原理:回声定位的艺术

超声波测距的核心原理是利用超声波在空气中的传播速度恒定(约为 340m/s),通过测量超声波从发射到接收的时间差,来计算出距离。模块通常包含一个超声波发射器和一个超声波接收器。发射器发出一段特定频率的超声波脉冲,当遇到障碍物时,超声波会反射回来,被接收器接收。STM32 通过测量发射和接收的时间间隔,即可计算出障碍物的距离。

STM32 超声波测距:从原理到实战,避坑指南分享

距离 = (时间差 * 声速) / 2

STM32 超声波测距:从原理到实战,避坑指南分享

公式中除以 2 是因为超声波经历了从发射器到障碍物,再从障碍物返回发射器的两个过程。

STM32 超声波测距:从原理到实战,避坑指南分享

STM32 超声波测距的具体实现步骤

  1. GPIO 口配置: 首先,需要配置 STM32 的两个 GPIO 口,一个用于输出超声波触发信号(Trig),另一个用于接收超声波回响信号(Echo)。Trig 口配置为推挽输出模式,Echo 口配置为输入模式,并开启外部中断功能。

    STM32 超声波测距:从原理到实战,避坑指南分享
    // 初始化 Trig 引脚
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    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(TRIG_GPIO_Port, &GPIO_InitStruct);
    
    // 初始化 Echo 引脚
    GPIO_InitStruct.Pin = ECHO_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; // 上升沿和下降沿触发中断
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(ECHO_GPIO_Port, &GPIO_InitStruct);
    
    // 使能外部中断
    HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
    
  2. 定时器配置: 使用 STM32 的定时器来测量超声波的传播时间。配置定时器为向上计数模式,并设置合适的分频系数,以获得足够高的精度。在 Echo 引脚的上升沿启动定时器,在下降沿停止定时器,读取定时器的计数值,即为超声波的传播时间。

    // 初始化定时器
    TIM_HandleTypeDef htim3;
    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 71; // 72MHz / 72 = 1MHz, 1us per count
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim3.Init.Period = 0xFFFF; // 最大计数周期
    htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    HAL_TIM_Base_Init(&htim3);
    
  3. 中断处理函数: 编写外部中断处理函数,在 Echo 引脚的上升沿启动定时器,在下降沿停止定时器,并读取定时器的计数值。同时需要注意,在中断处理函数中需要进行一些防抖处理,以避免误触发。

    // 外部中断处理函数
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    {
        if (GPIO_Pin == ECHO_Pin)
        {
            if (HAL_GPIO_ReadPin(ECHO_GPIO_Port, ECHO_Pin) == GPIO_PIN_SET) // 上升沿
            {
                __HAL_TIM_SET_COUNTER(&htim3, 0); // 清零计数器
                HAL_TIM_Base_Start(&htim3); // 启动定时器
            }
            else // 下降沿
            {
                HAL_TIM_Base_Stop(&htim3); // 停止定时器
                time = __HAL_TIM_GET_COUNTER(&htim3); // 获取时间
                distance = (float)time * 0.034 / 2; // 计算距离,单位 cm
            }
        }
    }
    
  4. 主循环: 在主循环中,周期性地触发超声波发射,并等待接收回响信号。需要设置合适的触发周期,以避免多次测量之间的干扰。

    while (1)
    {
        HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET); // 发送触发信号
        HAL_Delay(10); // 保持 10us 以上高电平
        HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);
        HAL_Delay(100); // 等待接收回响信号
        // ... 其他代码 ...
    }
    

实战避坑经验总结:细节决定成败

  • 数据滤波: 由于环境噪声等因素的影响,测量的距离数据可能会存在一定的波动。可以采用滑动平均滤波等算法对数据进行平滑处理,提高测量的精度。
  • 温度补偿: 声速会受到温度的影响,因此需要进行温度补偿。可以通过温度传感器测量环境温度,并根据温度计算出修正后的声速。
  • 死区范围: 超声波测距模块存在一定的死区范围,即在一定距离内无法进行测量。需要根据模块的datasheet,了解模块的死区范围,并避免在死区范围内使用。
  • 角度限制: 超声波具有一定的指向性,当障碍物与超声波发射方向的夹角过大时,超声波可能无法反射回来。需要注意超声波模块的安装角度,尽量保证超声波能够垂直照射到障碍物上。
  • 电源稳定: 电源不稳定可能导致测量数据出现偏差,建议使用稳压电源为超声波模块供电。

掌握了以上技巧,你就可以轻松地将超声波测距模块应用到你的 STM32 项目中,让你的嵌入式系统拥有“眼睛”,感知周围的世界。记得根据实际应用场景进行调整和优化,才能获得最佳的测量效果。

STM32 超声波测距:从原理到实战,避坑指南分享

转载请注明出处: 加班到秃头

本文的链接地址: http://m.acea4.store/blog/665622.SHTML

本文最后 发布于2026-04-11 05:45:27,已经过了16天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 秋名山车神 3 天前
    写得真不错,原理讲解得很清晰,代码示例也很实用,正好我最近也在搞这个,学习了!
  • 小明同学 6 天前
    定时器分频系数的设置确实很重要,直接影响到测量的精度,学习到了。
  • 薄荷味的夏天 5 天前
    定时器分频系数的设置确实很重要,直接影响到测量的精度,学习到了。
  • 接盘侠 3 天前
    有没有推荐的超声波模块型号?性价比高一点的,新手入门用。
  • 风一样的男子 6 天前
    定时器分频系数的设置确实很重要,直接影响到测量的精度,学习到了。