超声波测距

分享作者:wechat_15135690968
作者昵称:禹黎151
评测品牌:矽递科技
评测型号:101020010
发布时间:2025-12-31 11:07:54
1
概要
STM32超声波测距
开源口碑分享内容

一、硬件准备

  1. 主控:STM32F103C8T6 最小系统板
  2. 模块:HC-SR04(5 V 供电,信号口 5 V 但兼容 3.3 V,可直接接 F103)
  3. 供电:USB-TTL 的 5 V 给模块,3.3 V 给 MCU

二、测距原理回顾(已懂可跳过)

  1. Trig 引脚拉低→拉高→拉低,高电平 ≥10 µs,模块自动发出 8 个 40 kHz 方波
  2. Echo 随后变高,直到收到回波再变低;高电平宽度 t 即“往返时间”
  3. 距离 d = t * 0.034 cm/µs / 2 = t / 58.8 (cm)温度修正:v = 331.4 + 0.6×T(℃) m/s,可再乘 100/2 得到 cm 对应常数

三、CubeMX 图形配置(HAL 库,5 min 搞定)

  1. 新建工程→选 MCU STM32F103C8Tx
  2. RCC:外部晶振 8 M → 72 M(PLL)
  3. SYS:Debug 选 Serial Wire
  4. 引脚配置PA7 → GPIO_Output (Trig,默认命名为 Trig_Pin)PA6 → TIM3_CH1 (输入捕获)
  5. TIM3 参数Prescaler = 72-1 // 72 MHz/72 = 1 MHz → 1 µs 计数Counter Period = 0xFFFF // 最大 65 ms,足够 4 m 量程Trigger = 上升沿,分频 1,滤波 0
  6. NVIC:使能 TIM3 global interrupt(抢占优先级 2)
  7. USART1 异步 115200(方便打印结果)
  8. Project Manager→Toolchain

main.c

/* USER CODE BEGIN PV */
volatile uint32_t cap_val1 = 0;   // 第一次捕获
volatile uint32_t cap_val2 = 0;   // 第二次捕获
volatile uint8_t  capture_done = 0;
#define SPEED_SOUND_CM_US (0.034f)   // 340 m/s → 0.034 cm/µs
/* USER CODE END PV */

启动测距函数

/* USER CODE BEGIN 2 */
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);  // 开启输入捕获中断
/* USER CODE END 2 */

中断回调 + 主循环

/* USER CODE BEGIN 4 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM3) {
        if (capture_done == 0) {          // 第一次捕获→上升沿
            cap_val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
            __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);
            capture_done = 1;
        }
        else if (capture_done == 1) {     // 第二次捕获→下降沿
            cap_val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
            __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
            capture_done = 2;             // 通知主循环可以计算
        }
    }
}

int main(void)
{
  /* 初始化省略 */
  while (1)
  {
      // 1. 触发
      HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET);
      delay_us(12);   // 随便 >10 µs
      HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);

      // 2. 等待测量完成
      capture_done = 0;
      uint32_t timeout = 0;
      while (capture_done != 2 && ++timeout < 50000) delay_us(10);
      if (capture_done == 2) {
          uint32_t diff = (cap_val2 >= cap_val1) ? (cap_val2 - cap_val1)
                                                 : (0xFFFF - cap_val1 + cap_val2);
          float distance = diff * SPEED_SOUND_CM_US / 2.0f;   // cm
          printf("Distance=%.2f cm\r\n", distance);
      } else {
          printf("Timeout!\r\n");
      }

      HAL_Delay(60);   // 抗余震,最小 60 ms
  }
}

五、标准库 / 寄存器 方案(非 HAL,极简)
若项目不用 Cube,可直接操作寄存器,思路同 :

  1. GPIOA 时钟使能,PA7 推挽输出,PA6 浮空输入
  2. TIM3 1 MHz 计数,循环查询 PA6 电平,记录 t1、t2
  3. d = (t2-t1)*0.017 cm代码 30 行左右,适合对体积/启动时间极度敏感的场景。

六、常见问题与调试技巧

  1. 读数恒为 0→ Echo 引脚没进中断,用示波器看是否有高电平;检查 AFIO 重映射
  2. 读数跳动大→ 多次平均(丢最大最小再均值),或加简单 IIR 低通
  3. 最大量程不到 4 m→ 保证 5 V 供电;MCU 5 V 兼容差时可接 1 k+二极管钳位
  4. 温度影响→ 加 DS18B20/NTC,实时修正音速常数
  5. 多模块并联→ 各模块 Trig 统一控制,Echo 分别进不同捕获通道;


全部评论
暂无评论
0/144