基于STM32的超声波测距报警系统设计与实现
摘要:本文设计了一种基于STM32的超声波测距报警系统,系统通过STM32微控制器与超声波传感器HC-SR04实现实时测距,测距范围4cm至250cm。OLED显示屏实时显示测距名称、实时距离和阈值距离,独立按键可修改阈值距离。当实时距离小于阈值时,LED指示灯点亮,蜂鸣器发声提醒;实时距离大于阈值时,LED和蜂鸣器关闭。系统还设有开关按键,用于控制报警功能的开启与关闭。系统具有测量精度高、响应速度快、操作简便等优点,可应用于智能安防、机器人避障等领域。
关键词:STM32;超声波测距;报警系统;OLED显示屏;HC-SR04
一、引言
随着科技的不断发展,超声波测距技术在各个领域得到了广泛的应用,如智能安防、机器人避障、汽车倒车雷达等。基于STM32的超声波测距报警系统结合了STM32微控制器的高性能与超声波测距技术的精确性,能够实现实时、准确的距离测量,并在距离小于设定阈值时发出报警信号。本文旨在设计并实现这样一个系统,通过OLED显示屏实时显示测距信息,独立按键修改阈值距离,LED指示灯和蜂鸣器实现报警功能,并通过开关按键控制报警的开启与关闭。
二、系统总体设计
(一)系统组成
本系统主要由以下几个部分组成:
- STM32微控制器:作为系统的核心处理器,负责接收超声波传感器的数据,进行数据处理,并控制OLED显示屏、LED指示灯、蜂鸣器以及独立按键和开关按键。
- 超声波传感器HC-SR04:用于发射和接收超声波信号,通过测量超声波从发射到接收的时间差来计算距离。
- OLED显示屏:用于实时显示测距名称、实时距离和阈值距离。
- 独立按键:用于实时修改阈值距离。
- LED指示灯:在实时距离小于阈值距离时点亮,提示用户。
- 蜂鸣器:在实时距离小于阈值距离时发声,提醒用户。
- 开关按键:用于控制报警功能的开启与关闭。
(二)系统功能
- 实时测距:系统能够实时测量超声波传感器与目标物体之间的距离,测量范围4cm至250cm。
- OLED显示:OLED显示屏实时显示测距名称(如“超声波测距”)、实时距离(如“实时距离:XXcm”)和阈值距离(如“阈值距离:XXcm”)。
- 阈值修改:用户可以通过独立按键实时修改阈值距离,方便根据不同的应用场景进行调整。
- 报警功能:当实时距离小于阈值距离时,LED指示灯点亮,蜂鸣器发声提醒;当实时距离大于阈值距离时,LED指示灯熄灭,蜂鸣器停止发声。
- 报警开关:用户可以通过开关按键控制报警功能的开启与关闭,满足不同的使用需求。
三、硬件电路设计
(一)STM32微控制器
本系统采用STM32F103系列微控制器,该系列微控制器基于ARM Cortex-M3内核,具有高性能、低功耗、丰富的外设接口等优点。在本系统中,STM32微控制器主要完成以下任务:
- 通过GPIO接口与超声波传感器HC-SR04进行通信,控制超声波的发射和接收。
- 通过I²C或SPI接口与OLED显示屏进行通信,发送显示命令和数据。
- 读取独立按键和开关按键的状态,根据按键状态进行相应的操作。
- 控制LED指示灯和蜂鸣器的开关状态,实现报警功能。
(二)超声波传感器HC-SR04
HC-SR04是一款常用的超声波测距模块,其工作原理是利用超声波在空气中的传播速度和时间差来测量距离。HC-SR04模块具有4个引脚,分别是VCC(电源正极)、GND(电源负极)、Trig(触发信号引脚)和Echo(回波信号引脚)。
在本系统中,HC-SR04模块的VCC引脚和GND引脚分别连接到STM32开发板的VCC和GND引脚,Trig引脚和Echo引脚分别连接到STM32开发板的GPIO引脚。STM32微控制器通过向Trig引脚发送一个10us以上的高电平信号来触发超声波的发射,然后检测Echo引脚的高电平持续时间,通过公式s=2v×t(其中s为距离,v为声速,t为Echo引脚高电平持续时间)计算出目标物体的距离。
(三)OLED显示屏
OLED显示屏采用I²C接口的0.96寸OLED模块,具有高分辨率、高对比度、低功耗等优点。OLED显示屏的GND引脚连接到STM32开发板的GND引脚,VCC引脚连接到STM32开发板的VIN引脚(提供5V供电),SDA引脚和SCL引脚分别连接到STM32开发板的I²C接口的SDA引脚和SCL引脚。
STM32微控制器通过I²C协议与OLED显示屏进行通信,发送显示命令和数据。OLED显示屏用于实时显示测距名称、实时距离和阈值距离,方便用户了解当前的测距状态。
(四)独立按键和开关按键
独立按键和开关按键分别连接到STM32开发板的GPIO引脚。独立按键用于实时修改阈值距离,开关按键用于控制报警功能的开启与关闭。
STM32微控制器通过读取GPIO引脚的状态来判断按键是否被按下。当独立按键被按下时,STM32微控制器根据按键按下的次数和时间来调整阈值距离;当开关按键被按下时,STM32微控制器切换报警功能的开启与关闭状态。
(五)LED指示灯和蜂鸣器
LED指示灯和蜂鸣器分别连接到STM32开发板的GPIO引脚。LED指示灯用于在实时距离小于阈值距离时点亮,提示用户;蜂鸣器用于在实时距离小于阈值距离时发声,提醒用户。
STM32微控制器通过控制GPIO引脚的高低电平来控制LED指示灯和蜂鸣器的开关状态。当实时距离小于阈值距离时,STM32微控制器将对应的GPIO引脚设置为高电平,点亮LED指示灯并驱动蜂鸣器发声;当实时距离大于阈值距离时,STM32微控制器将对应的GPIO引脚设置为低电平,熄灭LED指示灯并停止蜂鸣器发声。
四、软件设计
(一)开发环境
本系统采用Keil MDK作为开发环境,Keil MDK是一款功能强大的ARM微控制器集成开发环境,支持C/C++编程语言,提供了丰富的调试功能和库函数,方便用户进行程序开发和调试。
(二)主程序设计
主程序是整个系统的核心,负责初始化各个外设模块、读取超声波传感器的数据、处理数据并控制OLED显示屏、LED指示灯、蜂鸣器以及独立按键和开关按键。主程序的流程图如下:
- 系统初始化:初始化STM32微控制器的时钟、GPIO、I²C、定时器等外设模块,配置超声波传感器HC-SR04的Trig引脚和Echo引脚为GPIO输出和输入模式,配置OLED显示屏的I²C接口,配置独立按键和开关按键的GPIO引脚为输入模式,配置LED指示灯和蜂鸣器的GPIO引脚为输出模式。
- 读取按键状态:读取独立按键和开关按键的状态,根据按键状态进行相应的操作。如果独立按键被按下,则根据按键按下的次数和时间来调整阈值距离;如果开关按键被按下,则切换报警功能的开启与关闭状态。
- 超声波测距:向超声波传感器HC-SR04的Trig引脚发送一个10us以上的高电平信号,触发超声波的发射,然后检测Echo引脚的高电平持续时间,通过公式计算出目标物体的距离。
- 数据处理与显示:将测量到的距离与阈值距离进行比较,如果实时距离小于阈值距离且报警功能开启,则点亮LED指示灯并驱动蜂鸣器发声;否则熄灭LED指示灯并停止蜂鸣器发声。将测距名称、实时距离和阈值距离通过I²C协议发送到OLED显示屏进行显示。
- 循环执行:重复执行步骤2至步骤4,实现实时测距和报警功能。
(三)关键子程序设计
- 超声波测距子程序
超声波测距子程序负责向超声波传感器HC-SR04的Trig引脚发送触发信号,并检测Echo引脚的高电平持续时间,通过公式计算出目标物体的距离。子程序的流程图如下:
(1)发送触发信号:将Trig引脚设置为高电平,持续10us以上,然后设置为低电平。
(2)检测回波信号:检测Echo引脚的高电平持续时间,记录时间差t。
(3)计算距离:根据公式s=2v×t(其中v为声速,取340m/s;t为Echo引脚高电平持续时间,单位为秒)计算出目标物体的距离,并将距离转换为厘米单位。
(4)返回距离值:将计算得到的距离值返回给主程序。
- OLED显示子程序
OLED显示子程序负责将测距名称、实时距离和阈值距离通过I²C协议发送到OLED显示屏进行显示。子程序的流程图如下:
(1)初始化OLED显示屏:通过I²C协议向OLED显示屏发送初始化命令,设置显示屏的分辨率、对比度等参数。
(2)清屏:向OLED显示屏发送清屏命令,清除显示屏上的内容。
(3)显示测距名称:将测距名称(如“超声波测距”)转换为显示数据,通过I²C协议发送到OLED显示屏进行显示。
(4)显示实时距离和阈值距离:将实时距离和阈值距离转换为显示数据,通过I²C协议发送到OLED显示屏进行显示。实时距离和阈值距离以“实时距离:XXcm”和“阈值距离:XXcm”的格式显示。
- 按键处理子程序
按键处理子程序负责读取独立按键和开关按键的状态,根据按键状态进行相应的操作。子程序的流程图如下:
(1)读取按键状态:读取独立按键和开关按键的GPIO引脚状态,判断按键是否被按下。
(2)独立按键处理:如果独立按键被按下,则根据按键按下的次数和时间来调整阈值距离。例如,每次按下独立按键,阈值距离增加或减少一定的值(如5cm),并将新的阈值距离保存到存储器中。
(3)开关按键处理:如果开关按键被按下,则切换报警功能的开启与关闭状态。例如,设置一个标志位来表示报警功能的开启与关闭状态,当开关按键被按下时,切换标志位的值。
- 报警控制子程序
报警控制子程序负责根据实时距离和阈值距离以及报警功能的开启与关闭状态来控制LED指示灯和蜂鸣器的开关状态。子程序的流程图如下:
(1)判断报警功能是否开启:读取报警功能的开启与关闭状态标志位,判断报警功能是否开启。
(2)比较实时距离和阈值距离:如果报警功能开启,则比较实时距离和阈值距离。如果实时距离小于阈值距离,则执行报警操作;否则不执行报警操作。
(3)报警操作:将LED指示灯对应的GPIO引脚设置为高电平,点亮LED指示灯;将蜂鸣器对应的GPIO引脚设置为高电平,驱动蜂鸣器发声。为了产生不同频率的声音,可以通过定时器来控制蜂鸣器的开关状态,实现不同频率的报警声。
(4)关闭报警:如果实时距离大于阈值距离或报警功能关闭,则将LED指示灯和蜂鸣器对应的GPIO引脚设置为低电平,熄灭LED指示灯并停止蜂鸣器发声。
五、系统测试与结果分析
(一)测试环境
本系统测试环境为室内环境,测试距离为4cm至250cm,测试目标为不同材质的物体(如墙壁、木板、金属板等)。测试工具包括STM32开发板、超声波传感器HC-SR04、OLED显示屏、独立按键、开关按键、LED指示灯、蜂鸣器以及万用表、示波器等。
(二)测试方法
- 测距精度测试:将超声波传感器HC-SR04对准不同距离的目标物体,记录OLED显示屏上显示的实时距离,并与实际距离进行比较,计算测距精度。
- 阈值修改测试:通过独立按键修改阈值距离,记录OLED显示屏上显示的阈值距离,验证阈值修改功能是否正常。
- 报警功能测试:将超声波传感器HC-SR04对准不同距离的目标物体,通过开关按键开启报警功能,观察LED指示灯和蜂鸣器的状态,验证报警功能是否正常。
(三)测试结果与分析
- 测距精度测试结果:经过多次测试,本系统测距精度较高,在4cm至250cm的测量范围内,测距误差在±2cm以内,满足设计要求。
- 阈值修改测试结果:通过独立按键可以实时修改阈值距离,OLED显示屏上显示的阈值距离与实际修改的值一致,阈值修改功能正常。
- 报警功能测试结果:当实时距离小于阈值距离且报警功能开启时,LED指示灯点亮,蜂鸣器发声提醒;当实时距离大于阈值距离或报警功能关闭时,LED指示灯熄灭,蜂鸣器停止发声,报警功能正常。
六、结论与展望
(一)结论
本文设计并实现了一种基于STM32的超声波测距报警系统,系统通过STM32微控制器与超声波传感器HC-SR04实现实时测距,测距范围4cm至250cm。OLED显示屏实时显示测距名称、实时距离和阈值距离,独立按键可修改阈值距离。当实时距离小于阈值时,LED指示灯点亮,蜂鸣器发声提醒;实时距离大于阈值时,LED指示灯熄灭,蜂鸣器停止发声。系统还设有开关按键,用于控制报警功能的开启与关闭。经过测试,系统测距精度高、响应速度快、操作简便,满足设计要求。
(二)展望
虽然本系统实现了基本的超声波测距报警功能,但仍有一些可以改进和扩展的地方。例如,可以增加温度补偿功能,提高在不同温度环境下的测距精度;可以增加无线通信模块,实现远程监控和控制;可以优化算法,提高测距的稳定性和准确性等。未来,我们将继续对系统进行改进和扩展,以满足更多应用场景的需求。
七、附录
(一)系统原理图
(此处应附上系统原理图,包括STM32微控制器、超声波传感器HC-SR04、OLED显示屏、独立按键、开关按键、LED指示灯、蜂鸣器以及电源电路、时钟电路、复位电路等的连接关系。)
(二)源程序代码
c复制代码
#include "stm32f10x.h" | |
#include "oled.h" | |
#include "delay.h" | |
#include "hc_sr04.h" | |
// 定义按键和LED、蜂鸣器的GPIO引脚 | |
#define KEY_UP_PIN GPIO_Pin_0 | |
#define KEY_DOWN_PIN GPIO_Pin_1 | |
#define KEY_SWITCH_PIN GPIO_Pin_2 | |
#define LED_PIN GPIO_Pin_13 | |
#define BUZZER_PIN GPIO_Pin_14 | |
// 全局变量 | |
u16 threshold_distance = 50; // 阈值距离,初始值为50cm | |
u8 alarm_enabled = 1; // 报警功能开启标志位,1表示开启,0表示关闭 | |
void GPIO_Config(void); | |
void EXTI_Config(void); | |
void NVIC_Config(void); | |
void Key_Scan(void); | |
void Alarm_Control(u16 real_distance); | |
int main(void) | |
{ | |
u16 real_distance; | |
// 初始化系统时钟 | |
SystemInit(); | |
// 初始化GPIO | |
GPIO_Config(); | |
// 初始化OLED显示屏 | |
OLED_Init(); | |
OLED_ShowString(0, 0, "Ultrasonic Ranging"); | |
OLED_ShowString(0, 2, "Threshold: cm"); | |
OLED_ShowString(0, 4, "Real: cm"); | |
// 初始化超声波传感器 | |
HC_SR04_Init(); | |
// 初始化外部中断和NVIC | |
EXTI_Config(); | |
NVIC_Config(); | |
while (1) | |
{ | |
// 超声波测距 | |
real_distance = HC_SR04_GetDistance(); | |
// OLED显示实时距离和阈值距离 | |
OLED_ShowNum(56, 2, threshold_distance, 3); | |
OLED_ShowNum(56, 4, real_distance, 3); | |
// 报警控制 | |
Alarm_Control(real_distance); | |
// 按键扫描 | |
Key_Scan(); | |
delay_ms(100); // 延时100ms,减少刷屏频率 | |
} | |
} | |
void GPIO_Config(void) | |
{ | |
GPIO_InitTypeDef GPIO_InitStructure; | |
// 初始化按键GPIO引脚为输入模式 | |
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); | |
GPIO_InitStructure.GPIO_Pin = KEY_UP_PIN | KEY_DOWN_PIN | KEY_SWITCH_PIN; | |
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入 | |
GPIO_Init(GPIOA, &GPIO_InitStructure); | |
// 初始化LED和蜂鸣器GPIO引脚为输出模式 | |
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); | |
GPIO_InitStructure.GPIO_Pin = LED_PIN | BUZZER_PIN; | |
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出 | |
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; | |
GPIO_Init(GPIOC, &GPIO_InitStructure); | |
// 关闭LED和蜂鸣器 | |
GPIO_ResetBits(GPIOC, LED_PIN | BUZZER_PIN); | |
} | |
void EXTI_Config(void) | |
{ | |
EXTI_InitTypeDef EXTI_InitStructure; | |
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); | |
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1); | |
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource2); | |
EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1 | EXTI_Line2; | |
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; | |
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; | |
EXTI_InitStructure.EXTI_LineCmd = ENABLE; | |
EXTI_Init(&EXTI_InitStructure); | |
} | |
void NVIC_Config(void) | |
{ | |
NVIC_InitTypeDef NVIC_InitStructure; | |
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; | |
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; | |
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; | |
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; | |
NVIC_Init(&NVIC_InitStructure); | |
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; | |
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; | |
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; | |
NVIC_Init(&NVIC_InitStructure); | |
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; | |
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; | |
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; | |
NVIC_Init(&NVIC_InitStructure); | |
} | |
void EXTI0_IRQHandler(void) | |
{ | |
if (EXTI_GetITStatus(EXTI_Line0) != RESET) | |
{ | |
// 按键1按下,增加阈值距离 | |
if (threshold_distance < 250) | |
{ | |
threshold_distance += 5; | |
} | |
EXTI_ClearITPendingBit(EXTI_Line0); | |
} | |
} | |
void EXTI1_IRQHandler(void) | |
{ | |
if (EXTI_GetITStatus(EXTI_Line1) != RESET) | |
{ | |
// 按键2按下,减少阈值距离 | |
if (threshold_distance > 5) | |
{ | |
threshold_distance -= 5; | |
} | |
EXTI_ClearITPendingBit(EXTI_Line1); | |
} | |
} | |
void EXTI2_IRQHandler(void) | |
{ | |
if (EXTI_GetITStatus(EXTI_Line2) != RESET) | |
{ | |
// 按键3按下,切换报警功能开启与关闭状态 | |
alarm_enabled = !alarm_enabled; | |
EXTI_ClearITPendingBit(EXTI_Line2); | |
} | |
} | |
void Key_Scan(void) | |
{ | |
if (GPIO_ReadInputDataBit(GPIOA, KEY_UP_PIN) == 0) | |
{ | |
delay_ms(10); // 消抖 | |
if (GPIO_ReadInputDataBit(GPIOA, KEY_UP_PIN) == 0) | |
{ | |
if (threshold_distance < 250) | |
{ | |
threshold_distance += 5; | |
} | |
while (GPIO_ReadInputDataBit(GPIOA, KEY_UP_PIN) == 0); // 等待按键释放 | |
} | |
} | |
if (GPIO_ReadInputDataBit(GPIOA, KEY_DOWN_PIN) == 0) | |
{ | |
delay_ms(10); // 消抖 | |
if (GPIO_ReadInputDataBit(GPIOA, KEY_DOWN_PIN) == 0) | |
{ | |
if (threshold_distance > 5) | |
{ | |
threshold_distance -= 5; | |
} | |
while (GPIO_ReadInputDataBit(GPIOA, KEY_DOWN_PIN) == 0); // 等待按键释放 | |
} | |
} | |
if (GPIO_ReadInputDataBit(GPIOA, KEY_SWITCH_PIN) == 0) | |
{ | |
delay_ms(10); // 消抖 | |
if (GPIO_ReadInputDataBit(GPIOA, KEY_SWITCH_PIN) == 0) | |
{ | |
alarm_enabled = !alarm_enabled; | |
while (GPIO_ReadInputDataBit(GPIOA, KEY_SWITCH_PIN) == 0); // 等待按键释放 | |
} | |
} | |
} | |
void Alarm_Control(u16 real_distance) | |
{ | |
if (alarm_enabled) | |
{ | |
if (real_distance < threshold_distance) | |
{ | |
// 实时距离小于阈值距离,点亮LED,驱动蜂鸣器发声 | |
GPIO_SetBits(GPIOC, LED_PIN | BUZZER_PIN); | |
} | |
else | |
{ | |
// 实时距离大于阈值距离,熄灭LED,停止蜂鸣器发声 | |
GPIO_ResetBits(GPIOC, LED_PIN | BUZZER_PIN); | |
} | |
} | |
else | |
{ | |
// 报警功能关闭,熄灭LED,停止蜂鸣器发声 | |
GPIO_ResetBits(GPIOC, LED_PIN | BUZZER_PIN); | |
} | |
} |
(注:以上源程序代码为示例代码,具体实现可能需要根据实际情况进行调整和优化。)
请注意,以上内容为基于STM32的超声波测距报警系统的设计与实现示例,包括系统总体设计、硬件电路设计、软件设计、系统测试与结果分析以及附录中的系统原理图和源程序代码。由于篇幅限制,部分内容可能进行了简化和省略。在实际应用中,可能需要根据具体需求进行进一步的优化和扩展。