基于STC89C52与Proteus的火灾报警系统设计与仿真实践

发布时间:2026/8/5 16:19:56
基于STC89C52与Proteus的火灾报警系统设计与仿真实践 这次我们来看一个基于 STC89C52 单片机的木材仓库火灾报警系统设计。对于从事单片机开发、嵌入式系统课程设计或电子竞赛的同学来说这是一个非常经典且实用的项目。它不涉及复杂的 AI 模型或高算力需求核心在于如何利用低成本、易获取的硬件如 STC89C52、DS18B20、MQ-2 传感器和软件工具如 Keil、Proteus构建一个稳定可靠的本地化监测与报警方案。项目的重点不是概念多复杂而是能不能在你手头的开发板上跑起来以及如何通过仿真验证整个系统的逻辑。本文将带你从零开始理清系统的核心功能、硬件选型、电路设计、代码编写并最终在 Proteus 中完成仿真测试。如果你关心如何将理论知识转化为一个可演示、可调试的完整项目这篇文章可以直接收藏。我们将重点关注系统的模块化设计思路、传感器数据采集的稳定性、报警逻辑的可靠性以及 Proteus 仿真与实际硬件调试的差异。通过本文你将掌握一个完整的“传感器单片机执行器”系统开发流程并能够将其思路迁移到其他安防或环境监测场景中。1. 核心能力速览能力项说明核心控制器STC89C52兼容 AT89C528 位单片机温度监测DS18B20 数字温度传感器单总线通信精度 ±0.5°C烟雾监测MQ-2 半导体烟雾/可燃气体传感器模拟量输出显示模块LCD1602 液晶显示屏用于实时显示温度和烟雾浓度声光报警LED 指示灯与蜂鸣器用于超限报警开发环境Keil uVision5代码编写与编译仿真工具Proteus 8 Professional电路设计与系统仿真程序烧录使用 STC-ISP 工具通过串口下载适合场景单片机课程设计、毕业设计、电子竞赛、物联网安防系统入门实践2. 适用场景与使用边界这个基于 STC89C52 的火灾报警系统设计主要适用于以下几类人群和场景单片机初学者与学习者作为从理论到实践的桥梁项目涵盖了 GPIO 控制、ADC 采集、单总线通信、中断、液晶显示等单片机核心知识点是巩固 51 单片机知识的绝佳练手项目。课程设计与毕业设计项目结构完整包含硬件设计、软件编程和仿真验证文档和代码易于扩展例如增加 GSM 短信报警、Wi-Fi 上传数据等能够满足大多数本科阶段电子类课程设计或毕业设计的要求。电子竞赛与创新实践可作为智能安防、环境监测类赛题的基础框架快速搭建原型系统。小型场所本地化监控理论上可用于小型木材仓库、档案室、实验室等对防火有基本要求的封闭空间进行本地化的温度与烟雾浓度监测。使用边界与重要提醒教学与原型验证用途本文所述系统主要在 Proteus 仿真环境下验证逻辑其传感器模型如 MQ-2行为是简化的。切勿直接将仿真系统用于真实火灾报警场景。真实环境复杂涉及传感器校准、防误报算法、设备防护等级、供电可靠性、国家消防认证等一系列工程和安全问题。性能限制STC89C52 处理能力和内存有限不适合运行复杂的滤波算法或连接过多外设。DS18B20 和 MQ-2 的响应速度、精度和稳定性在极端环境下可能不足。安全合规性任何用于真实人身财产安全防护的系统都必须遵循所在国家或地区的相关安全标准和法规并采用经过认证的专业设备。本设计仅为学习提供思路参考。3. 环境准备与前置条件在开始动手之前请确保你的电脑上已经安装好必要的软件环境。这是项目能否顺利推进的第一步。软件环境清单Keil uVision5 (C51 版本)用于编写、编译和调试单片机的 C 语言源代码。确保安装时选择了 C51 工具链而不是 ARM 的。Proteus 8 Professional (或更高版本)用于绘制电路原理图并进行交互式仿真。需要包含 8051 系列单片机、LCD1602、DS18B20、MQ-2 等元件的仿真模型库。STC-ISP 烧录软件如果你有实物开发板需要此软件将通过 Keil 生成的.hex文件烧录到 STC89C52 单片机中。可以从 STC 官网下载最新版。串口调试助手可选但推荐如SSCOM、XCOM用于在实物调试时查看单片机通过串口打印的数据便于排查问题。硬件知识准备基础 C 语言编程理解变量、函数、循环、条件判断。51 单片机基础了解 GPIO、定时器/计数器、中断、串口通信的基本概念。电路基础能看懂简单的原理图理解上拉电阻、电源、接地的含义。传感器初步了解知道 DS18B20 是数字温度传感器MQ-2 是模拟量输出的烟雾传感器。检查你的 Proteus 元件库打开 Proteus在元件选择框中搜索以下关键词确认是否存在对应的仿真模型AT89C52(可替代 STC89C52)LM016L(即 LCD1602)DS18B20MQ-2或MQS-2(Proteus 中可能用此模型)BUZZER(蜂鸣器)LEDPOT-HG(滑动变阻器用于模拟 MQ-2 输出变化)RES(电阻)CAP(电容)CRYSTAL(晶振)如果缺少某个模型需要去网上寻找并添加到你的 Proteus 库中。4. 系统设计与原理图绘制在编写代码之前我们需要在 Proteus 中设计出系统的电路原理图。清晰的电路图是后续仿真和实物连接的基础。4.1 核心模块连接设计1. 单片机最小系统STC89C52 的P0口需要接上拉电阻例如 10kΩ 排阻才能驱动 LCD1602。连接 12MHz 晶振到XTAL1和XTAL2并配上两个 30pF 左右的电容到地。RST引脚接上电复位电路10uF 电容 10kΩ 电阻。EA引脚接高电平VCC使用内部程序存储器。2. 显示模块 (LCD1602)RS,RW,E控制引脚分别接单片机P2.0,P2.1,P2.2。D0-D7数据引脚接单片机P0.0-P0.7。VSS接地VDD接5VVEE接一个滑动变阻器中间引脚用于调节对比度。3. 温度传感器 (DS18B20)DQ数据引脚接单片机P3.7并接一个 4.7kΩ 的上拉电阻到VCC。VDD接5VGND接地。注意DS18B20 是单总线设备对时序要求严格仿真中模型工作良好实物连接时导线不宜过长。4. 烟雾传感器 (MQ-2)MQ-2 有 4 个引脚VCC,GND,DO,AO。我们使用模拟输出AO。AO引脚接单片机P1.0假设使用 ADC0808 芯片进行 AD 转换或者更简单的在仿真中我们可以用一个滑动变阻器 (POT-HG) 来代替 MQ-2 的模拟输出将其滑动端接至P1.0通过手动调节阻值来模拟烟雾浓度变化。单片机通过查询P1.0口电平需配置为输入或经过 ADC 转换后的数字值来判断。为了简化仿真本文采用将滑动变阻器输出直接接P1.0并在程序中将P1.0配置为高阻输入通过读取P1端口值来获取模拟量0-255。实物中必须使用 ADC 芯片如 ADC0808/PCF8591或单片机内部 ADC如果选用带 ADC 的单片机如 STC12C5A60S2来处理 MQ-2 的模拟信号。5. 报警模块报警 LED 接P2.6串联一个 220Ω 限流电阻到地。蜂鸣器有源接P2.7。有源蜂鸣器高电平驱动无源蜂鸣器需要 PWM 驱动。4.2 在 Proteus 中绘制原理图打开 Proteus ISIS新建一个设计。从元件库中依次添加所有需要的元件。按照上述设计连接电路。一个参考的连接方式如下LCD1602:RS-P2.0,RW-P2.1,E-P2.2,D0-D7-P0.0-P0.7DS18B20:DQ-P3.7MQ-2模拟输入:POT-HG滑动端 -P1.0LED:P2.6BUZZER:P2.7为P0口添加一个RESPACK-8上拉排阻。放置电源 (POWER) 和地 (GROUND) 符号并正确连接。最终绘制完成的原理图应该是一个闭合的、可工作的电路。务必检查VCC和GND是否连接到所有需要供电的元件。5. 软件编程与代码解析电路是躯干程序是灵魂。下面我们分模块编写驱动代码和主控逻辑。5.1 工程创建与头文件打开 Keil uVision5新建一个Project选择STC MCU Database中的STC89C52RC。新建main.c、lcd1602.c、lcd1602.h、ds18b20.c、ds18b20.h、delay.c、delay.h等文件并添加到工程中。在main.c中包含必要的头文件。// main.c #include reg52.h // 51单片机头文件 #include “lcd1602.h” #include “ds18b20.h” #include “delay.h” // 宏定义引脚 sbit LED_Alarm P2^6; // 报警LED sbit BUZZER P2^7; // 蜂鸣器 sbit MQ2_IN P1^0; // MQ-2模拟输入简化处理 // 报警阈值 #define TEMP_THRESHOLD 50 // 温度阈值 50°C #define SMOKE_THRESHOLD 150 // 烟雾浓度阈值 (0-255模拟量范围) // 全局变量 unsigned char Temp_Value 0; // 温度值 unsigned char Smoke_Value 0; // 烟雾浓度值 bit Alarm_Flag 0; // 报警标志位5.2 LCD1602 驱动模块LCD1602 的驱动是标准代码需要实现初始化、写命令、写数据、清屏、显示字符串等功能。// lcd1602.h #ifndef __LCD1602_H__ #define __LCD1602_H__ void LCD_Init(void); void LCD_WriteCmd(unsigned char cmd); void LCD_WriteData(unsigned char dat); void LCD_Clear(void); void LCD_SetCursor(unsigned char line, unsigned char column); void LCD_ShowStr(unsigned char line, unsigned char column, unsigned char *str); #endif// lcd1602.c #include “lcd1602.h” #include “delay.h” // 引脚定义根据你的原理图连接修改 sbit LCD_RS P2^0; sbit LCD_RW P2^1; sbit LCD_E P2^2; #define LCD_DataPort P0 // 写命令函数 void LCD_WriteCmd(unsigned char cmd) { LCD_RS 0; LCD_RW 0; LCD_DataPort cmd; LCD_E 1; DelayMs(2); LCD_E 0; DelayMs(2); } // ... 其他函数实现写数据、初始化、清屏、设置光标、显示字符串 // 具体实现代码较长此处省略可参考标准51单片机LCD1602驱动库。5.3 DS18B20 温度读取模块DS18B20 的驱动关键在于精确的延时函数以满足单总线时序。// ds18b20.h #ifndef __DS18B20_H__ #define __DS18B20_H__ unsigned int DS18B20_ReadTemp(void); // 读取温度值 #endif// ds18b20.c #include “ds18b20.h” #include “delay.h” sbit DQ P3^7; // 数据线引脚 // DS18B20初始化存在检测 bit DS18B20_Init(void) { bit flag; DQ 1; DelayUs(2); DQ 0; DelayUs(500); // 拉低480us以上 DQ 1; DelayUs(60); // 释放总线等待15-60us flag DQ; // 读取存在脉冲 DelayUs(240); return flag; // 0:存在1:不存在 } // 从DS18B20读一个字节 unsigned char DS18B20_ReadByte(void) { unsigned char i, dat 0; for(i0; i8; i) { DQ 0; _nop_(); _nop_(); // 拉低开始读时序 DQ 1; DelayUs(2); // 释放总线 dat 1; if(DQ) dat | 0x80; DelayUs(60); // 等待读时序结束 } return dat; } // 向DS18B20写一个字节 void DS18B20_WriteByte(unsigned char dat) { unsigned char i; for(i0; i8; i) { DQ 0; _nop_(); _nop_(); // 拉低开始写时序 DQ dat 0x01; // 发送最低位 DelayUs(60); // 保持60us DQ 1; dat 1; // 释放总线准备下一位 DelayUs(2); } } // 读取温度值 unsigned int DS18B20_ReadTemp(void) { unsigned int temp 0; unsigned char LSB, MSB; if(DS18B20_Init() 0) { // 检测到器件 DS18B20_WriteByte(0xCC); // 跳过ROM DS18B20_WriteByte(0x44); // 启动温度转换 DelayMs(750); // 等待转换完成12位精度需750ms DS18B20_Init(); DS18B20_WriteByte(0xCC); // 跳过ROM DS18B20_WriteByte(0xBE); // 读暂存器 LSB DS18B20_ReadByte(); // 低字节 MSB DS18B20_ReadByte(); // 高字节 temp MSB; temp 8; temp | LSB; } return temp; // 返回16位原始数据 }5.4 主程序逻辑主程序负责协调各个模块循环读取传感器数据判断是否超限并控制显示和报警。// main.c 主函数部分 void main() { unsigned int temp_raw; unsigned char temp_display, smoke_display; unsigned char disp_buf[16]; LCD_Init(); // 初始化液晶 LCD_Clear(); LCD_ShowStr(0, 0, “Temp: C“); LCD_ShowStr(1, 0, “Smoke: “); while(1) { // 1. 读取温度 temp_raw DS18B20_ReadTemp(); // DS18B20返回的是16位有符号整数低4位是小数部分 // 简单处理取整数部分 (temp_raw 4) Temp_Value (unsigned char)(temp_raw 4); // 2. 读取烟雾浓度简化读取P1.0口模拟电压对应的数字值 // 注意P1口需先写0xFF使其为高阻输入状态 P1 0xFF; Smoke_Value P1 0x01; // 仅读取P1.0实际可扩展为8位ADC值 // 在仿真中我们用滑动变阻器模拟这里假设Smoke_Value是0-255的值 // 为了演示我们用一个变量模拟变化实际应从ADC读取 static unsigned char sim_smoke 100; sim_smoke; if(sim_smoke 200) sim_smoke 100; Smoke_Value sim_smoke; // 3. 判断报警条件 if((Temp_Value TEMP_THRESHOLD) || (Smoke_Value SMOKE_THRESHOLD)) { Alarm_Flag 1; LED_Alarm 0; // 低电平点亮LED BUZZER 0; // 低电平驱动有源蜂鸣器 } else { Alarm_Flag 0; LED_Alarm 1; BUZZER 1; } // 4. 更新LCD显示 // 显示温度 sprintf(disp_buf, “%3d”, Temp_Value); // 需要包含 stdio.h LCD_SetCursor(0, 6); LCD_ShowStr(0, 6, disp_buf); // 显示烟雾浓度 sprintf(disp_buf, “%4d”, Smoke_Value); LCD_SetCursor(1, 7); LCD_ShowStr(1, 7, disp_buf); // 显示报警状态 LCD_SetCursor(1, 12); if(Alarm_Flag) { LCD_ShowStr(1, 12, “ALARM“); } else { LCD_ShowStr(1, 12, “SAFE “); } DelayMs(500); // 延时500ms控制刷新频率 } }6. Proteus 仿真与调试代码编写完成后下一步就是在 Proteus 中加载程序并进行仿真这是验证逻辑是否正确的最关键一步。编译生成 HEX 文件在 Keil 中确保Options for Target-Output中勾选了Create HEX File。点击Rebuild编译工程。如果没有错误会在工程目录下生成.hex文件。在 Proteus 中加载程序回到 Proteus 原理图界面。双击原理图中的AT89C52或STC89C52单片机元件会弹出属性编辑框。在Program File一栏点击文件夹图标选择刚才 Keil 生成的.hex文件。将Clock Frequency设置为12MHz与你的晶振频率一致。点击OK。运行仿真点击 Proteus 界面左下角的Play(运行) 按钮。观察 LCD1602 显示屏是否点亮并显示初始信息 “Temp: C” 和 “Smoke:”。DS18B20 元件上可能会显示一个默认温度如 85°C你可以双击 DS18B20 元件在属性中修改Current Temperature值来模拟温度变化。找到代表 MQ-2 模拟输入的滑动变阻器 (POT-HG)。在仿真运行时用鼠标点击并拖动滑动变阻器上的箭头改变其阻值从而改变输入到P1.0口的电压模拟烟雾浓度变化。功能验证正常状态当 DS18B20 温度低于 50°C且滑动变阻器输出值对应Smoke_Value低于 150 时LCD 应显示 “SAFE”LED 熄灭蜂鸣器静音。高温报警双击 DS18B20将温度设置为 55°C。观察 LCD 温度显示是否更新同时报警状态是否变为 “ALARM”LED 是否点亮蜂鸣器是否响起。烟雾报警将滑动变阻器调整到高位使Smoke_Value超过 150。观察 LCD 烟雾值显示是否变化并触发报警。报警解除将温度和烟雾浓度都调回阈值以下观察报警是否自动解除显示恢复 “SAFE”。仿真调试技巧如果 LCD 不显示检查P0口上拉电阻是否连接VEE对比度调节是否合适以及代码中 LCD 初始化时序是否正确。如果 DS18B20 温度读取始终为 0 或错误检查单总线引脚连接、上拉电阻以及ds18b20.c中的延时函数精度。Proteus 仿真对时序要求比实物宽松但仍需基本正确。可以利用 Proteus 的Virtual Terminal(虚拟终端) 连接到单片机的串口在代码中添加printf语句打印调试信息这是非常有效的排查手段。7. 实物制作与调试要点进阶如果你打算将系统制作成实物仿真成功只是第一步。实物调试会遇到更多问题。元器件采购与焊接STC89C52 单片机或开发板、LCD1602、DS18B20、MQ-2、有源蜂鸣器、LED、电阻、电容、晶振、排针、杜邦线、万用板或洞洞板。注意MQ-2 传感器需要预热几分钟才能稳定输出。实物连接时AO引脚必须连接到 ADC 转换芯片或带 ADC 的单片机引脚。程序烧录使用 USB-TTL 串口模块如 CH340、CP2102连接电脑和单片机的P3.0(RXD) 和P3.1(TXD)。打开 STC-ISP 软件选择正确的单片机型号、串口号。打开编译好的.hex文件点击“下载/编程”按钮然后给单片机上电冷启动等待烧录完成。常见实物问题排查LCD1602 显示乱码或黑块首先调节VEE对比度电压。检查RS,RW,E控制线连接是否与代码定义一致。确保P0口上拉电阻有效通常用 10kΩ 排阻。DS18B20 读取失败检查DQ线是否接了 4.7kΩ 上拉电阻。检查代码中的延时函数实物对微秒级延时精度要求更高建议使用定时器产生精确延时或使用经过验证的延时函数库。尝试降低 DS18B20 的通信速率使用更宽松的延时。MQ-2 数值不变或不准确认AO引脚连接到了 ADC 输入。检查 ADC 参考电压是否稳定。MQ-2 需要通电预热。在代码中实现软件滤波如多次采样取平均以消除抖动。蜂鸣器不响确认是有源蜂鸣器给高/低电平就响还是无源蜂鸣器需要 PWM 驱动。检查驱动三极管或集成电路是否工作正常。系统不稳定检查电源是否充足5V/1A 以上所有GND是否共地良好。在单片机VCC和GND之间靠近引脚处加一个 10uF 电解电容和一个 0.1uF 瓷片电容进行电源滤波。8. 功能扩展与优化建议基础系统完成后你可以考虑以下方向进行扩展这会让你的项目更具挑战性和实用性增加实时时钟 (RTC)添加 DS1302 或 PCF8563 芯片在 LCD 上显示当前时间并记录报警发生的时间点。增加数据存储使用 AT24C02 等 EEPROM 芯片存储历史报警记录或温度阈值。增加无线通信添加 ESP8266 Wi-Fi 模块或 HC-05 蓝牙模块将报警信息和传感器数据发送到手机 APP 或电脑上位机实现远程监控。改进烟雾检测使用真正的 ADC 芯片如 ADC0808读取 MQ-2 的模拟量并编写更精确的浓度-电压换算程序。增加手动布防/撤防添加按键允许管理员在安全检查后手动关闭报警系统。多级报警区分预警闪烁黄灯和火警红灯常亮蜂鸣器例如温度超过 45°C 预警超过 60°C 或烟雾浓度超高时火警。上位机软件使用 C#、Python 或 LabVIEW 编写一个简单的上位机通过串口接收数据绘制温度/烟雾浓度曲线图。9. 项目总结与资源获取这个“木材仓库火灾报警系统”项目完整地走通了从需求分析、硬件选型、电路设计、软件编程到仿真验证的嵌入式系统开发全流程。它的价值在于提供了一个清晰、可复现的模板你可以基于此模板替换不同的传感器如湿度传感器 DHT11、火焰传感器和执行器如继电器控制排风扇、电磁阀控制喷水快速构建其他类型的监测控制系统。最值得尝试的点模块化编程将 LCD、DS18B20 驱动写成独立的.c/.h文件主程序逻辑清晰便于调试和移植。Proteus 仿真先行在焊接实物前用仿真验证了核心逻辑节省了大量时间和物料成本。报警逻辑直观通过简单的阈值比较实现报警易于理解和修改。最先应该验证的功能LCD1602 能否正常显示静态字符。DS18B20 能否在 Proteus 中读取并显示变化的温度值。通过滑动变阻器模拟的烟雾信号能否触发报警。最容易踩的坑时序问题DS18B20 和 LCD1602 的驱动对延时很敏感务必使用经过测试的延时函数。端口配置读 DS18B20 或 MQ-2 模拟口时要先将端口设置为高阻输入写1。电源与接地实物中电源不稳定或地线虚接是导致各种诡异问题的首要原因。下一步 你可以尝试将仿真成功的代码烧录到真正的 STC89C52 开发板上连接实物传感器进行测试。在这个过程中你会深刻体会到仿真与实物的差异并学会使用万用表、逻辑分析仪等工具进行调试这才是嵌入式工程师真正的成长之路。相关的完整源码、Proteus 仿真文件、元件清单通常可以在一些开源硬件平台或电子技术论坛找到搜索“STC89C52 火灾报警 Proteus 仿真”即可。建议在理解本文思路的基础上自己动手从头构建一遍收获会更大。