基于STM32的超声波测距报警系统(Proteus仿真+代码)
基于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和蜂鸣器“秒响应”,按键改阈值也没毛病,有兴趣的同学可以跟着跑一遍~)

(注:仅学习用途,代码和仿真已测试通过,有问题随时交流~)
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)