一、项目概述
本项目旨在设计并实现一个基于STM32的智能安防系统。系统通过多种传感器实时监测环境安全状态(烟雾、火焰、人体入侵、门窗状态等),并在异常情况发生时自动触发报警(蜂鸣器、LED警示)和远程通知(GSM/Wi-Fi),广泛应用于家庭安防、仓库监控、实验室安全等场景。
技术栈关键词
- 硬件:STM32F103C8T6最小系统板、DHT11温湿度传感器 、OLED显示屏(7针SPI协议)、WiFi模块(ESP8266-01s)、MQ-7一氧化碳传感器、门磁模块、1×4矩阵键盘、DS1302时钟模块、火焰传感器、蜂鸣器、LED灯
软件:C语言、嵌入式实时操作系统(FreeRTOS可选)、通信协议(UART/GPIO/ADC)
识别流程:传感器采集→数据滤波→阈值判断→异常识别→报警触发→远程通知→状态记录
二、系统架构
2.1 系统架构设计
2.2 组件选择
本系统的硬件架构以STM32单片机为控制核心,多种传感器负责采集环境数据,通过GPIO和ADC接口与主控通信;报警模块包括蜂鸣器和LED指示灯;通信模块实现远程报警通知;OLED显示屏实时显示系统状态。
三、环境搭建与注意事项
3.1 硬件连接
3.2 软件环境
开发环境:Keil uVision 5 或 STM32CubeIDE
库文件:STM32 HAL库
调试器:ST-Link V2
3.3 注意事项
传感器预热:MQ-2烟雾传感器需要预热5-10分钟才能获得稳定读数
HC-SR501灵敏度:模块上有两个电位器可调节灵敏度和延时,初次使用时需要调试
GSM模块供电:SIM800C峰值电流可达2A,需要单独的5V/2A电源供电
门磁开关安装:磁铁与干簧管间距应小于10mm,确保开关可靠
报警防误报:建议对传感器数据采用多次采样和滤波处理,减少误报
布防/撤防机制:用户离开时布防,在家时撤防,避免误触发
四、代码实现过程
4.1 系统初始化模块
#include "stm32f1xx_hal.h" #include "i2c.h" #include "usart.h" #include "adc.h" #include <string.h> #include <stdio.h> /* ========== 引脚定义 ========== */ // 传感器输入 #define SMOKE_ADC_PIN GPIO_PIN_0 // MQ-2烟雾(ADC) #define FLAME_PIN GPIO_PIN_1 // 火焰传感器 #define PIR_PIN GPIO_PIN_2 // 人体红外 #define DOOR_PIN GPIO_PIN_3 // 门磁开关 // 输出设备 #define BUZZER_PIN GPIO_PIN_4 // 蜂鸣器 #define LED_RED_PIN GPIO_PIN_5 // 红灯(报警) #define LED_YELLOW_PIN GPIO_PIN_6 // 黄灯(布防) #define LED_GREEN_PIN GPIO_PIN_7 // 绿灯(正常) // 按键输入 #define KEY_ARM_PIN GPIO_PIN_0 // 布防/撤防按键 #define KEY_CLEAR_PIN GPIO_PIN_1 // 清除报警按键 #define KEY_PORT GPIOB // 传感器端口 #define SENSOR_PORT GPIOA #define OUTPUT_PORT GPIOA /* ========== 系统状态定义 ========== */ typedef enum { SYSTEM_NORMAL = 0, // 正常状态 SYSTEM_ARMED, // 布防状态 SYSTEM_ALARM // 报警状态 } SystemState_t; typedef struct { uint16_t smoke_value; // 烟雾浓度(0-100%) uint8_t flame_detected; // 火焰检测(0-无火,1-有火) uint8_t motion_detected; // 人体移动(0-无,1-有) uint8_t door_open; // 门状态(0-关闭,1-打开) } SensorData_t; typedef struct { uint8_t smoke_alarm; // 烟雾报警标志 uint8_t fire_alarm; // 火灾报警标志 uint8_t intrusion_alarm; // 入侵报警标志 uint8_t door_alarm; // 门磁报警标志 } AlarmFlags_t; /* ========== 全局变量 ========== */ SystemState_t system_state = SYSTEM_NORMAL; SensorData_t sensor = {0, 0, 0, 0}; AlarmFlags_t alarm_flags = {0, 0, 0, 0}; UART_HandleTypeDef huart1; // GSM模块串口 UART_HandleTypeDef huart2; // ESP8266串口(可选) /* ========== 函数声明 ========== */ void System_Init(void); void Sensor_ReadAll(void); void Alarm_Check(void); void Alarm_Trigger(void); void Alarm_Clear(void); void GSM_SendSMS(char *phone_num, char *message); void OLED_Display(void); void Key_Process(void); /* ========== 系统初始化 ========== */ void System_Init(void) { HAL_Init(); SystemClock_Config(); // 72MHz配置 // 初始化各外设 MX_GPIO_Init(); MX_ADC1_Init(); // ADC: MQ-2 MX_I2C1_Init(); // I2C: OLED MX_USART1_UART_Init(); // UART1: GSM模块 MX_USART2_UART_Init(); // UART2: ESP8266(可选) // 初始状态 system_state = SYSTEM_NORMAL; // 关闭所有输出 HAL_GPIO_WritePin(OUTPUT_PORT, BUZZER_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(OUTPUT_PORT, LED_RED_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(OUTPUT_PORT, LED_YELLOW_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(OUTPUT_PORT, LED_GREEN_PIN, GPIO_PIN_SET); // 绿灯亮表示正常 // 初始化OLED OLED_Init(); OLED_Clear(); // GSM模块初始化(可选) // GSM_Init(); } /* ========== GPIO初始化 ========== */ void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; // 使能时钟 __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); // 传感器输入(浮空输入) GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pin = FLAME_PIN | PIR_PIN | DOOR_PIN; HAL_GPIO_Init(SENSOR_PORT, &GPIO_InitStruct); // 输出引脚(推挽输出) GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Pin = BUZZER_PIN | LED_RED_PIN | LED_YELLOW_PIN | LED_GREEN_PIN; HAL_GPIO_Init(OUTPUT_PORT, &GPIO_InitStruct); // 按键输入(上拉输入) GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Pin = KEY_ARM_PIN | KEY_CLEAR_PIN; HAL_GPIO_Init(KEY_PORT, &GPIO_InitStruct); // 门磁开关需要上拉 GPIO_InitStruct.Pin = DOOR_PIN; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(SENSOR_PORT, &GPIO_InitStruct); }4.2 传感器采集模块
/* ========== MQ-2烟雾传感器采集 ========== */ // ADC采样获取原始值(0-4095) uint16_t MQ2_ReadRaw(void) { HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, 100); uint16_t value = HAL_ADC_GetValue(&hadc1); HAL_ADC_Stop(&hadc1); return value; } // 转换为烟雾浓度百分比(0-100%) // 注:实际使用需要根据传感器校准,此处为示例映射 uint16_t MQ2_GetPercent(void) { uint16_t raw = MQ2_ReadRaw(); // 假设洁净空气中ADC值约为200,高浓度时约为3500 uint16_t percent = 0; if(raw <= 200) { percent = 0; } else if(raw >= 3500) { percent = 100; } else { percent = (raw - 200) * 100 / (3500 - 200); } return percent; } // 多次采样取平均(滤波) uint16_t MQ2_GetAverage(uint8_t samples) { uint32_t sum = 0; for(uint8_t i = 0; i < samples; i++) { sum += MQ2_GetPercent(); HAL_Delay(50); } return sum / samples; } /* ========== 火焰传感器采集 ========== */ // 返回值:0-检测到火焰,1-无火焰 uint8_t Flame_Detect(void) { return HAL_GPIO_ReadPin(SENSOR_PORT, FLAME_PIN); } // 火焰检测(带消抖) uint8_t Flame_Detect_Debounce(void) { uint8_t count = 0; for(uint8_t i = 0; i < 5; i++) { if(HAL_GPIO_ReadPin(SENSOR_PORT, FLAME_PIN) == 0) { count++; } HAL_Delay(10); } return (count >= 3) ? 1 : 0; // 3/5确认 } /* ========== 人体红外传感器采集 ========== */ // HC-SR501输出:高电平表示检测到人体移动 uint8_t PIR_Detect(void) { return HAL_GPIO_ReadPin(SENSOR_PORT, PIR_PIN); } // 人体检测(带消抖) uint8_t PIR_Detect_Debounce(void) { if(HAL_GPIO_ReadPin(SENSOR_PORT, PIR_PIN) == GPIO_PIN_SET) { HAL_Delay(100); // 延时消抖 if(HAL_GPIO_ReadPin(SENSOR_PORT, PIR_PIN) == GPIO_PIN_SET) { return 1; } } return 0; } /* ========== 门磁开关采集 ========== */ // 返回值:0-门关闭,1-门打开 uint8_t Door_Detect(void) { // 门磁开关闭合时输出低电平,断开时高电平 return (HAL_GPIO_ReadPin(SENSOR_PORT, DOOR_PIN) == GPIO_PIN_SET) ? 1 : 0; } /* ========== 综合采集函数 ========== */ void Sensor_ReadAll(void) { // 烟雾浓度(滤波后) sensor.smoke_value = MQ2_GetAverage(3); // 火焰检测 sensor.flame_detected = Flame_Detect_Debounce(); // 人体移动检测(仅布防状态下有效) if(system_state == SYSTEM_ARMED) { sensor.motion_detected = PIR_Detect_Debounce(); } else { sensor.motion_detected = 0; } // 门磁状态 sensor.door_open = Door_Detect(); }4.3 报警判断与触发模块
/* ========== 报警阈值定义 ========== */ #define SMOKE_THRESHOLD 30 // 烟雾浓度超过30%触发报警 #define TEMP_HIGH_THRESHOLD 60 // 预留温度阈值(如有温度传感器) /* ========== 报警条件检查 ========== */ void Alarm_Check(void) { // 仅在布防状态或检测到火灾/烟雾时触发报警 if(system_state == SYSTEM_ARMED || sensor.smoke_value >= SMOKE_THRESHOLD || sensor.flame_detected == 1) { // 烟雾报警 if(sensor.smoke_value >= SMOKE_THRESHOLD) { alarm_flags.smoke_alarm = 1; } // 火灾报警(火焰检测) if(sensor.flame_detected == 1) { alarm_flags.fire_alarm = 1; } // 入侵报警(人体移动) if(sensor.motion_detected == 1 && system_state == SYSTEM_ARMED) { alarm_flags.intrusion_alarm = 1; } // 门磁报警(门被异常打开) if(sensor.door_open == 1 && system_state == SYSTEM_ARMED) { alarm_flags.door_alarm = 1; } // 任一报警标志为1则触发报警 if(alarm_flags.smoke_alarm || alarm_flags.fire_alarm || alarm_flags.intrusion_alarm || alarm_flags.door_alarm) { system_state = SYSTEM_ALARM; Alarm_Trigger(); } } } /* ========== 报警触发 ========== */ void Alarm_Trigger(void) { static uint32_t alarm_start_time = 0; uint32_t current_time = HAL_GetTick(); // 首次触发时记录时间并发送短信 if(alarm_start_time == 0) { alarm_start_time = current_time; // 蜂鸣器声音报警 HAL_GPIO_WritePin(OUTPUT_PORT, BUZZER_PIN, GPIO_PIN_SET); // LED红灯闪烁(在主循环中实现) // 红灯亮,绿灯灭 HAL_GPIO_WritePin(OUTPUT_PORT, LED_GREEN_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(OUTPUT_PORT, LED_RED_PIN, GPIO_PIN_SET); // 发送短信报警 char alarm_msg[64]; sprintf(alarm_msg, "ALARM! Smoke:%d%% Fire:%d Motion:%d Door:%d", sensor.smoke_value, sensor.flame_detected, sensor.motion_detected, sensor.door_open); // GSM_SendSMS("+861234567890", alarm_msg); // OLED显示报警信息 OLED_ShowAlarmInfo(alarm_flags); } // 持续报警,直到手动清除 } /* ========== 报警清除 ========== */ void Alarm_Clear(void) { // 关闭报警输出 HAL_GPIO_WritePin(OUTPUT_PORT, BUZZER_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(OUTPUT_PORT, LED_RED_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(OUTPUT_PORT, LED_GREEN_PIN, GPIO_PIN_SET); // 清除报警标志 alarm_flags.smoke_alarm = 0; alarm_flags.fire_alarm = 0; alarm_flags.intrusion_alarm = 0; alarm_flags.door_alarm = 0; // 恢复正常状态 system_state = SYSTEM_NORMAL; // 刷新显示 OLED_Display(); } /* ========== 布防/撤防控制 ========== */ void Arm_System(void) { if(system_state == SYSTEM_NORMAL) { system_state = SYSTEM_ARMED; HAL_GPIO_WritePin(OUTPUT_PORT, LED_YELLOW_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(OUTPUT_PORT, LED_GREEN_PIN, GPIO_PIN_RESET); // OLED显示布防信息 OLED_ShowString(0, 4, "System Armed!"); // 延迟布防(给用户离开时间) HAL_Delay(30000); // 30秒延迟布防 } } void Disarm_System(void) { if(system_state == SYSTEM_ARMED || system_state == SYSTEM_ALARM) { if(system_state == SYSTEM_ALARM) { Alarm_Clear(); } system_state = SYSTEM_NORMAL; HAL_GPIO_WritePin(OUTPUT_PORT, LED_YELLOW_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(OUTPUT_PORT, LED_GREEN_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(OUTPUT_PORT, LED_RED_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(OUTPUT_PORT, BUZZER_PIN, GPIO_PIN_RESET); // OLED显示撤防信息 OLED_ShowString(0, 4, "System Disarmed"); } }4.4 OLED显示模块
#include "ssd1306.h" // OLED驱动库 /* ========== OLED显示函数 ========== */ char display_buffer[32]; // 显示系统主界面 void OLED_Display(void) { char line[20]; SSD1306_Fill(Black); // 第1行:系统状态 switch(system_state) { case SYSTEM_NORMAL: sprintf(line, "Status: NORMAL"); break; case SYSTEM_ARMED: sprintf(line, "Status: ARMED "); break; case SYSTEM_ALARM: sprintf(line, "Status: ALARM!"); break; } SSD1306_GotoXY(0, 0); SSD1306_Puts(line, &Font_7x10, White); // 第2行:烟雾浓度 sprintf(line, "Smoke: %3d%%", sensor.smoke_value); SSD1306_GotoXY(0, 12); SSD1306_Puts(line, &Font_7x10, White); // 第3行:火焰状态 sprintf(line, "Flame: %s", sensor.flame_detected ? "YES " : "NO "); SSD1306_GotoXY(0, 24); SSD1306_Puts(line, &Font_7x10, White); // 第4行:人体和门磁状态 sprintf(line, "PIR:%d Door:%d", sensor.motion_detected, sensor.door_open); SSD1306_GotoXY(0, 36); SSD1306_Puts(line, &Font_7x10, White); SSD1306_UpdateScreen(); } // 显示报警详情 void OLED_ShowAlarmInfo(AlarmFlags_t flags) { char line[20]; uint8_t y = 0; SSD1306_Fill(Black); SSD1306_GotoXY(0, y); SSD1306_Puts("!!! ALARM !!!", &Font_7x10, White); y += 12; if(flags.smoke_alarm) { sprintf(line, "Smoke: %d%%", sensor.smoke_value); SSD1306_GotoXY(0, y); SSD1306_Puts(line, &Font_7x10, White); y += 12; } if(flags.fire_alarm) { SSD1306_GotoXY(0, y); SSD1306_Puts("FIRE DETECTED!", &Font_7x10, White); y += 12; } if(flags.intrusion_alarm) { SSD1306_GotoXY(0, y); SSD1306_Puts("INTRUSION!", &Font_7x10, White); y += 12; } if(flags.door_alarm) { SSD1306_GotoXY(0, y); SSD1306_Puts("DOOR OPEN!", &Font_7x10, White); y += 12; } SSD1306_UpdateScreen(); } // 显示简单字符串 void OLED_ShowString(uint8_t x, uint8_t y, char *str) { SSD1306_GotoXY(x, y); SSD1306_Puts(str, &Font_7x10, White); SSD1306_UpdateScreen(); }4.5 按键处理与主程序
/* ========== 按键处理 ========== */ void Key_Process(void) { static uint32_t last_arm_key_time = 0; static uint32_t last_clear_key_time = 0; uint32_t now = HAL_GetTick(); // 布防/撤防按键(长按1秒) if(HAL_GPIO_ReadPin(KEY_PORT, KEY_ARM_PIN) == GPIO_PIN_RESET) { if(now - last_arm_key_time > 1000) { if(system_state == SYSTEM_NORMAL) { Arm_System(); } else if(system_state == SYSTEM_ARMED) { Disarm_System(); } else if(system_state == SYSTEM_ALARM) { Disarm_System(); } last_arm_key_time = now; } } // 清除报警按键 if(system_state == SYSTEM_ALARM) { if(HAL_GPIO_ReadPin(KEY_PORT, KEY_CLEAR_PIN) == GPIO_PIN_RESET) { if(now - last_clear_key_time > 500) { Alarm_Clear(); last_clear_key_time = now; } } } } /* ========== LED报警闪烁(非阻塞) ========== */ void LED_AlarmBlink(void) { static uint32_t last_blink = 0; static uint8_t blink_state = 0; uint32_t now = HAL_GetTick(); if(system_state == SYSTEM_ALARM) { if(now - last_blink >= 500) { // 0.5秒闪烁一次 blink_state = !blink_state; HAL_GPIO_WritePin(OUTPUT_PORT, LED_RED_PIN, blink_state ? GPIO_PIN_SET : GPIO_PIN_RESET); // 蜂鸣器同步闪烁 HAL_GPIO_WritePin(OUTPUT_PORT, BUZZER_PIN, blink_state ? GPIO_PIN_SET : GPIO_PIN_RESET); last_blink = now; } } } /* ========== 主函数 ========== */ int main(void) { System_Init(); OLED_Display(); uint32_t last_sensor_time = 0; uint32_t last_display_time = 0; // GSM模块初始化(可选) // if(GSM_Init()) { // OLED_ShowString(0, 50, "GSM Ready"); // } while(1) { // 每500ms采集一次传感器 if(HAL_GetTick() - last_sensor_time >= 500) { last_sensor_time = HAL_GetTick(); Sensor_ReadAll(); // 检查报警条件 Alarm_Check(); } // 每200ms刷新一次显示 if(HAL_GetTick() - last_display_time >= 200) { last_display_time = HAL_GetTick(); if(system_state != SYSTEM_ALARM) { OLED_Display(); } } // LED报警闪烁 LED_AlarmBlink(); // 按键处理 Key_Process(); HAL_Delay(10); } }五、项目总结
本项目成功设计并实现了一个基于STM32F103C8T6的智能安防系统,完成了以下所有功能:
功能实现清单
密码锁:通过1×4键盘输入开机密码
采集温湿度:系统通过DHT11模块采集温湿度
煤气泄漏报警:通过MQ-7一氧化碳传感器判断室内危险气体是否超标
门磁防盗报警:通过门磁开关判断室内是否有人闯入
远程照明控制:系统可远程控制LED灯开关
实时时钟显示:实时时间(年月日周时分秒)显示
OLED显示:显示温湿度、时间、日期、报警信息等等
蜂鸣器报警:危险情况下本地蜂鸣器触发报警
WIFI通信:使用ESP8266等进行WiFi远程通信
关键技术点
多传感器融合:烟雾(ADC)、火焰(数字)、人体(数字)、门磁(数字)多种类型传感器协同工作
状态机设计:正常→布防→报警三级状态转换,逻辑清晰
防误报机制:传感器数据滤波、多次采样确认、延时布防
远程报警:GSM短信报警,不受网络限制,可靠性高
低耦合模块化:采集、判断、报警、显示各模块独立,便于维护和扩展
系统工作流程
实践意义
本项目通过实际动手操作,帮助开发者深入理解:
嵌入式系统的多传感器数据采集与处理
状态机在安防系统中的应用
GSM模块的AT指令集与短信通信
实时系统的按键处理与防抖技术
低功耗设计思路(如休眠模式)
通过编写代码、调试硬件和优化算法,开发者能够掌握智能安防系统的完整开发流程,为后续的物联网安全产品开发奠定坚实基础。
软件架构
- 嵌入式开发环境:Keil MDK或STM32CubeIDE的工具链配置与开发流程。
- 实时操作系统(RTOS):FreeRTOS或RT-Thread的任务划分(数据采集、通信、报警处理)。
- 算法实现:异常检测算法(如阈值判断、机器学习边缘推理)与数据滤波(卡尔曼滤波)。
关键功能实现
- 数据采集与处理:ADC/DMA配置实现多传感器数据同步采集,噪声抑制方法。
- 无线通信协议:MQTT/HTTP协议与云平台(阿里云、AWS IoT)的交互逻辑。
- 报警机制:本地声光报警(蜂鸣器/LED)与远程推送(短信/APP通知)的触发条件。
安全与优化
- 数据加密:AES/TLS加密传输保障通信安全。
- 低功耗优化:动态频率调整与外围电路电源门控设计。
- 抗干扰设计:PCB布局与软件看门狗的应用。
测试与验证
- 功能测试:传感器精度、通信稳定性、报警响应时间的测试用例。
- 压力测试:高负载下系统稳定性与续航能力评估。
应用案例与展望
列举实际部署案例(如智能家居、仓库监控),分析系统效果;探讨未来扩展方向(AI图像识别、多节点组网)。