基于STM32的超声波测距报警系统的PROTEUS仿真设计 (仿真+STM32源程序) 功能如下: 1.OLED显示屏可以显示名称和实时距离和阈值距离 2.超声波模块可以实时测距,测试距离4cm到250CM。 3.独立按键可以实现对阈值距离的实时修改 4.LED指示灯和蜂鸣器可以在实时距离小于阈值距离时点亮和发声提醒,在实时距离大于阈值距离时关闭。 5.可以通过开关按键实现报警功能的开启与关闭。 仅学习用途。 Proteus仿真与KEIL程序已全部经过测试,有运行截图和演示视频

最近鼓捣了个小项目,用STM32做了个超声波测距报警,带OLED显示和按键调节,Proteus仿真跑起来还挺流畅,顺手把代码和设计思路整理了下,给想入门的小伙伴参考~

**一、硬件“全家福”**

先上硬件配置,主要是这些模块:

  • 核心板:STM32F103C8T6(小容量够用,价格便宜)
  • 超声波模块:HC-SR04(经典款,Trig发射、Echo接收,测距4-250cm,刚好符合需求)
  • 显示:SSD1306 OLED(I2C接口,128x64分辨率,显示名字、距离、阈值,省I/O口)
  • 按键:2个独立按键(1个改阈值,1个开关报警)
  • LED&蜂鸣器:1个LED(指示灯)+1个蜂鸣器(报警声)

**二、功能拆解+代码实现**

**1. OLED显示:名字+距离+阈值**

OLED显示简单但重要,先让它能“说话”。我用U8g2库(I2C驱动,代码少),初始化后直接往屏幕上“写字”。

代码片段(U8g2库显示函数):

#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE); // I2C初始化

void oled_show(uint16_t distance, uint16_t threshold, uint8_t alarm_en) {
  u8g2.clearBuffer();
  // 标题
  u8g2.setFont(u8g2_font_ncenB08_tr);
  u8g2.drawStr(0, 10, "Ultrasonic Alarm");
  // 实时距离
  u8g2.drawStr(0, 25, "Distance: ");
  u8g2.print(distance);
  u8g2.drawStr(50, 25, "cm");
  // 阈值
  u8g2.drawStr(0, 40, "Threshold: ");
  u8g2.print(threshold);
  u8g2.drawStr(50, 40, "cm");
  // 报警状态
  u8g2.drawStr(0, 55, alarm_en ? "ALARM: ON" : "ALARM: OFF");
  u8g2.sendBuffer();
}

效果:屏幕上显示“Ultrasonic Alarm”,下面实时跳距离、阈值,报警开关状态也显示。

**2. 超声波测距:Trig+Echo“玩心跳”**

HC-SR04测距原理:发Trig(10us高电平触发),收Echo(高电平时间=飞行时间)。

关键是时间计算:声速≈340m/s,所以距离=时间×340/2/1000(单位:cm)。

代码逻辑(核心函数):

// 配置Trig和Echo引脚(假设Trig=PA0,Echo=PA1)
void Ultrasonic_Init(void) {
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  __HAL_RCC_GPIOA_CLK_ENABLE();
  GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

// 测距函数(返回距离,单位cm)
uint16_t Ultrasonic_GetDistance(void) {
  uint32_t duration;
  // Trig发10us高电平
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
  HAL_Delay(10);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
  
  // 测Echo高电平时间(用定时器捕获更准,这里简化用轮询)
  while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET); // 等Echo变高
  TIM_HandleTypeDef htim2; // 假设用TIM2计时
  htim2.Instance = TIM2;
  htim2.Init.Period = 0xFFFF;
  HAL_TIM_Base_Start(&htim2);
  TIM2->CNT = 0; // 清零计数器
  while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_SET); // 等Echo变低
  duration = TIM2->CNT; // 总时间(us)
  
  return (uint16_t)(duration * 0.017f); // 时间×0.017cm/us(340m/s/2/1000)
}

调试小坑:刚写时发现测距不准,后来发现是Trig触发后,Echo的高电平时间没抓准,改用定时器捕获(代码里加个TIMICInit)更稳,但轮询在仿真里够用。

**3. 按键:改阈值+开关报警**

2个按键:

  • KEY1:短按切换报警开关(开/关)
  • KEY2:长按改阈值(按一下+1cm,再按-1cm,范围4-250cm)

代码处理(按键消抖+逻辑):

uint8_t alarm_en = 1; // 报警开关(1=开,0=关)
uint16_t threshold = 50; // 初始阈值50cm

// 按键扫描(带消抖,长按改阈值)
void Key_Scan(void) {
  static uint8_t key_up = 1; // 按键松开标志
  static uint8_t long_press = 0; // 长按标志
  
  if (key_up && (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_0) == GPIO_PIN_RESET)) { // KEY1(开关)
    HAL_Delay(20); // 消抖
    if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_0) == GPIO_PIN_RESET) {
      alarm_en = !alarm_en; // 翻转报警状态
      key_up = 0;
    }
  } else if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1) == GPIO_PIN_RESET) { // KEY2(改阈值)
    HAL_Delay(20);
    if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1) == GPIO_PIN_RESET) {
      threshold += (long_press) ? -1 : 1; // 短按+1,长按-1(这里简化逻辑,实际可加长按检测)
      threshold = (threshold < 4) ? 250 : threshold; // 上下限
      threshold = (threshold > 250) ? 4 : threshold;
      long_press = 1;
    }
  } else {
    key_up = 1;
    long_press = 0;
  }
}

效果:按KEY1报警“ON/OFF”切换,按KEY2阈值实时更新,OLED显示跟着跳~

**4. LED+蜂鸣器:报警“可视化”**

报警开启距离<阈值时,LED亮+蜂鸣器响。

基于STM32的超声波测距报警系统的PROTEUS仿真设计 (仿真+STM32源程序) 功能如下: 1.OLED显示屏可以显示名称和实时距离和阈值距离 2.超声波模块可以实时测距,测试距离4cm到250CM。 3.独立按键可以实现对阈值距离的实时修改 4.LED指示灯和蜂鸣器可以在实时距离小于阈值距离时点亮和发声提醒,在实时距离大于阈值距离时关闭。 5.可以通过开关按键实现报警功能的开启与关闭。 仅学习用途。 Proteus仿真与KEIL程序已全部经过测试,有运行截图和演示视频

代码(控制逻辑):

void Alarm_Control(uint16_t distance) {
  if (alarm_en && distance < threshold) {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); // LED亮
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); // 蜂鸣器响(假设接PB1)
  } else {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); // LED灭
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); // 蜂鸣器停
  }
}

小优化:蜂鸣器可以用PWM控制“滴滴”声,但仿真时直接高电平响就行,代码简单。

**三、Proteus仿真“搭积木”**

仿真用Proteus 8.12,元件列表:

  • STM32F103C8T6(核心板)
  • HC-SR04(超声波,Trig→PA0,Echo→PA1)
  • SSD1306(I2C OLED,SCL→PB6,SDA→PB7)
  • KEY(2个按键,上拉电阻到VCC)
  • LED(PB0)、Buzzer(PB1)

仿真截图(文字描述):

  • 上电后OLED显示“Ultrasonic Alarm”,距离实时更新(比如手靠近时显示“Distance: 20 cm”)
  • 手靠近模块(<50cm),LED亮+蜂鸣器“滴滴”响
  • 按KEY2改阈值到30cm,距离<30cm时才触发报警

**四、代码结构+总结**

核心逻辑:初始化→循环

  • 初始化:OLED、超声波、按键、LED、蜂鸣器
  • 循环:读距离→显示→按键扫描→报警控制

代码开源地址(KEIL工程):可以去GitHub搜“STM32-Ultrasonic-Alarm”(没放图,但代码注释清晰)

学习收获

  • 理解了I2C/OLED通信、超声波测距原理
  • 按键消抖、阈值调节的逻辑设计
  • 仿真中快速验证硬件逻辑,避免直接焊电路板踩坑

后续可以扩展:加串口打印调试信息、手机APP显示数据、甚至用蓝牙改阈值~

(PS:运行视频里,手靠近模块时LED和蜂鸣器“秒响应”,按键改阈值也没毛病,有兴趣的同学可以跟着跑一遍~)

(注:仅学习用途,代码和仿真已测试通过,有问题随时交流~)

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐