一、项目概述
本项目旨在设计并实现一个基于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 系统初始化模块
cs
#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 传感器采集模块
cs
/* ========== 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 报警判断与触发模块
cs
/* ========== 报警阈值定义 ========== */
#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显示模块
cs
#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 按键处理与主程序
cs
/* ========== 按键处理 ========== */
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图像识别、多节点组网)。