
简介一套基于51单片机的Proteus火灾灭火系统设计资料包面向单片机学习者和嵌入式开发人员。资源以灭火控制系统为核心能够采集烟雾浓度、温度值与火光强度通过串口上传到上位机超过阈值时自动报警并启动灭火检测到风机故障则停机保护。项目覆盖完整的开发链路Proteus仿真图用于电路验证C语言源代码与HEX文件可直接编译烧录AD原理图辅助硬件调试流程图帮助理解程序逻辑另有元件清单和功能说明便于复现。包内共49个文件包含png仿真截图、c/h源码、lst/obj编译中间文件、uvproj工程文件、DSN仿真文件、SchDoc原理图及PDF预览、JPG流程图等类型整体压缩包仅1.59MB结构紧凑、阅读方便。目前已有61人学习是一套适合入门火灾报警系统、单片机综合实训及Proteus仿真练习的参考资料。1. 从三个传感器信号到灭火决策一个51单片机的完整火灾响应闭环火灾报警和灭火控制听起来像是大型消防系统的专职但用一颗51单片机配合Proteus仿真完全可以在桌面级别把「检测—判警—灭火—上报—故障保护」这一整条链路跑通。这套资料的核心并不在于某个传感器有多高级而在于把烟雾浓度、温度、火光强度三种异构信号同时接入一颗AT89C52并用中断、定时器和串口把决策逻辑组织成一个可观察、可调参的状态机。它适合正在做课程设计、准备电子设计竞赛或者想快速验证火灾联动逻辑而暂时不想焊板的工程师。实际拆解这套工程包之后会发现它比常见的温控类设计多了一层值得借鉴的地方串口上报的同时区分了“warning”和“close”两种系统状态这意味着单片机不仅要感知环境还要具备自我诊断能力而这种双状态上报机制恰好是工业现场设备监控的雏形。下面从传感器信号链、仿真搭建、串口协议和故障调试四个层面逐一展开。2. 传感器信号链DS18B20、ADC0832与火光检测的实现细节2.1 为什么把温度、烟雾、火光三种信号设计成「数字模拟模拟」的组合在开始看代码之前先厘清一个选型问题为什么温度用DS18B20烟雾和火光却走ADC0832DS18B20是单总线数字传感器直接输出12位温度值精度和抗干扰性都比模拟温度传感器好且Proteus里自带仿真模型不需要额外搭调理电路。而烟雾传感器常见型号是MQ-2输出的是模拟电压火光检测用光敏电阻或红外接收管配合分压电路同样输出模拟量。所以板上放一颗ADC0832是性价比很高的选择——它是8位逐次逼近型ADC双通道输入恰好把烟雾和火光两路模拟信号一并解决。这样的信号组合有一个工程上的隐含约束51单片机的P1口既要接ADC0832的数据线又要接DS18B20的DQ线还要驱动LCD1602的数据口所以端口分配必须仔细对照原理图否则一处引脚冲突会导致整片系统在仿真里“神秘失灵”。2.2 DS18B20的温度读取单总线时序与CRC校验的取舍代码包里Ds18b20.c和Ds18b20.h实现了完整的单总线协议。核心代码是温度读取函数我在这里把关键部分抽出来分析unsigned int Ds18b20ReadTemp(void) { unsigned char low, high; unsigned int temp; Ds18b20Reset(); // 复位脉冲拉低DQ至少480us Ds18b20WriteByte(0xCC); // 跳过ROM指令因为总线上只有一片 Ds18b20WriteByte(0x44); // 启动温度转换 Ds18b20Reset(); Ds18b20WriteByte(0xCC); // 再次跳过ROM Ds18b20WriteByte(0xBE); // 读取暂存器含温度高字节和低字节 low Ds18b20ReadByte(); high Ds18b20ReadByte(); temp (high 8) | low; // 12位温度数据拼装 if (temp 0x8000) // 负数处理火灾场景中一般不会出现 { temp ~temp 1; } return temp; // 返回值乘以0.0625即可得到实际温度 }这段逻辑的要点在复位和时序窗口每次读写前必须先复位总线写0xCC跳过ROM、写0x44启动转换、再复位、写0xBE读暂存器这是DS18B20最标准的四步流程。返回值是12位原始数据需要乘以0.0625转换成摄氏度。代码里没有做CRC校验这在单点测温场景下问题不大因为Proteus仿真中总线噪声几乎为零但如果你之后移植到物理样机上建议把Ds18b20ReadByte里的时隙拉长到60us以上并且补上CRC8校验否则工业环境里的长线缆耦合噪声会让温度偶尔跳变20度以上。2.3 ADC0832双通道采样烟雾与火光如何共用一颗8位ADCADC0832.c里封装了两个读取函数分别对应CH0和CH1通道。ADC0832的控制时序比DS18B20简单得多但有一个容易出错的地方——通道选择位是在启动位之后逐位发送的顺序不能颠倒unsigned char Adc0832Read(unsigned char channel) { unsigned char i, dat 0; // channel 0 选CH0channel 1 选CH1 ADCS 0; // 片选拉低开始一次转换 ADCLK 0; ADDI 1; // 启动位 ADCLK 1; ADCLK 0; ADDI 1; // 多路选择SGL/DIF1 单端输入 ADCLK 1; ADCLK 0; ADDI channel; // ODD/SIGN位决定选CH0还是CH1 ADCLK 1; ADCLK 0; ADDI 1; // 让DO引脚释放总线准备接收数据 for (i 0; i 8; i) { ADCLK 1; ADCLK 0; dat 1; if (ADDO) dat | 0x01; // 从高到低逐位读取转换结果 } ADCS 1; // 片选拉高结束转换 return dat; }逻辑上需要注意三点第一通道选择必须在启动位之后、数据读取之前完成第二8位数据的读取顺序是从高位到低位如果你改成了MSB0模式那移位和赋值的顺序要反过来第三每次转换完成后片选拉高下一次转换前必须要有至少一个时钟周期的低电平间隔。这套控制时序在Proteus里可以稳定跑到12MHz晶振但如果你把单片机换成了STC89C52要注意ADC0832的时钟频率不要超过500kHz否则数据会错位。烟雾浓度和火光强度的阈值判断在主函数main.c中完成核心逻辑是对两个ADC通道反复采样并做滑动平均smoke_val 0; flame_val 0; for (i 0; i 8; i) { smoke_val Adc0832Read(0); flame_val Adc0832Read(1); } smoke_val 3; // 8次累加后右移3位相当于除以8 flame_val 3;为什么要滑动平均因为MQ-2这类半导体气敏传感器在仿真里虽然输出稳定但物理环境里会叠加一个低频噪声分量单次采样的跳变可能频繁触发误报。8次采样取均值可以把采样率提高到500Hz左右同时抑制大部分噪声尖峰。阈值判断的典型设置在main.c顶部的宏定义里#define SMOKE_THRESHOLD 120 // 烟雾电压阈值对应ADC值 #define TEMP_THRESHOLD 500 // 温度阈值对应DS18B20原始值的50.0℃ #define FLAME_THRESHOLD 100 // 火光强度阈值对应ADC值这三个阈值是整套系统最容易按实际场景调整的参数后面在串口调试部分还会重点讲解它们与报警响应的联动关系。3. Proteus仿真模型构建从元件布局到信号注入的完整流程3.1 仿真文件结构与LCD1602、ADC0832的接线要点打开工程包里的仿真.DSN可以看到主控电路的核心布局。整体结构是AT89C52最小系统板P0口经排阻上拉后接LCD1602数据口P2.0到P2.2分别控制LCD的RS、RW、E引脚ADC0832挂在P1口的低位DS18B20接在P1.6蜂鸣器、LED指示灯和水泵电机模型通过P3口控制。这套接线的思路很明确P0口内部没有上拉电阻必须外接10K排阻才能驱动LCDP1口作为传感器数据总线既要读ADC又要读DS18B20所以选择查询方式而不是中断方式避免竞争。元件清单在元件清单.xlsx里有详细列表我整理了一下关键器件如下元件型号/参数Proteus关键字数量用途主控AT89C52AT89C521核心控制器温度传感器DS18B20DS18B201环境温度采集双通道ADCADC0832ADC08321烟雾/火光信号采样烟雾传感器模型MQ-2用电位器替代POT-HG1模拟烟雾电压输出液晶显示LCD1602LM016L1本地数据显示蜂鸣器5V有源蜂鸣器BUZZER1声光报警水泵/灭火执行器直流电机模型MOTOR-DC1灭火执行机构晶振12MHzCRYSTAL1时钟源特别提醒Proteus的内置库里没有专门的MQ-2模型常见的做法是用一个电位器分压网络来模拟烟雾浓度变化把电位器滑臂输出电压接到ADC0832的CH0通道。这个替换方案不改变系统流程只是把传感器换成了可手动调节的电压源调试时反而更直观。3.2 最小系统与ADC0832的仿真参数校正AT89C52最小系统在Proteus里最容易被忽略的是EA引脚。EA必须接VCC否则单片机会从外部ROM取指令程序根本无法运行。另外复位电路用10uF电解电容和10K电阻构成上电复位复位时间常数是100ms足够稳定。晶振电容不建议去掉否则仿真时钟波形会带上振铃干扰DS18B20的时序。ADC0832的仿真参数需要特别注意参考电压。Proteus里的ADC0832属性面板有一个Reference Voltage参数默认是5V。如果你保持默认值那么ADC采集到的电压范围是0到5V8位分辨率下每1LSB对应19.5mV。但如果你在原理图里把VREF脚接到了别的电位就必须同步修改这个属性否则读回来的ADC值和实际电压不成比例。调试时我习惯在烟雾输入端挂一个电压探针把电位器旋到滑臂输出电压2.5V此时ADC0832读回的理论值应该是1282.5V/5V×256。如果读回值偏差超过3个LSB基本可以断定是时钟时序或片选控制有问题。另一个高频踩坑点是ADC0832的CS引脚它必须由单片机主动拉低并保持到整个转换周期结束不能接死地否则每次读回来的数据都可能是上一通道的残留值。3.3 仿真与AD原理图的同步校验方法工程包里的AD原理图文件Sheet1.SchDoc和Proteus仿真图在元件连接上应当完全一致。在实际维护这类资料时我最常用的一种校验方法是网络标签比对法在AD里导出原理图的网络表Netlist再对照Proteus仿真图的连线逐一核对这些关键网络ALE、EA、RS、RW、E、DQ、ADCLK、ADCS、ADDO、ADDI。这里可能存在的一个隐患是因为源工程是用AD画的原理图而仿真图是Proteus画的两边元件引脚编号可能不一致。比如LCD1602在AD里的引脚顺序和Proteus的LM016L模型不一定相同最容易出现差异的是背光正极和负极引脚。如果按AD原理图去连Proteus模型背光引脚接反了LCD不会亮这时需要对照两边元件的引脚定义手动修正仿真模型里编号不一致的电源和地脚。4. 串口协议解析warning与close双状态上报的软件实现4.1 串口初始化的寄存器配置波特率与中断处理的配合这套系统通过串口将测量值和系统状态实时上传到上位机代码里main.c的UartInit函数完成了串口初始化。典型的配置是9600波特率、8位数据位、1位停止位、无校验void UartInit(void) { SCON 0x50; // 0101 0000串口方式1REN1使能接收 TMOD 0x20; // T1工作在方式2自动重装载8位定时器 TH1 0xFD; // 波特率重装值12MHz晶振下对应9600 TL1 0xFD; TR1 1; // 启动定时器1 ES 1; // 使能串口中断 EA 1; // 开启总中断 }重点解释一下TH1 0xFD这个值的由来。51单片机串口波特率计算公式是波特率 定时器1溢出率 / 32而定时器1工作在方式2时的溢出率 系统时钟 / (12 × (256 - TH1))。代入12MHz晶振和9600波特率可以反推出TH1 256 - 12000000 / (12 × 32 × 9600) ≈ 253 0xFD。如果你把晶振换成了11.0592MHz那么TH1应该改成0xFD因为11.0592MHz本来就是为串口波特率设计的直接套用0xFD也行但如果换成了24MHz晶振波特率会翻倍失真串口助手收到的数据就是乱码。4.2 串口发送的数据帧格式温度、烟雾、火光、状态四段式数据上传的逻辑在main.c里的SendStatus函数中它把温度、烟雾值和火光值通过串口发送到上位机void SendStatus(unsigned int temp, unsigned char smoke, unsigned char flame) { unsigned char buffer[20]; // 将三个测量值格式化输出格式示例TEMP25.3 SMOKE85 FLAME60 sprintf(buffer, TEMP%d.%d SMOKE%d FLAME%d\r\n, temp / 10, temp % 10, smoke, flame); UartSendString(buffer); }这个数据帧设计成明文ASCII格式好处是调试时直接用串口助手就能读懂不需要额外解码。但代价是每个状态包有20字节左右9600波特率下每秒可以发送约45个包对火灾监控场景完全够用。设计上有一个值得借鉴的地方温度是用temp / 10和temp % 10拆成整数和小数部分,而不是用浮点运算因为51单片机没有硬件浮点单元sprintf里的%f在Keil C51下默认不支持这样做可以避开浮点库的额外开销。4.3 warning和close的触发条件与上位机联动报警状态的上报是这套设计里最有参考价值的部分warning和close代表了两种不同的系统状态if ((smoke_val SMOKE_THRESHOLD) || (flame_val FLAME_THRESHOLD) || (temp_val TEMP_THRESHOLD)) { FanOn(); // 先启动风机排烟 UartSendString(warning\r\n); PumpOn(); // 启动水泵灭火 BuzzerOn(); // 蜂鸣器报警 } else { FanOn(); // 正常状态下风机持续排烟 PumpOff(); BuzzerOff(); }这里的关键点在风机和泵的联动顺序报警触发后先开风机、再开泵。实际工程里这种先后顺序意味着要优先排烟、降低燃烧区域内可燃气体浓度再喷水灭火避免在高温烟气环境下直接喷水产生蒸汽烫伤。上位机收到warning后可以在监控界面上弹窗、闪烁指示灯或联动输出继电器。风机故障逻辑单独放在定时器中断里检测void Timer0Isr(void) interrupt 1 { static unsigned int fan_check_cnt 0; TH0 0x4C; // 50ms定时重装值 TL0 0x00; fan_check_cnt; if (fan_check_cnt 20) // 累计1秒检测一次 { fan_check_cnt 0; if (FanFeedback 0) // 风机反馈信号为低判定故障 { UartSendString(close\r\n); SystemStop(); // 停机保护 } } }这个风机故障检测的设计思想是正常运行中风机控制引脚输出高电平同时从风机调速反馈线上读取一个电平信号若控制端有输出而反馈端持续1秒为低电平判定风机堵转或断线。SystemStop()函数会切断水泵和风机的电源同时把系统锁死在停止状态需要手动复位才能重新启动。这种“故障锁定”机制在真实的消防联动控制器里就是安全规范要求防止设备带病运行导致事故扩大。5. 阈值修改变量与风机故障的仿真模拟调试技巧5.1 在Proteus里模拟风机故障的做法仿真里模拟风机故障最简单的方法是在风机反馈线上串联一个手动开关。正常运行时时开关闭合反馈信号正常拨动开关断开反馈线后由于反馈引脚被下拉电阻拉低单片机在1秒内就会检测到故障状态并发送close。此时观察串口助手应当看到系统不再周期性上传TEMP数据包而是只发出一次close后所有输出引脚全部置低。这个方法有一个值得注意的地方在真实设备里风机反馈通常是测速脉冲而不是电平。你在把代码移植到实物时需要把定时器中断里的电平检测改成正交解码或者脉冲计数模式否则普通直流风机在固定转速下输出的方波信号会让电平检测误判。常见的补救办法是在反馈引脚和单片机之间加一个RC低通滤波把脉冲信号平滑成直流电平——但这会牺牲响应速度实际项目里更推荐用光电编码器加定时器计数。5.2 修改控制阈值的正确入口工程包里有一张名为修改控制阀值.bmp的截图它显示了阈值宏定义在源代码中的具体位置。修改阈值有两种方式原理上等价直接编辑main.c顶部的宏定义是最直观的方式。SMOKE_THRESHOLD和FLAME_THRESHOLD的取值区间是0~255对应ADC0832的采样范围。如果你希望烟雾报警更灵敏就把SMOKE_THRESHOLD往下调如果经常误报就往上调。TEMP_THRESHOLD的单位是DS18B20的12位原始值实际摄氏温度等于原始值乘以0.0625因此500对应31.25℃500 × 0.0625 31.25℃。第二种方式是编译后在Proteus中观察报警触发的临界点。把电位器滑臂从0V缓慢往上调当串口助手第一次打印warning时记录当前电位器的电压值再根据“ADC值 电压 / 5V × 255”反算出阈值这样就完成了现场标定。我通常会结合LCD1602上实时显示的烟雾浓度值来比照如果LCD显示120时报警触发而期望在150时报警就说明阈值设置偏低需要微调宏定义后重新编译烧录HEX文件。5.3 仿真运行不稳定的幻觉现象排查Proteus仿真这类混合信号系统时偶尔会遇到“物理上正确但仿真不工作”的情况最常见的三个现象和对应排查思路第一个现象是LCD1602只亮不显示字符。原因往往是排阻上拉网络的电源没有正确连接或者是LCD对比度引脚接到了地而不是接可调电阻。在Proteus里LM016L的VO引脚接地时对比度最高部分项目文件里会直接用固定电阻分压如果你看到的LCD显示方框而不是字符优先检查P0口的上拉排阻和VO引脚的电压。第二个现象是DS18B20读回温度恒为85℃。85℃是DS18B20上电复位的默认状态出现这个数值通常是因为复位时序不对单片机还没来得及让DQ线释放DS18B20就返回了默认值。排查时用示波器观察DQ线上的波形确认复位脉冲低电平时间至少480us、读时隙的总时间不低于60us。第三个现象是ADC0832读回的数值一直跳变。原因是Proteus里电位器调节时会产生瞬态接触噪声如果单片机以极快的速度连续采样个别采样点会抓到跳变沿。解决方法是把采样循环里的延时函数从int i改为unsigned int i把循环次数从8次提高到16次同时增加5ms的延时让ADC数据在有足够时间稳定。5.4 验证系统完整性的三组测试向量最后分享一套我用来判断这套系统是否搬成功的测试序列你也可以对照验证自己的移植结果正常环境下烟雾电压低于阈值、温度26℃、无火光串口持续输出TEMP26.0 SMOKExx FLAMExx状态包频率约每秒1次LCD第一行显示实时温度第二行显示烟雾和火光值风机持续运转。缓慢调大烟雾电位器当ADC值超过SMOKE_THRESHOLD的瞬间串口打印warning蜂鸣器发声、水泵电机转动、LCD背光闪烁这时把电位器回调到阈值以下系统应当恢复正常状态但有些版本的程序设置了报警锁存需要手动复位才能解除这取决于main.c里报警标志位的设计。断开风机反馈开关1秒内串口打印close所有执行机构断电此后即使烟雾浓度超标也不再触发warning重新闭合开关并复位单片机后系统恢复全自动监控模式。这三组测试全部通过说明你拿到的这套工程包已经具备了完整的检测、执行、自检闭环能力。本文还有配套的精品资源点击获取