资讯动态

STM32多路火灾报警系统设计:从传感器选型到去抖滤波的工程复盘

发布时间:2026/10/3 1:09:15 来源:尧图企业网站定制
入秋之后帮人参谋了一个毕业设计项目基于STM32的多路火灾报警系统。这标题在嵌入式和自动化类选题里属于常青树每年都能见到好几个版本。但说实话大部分交上来的方案只做到了“能响”——单片机检测到一个模拟量超过阈值就推高蜂鸣器演示流程走一遍就结束。实际做一套真正可用的多路火灾报警系统远不是点个LED那么简单从传感器选型、信号调理、电源隔离到软件层面的去抖、滤波、迟滞判断每一环都有能让人熬夜的坑。这套系统的核心价值在于“多路”和“可靠”。单个烟雾报警器覆盖范围有限厨房的水蒸气、客厅的香烟、卧室的空调热风会让单点传感器疯狂误报而真正火灾初期的高温、浓烟特征又可能因为传感器安装位置不当而漏报。STM32的多路ADC采集、多组GPIO控制、定时器调度能力配合合理的外围电路可以在一颗主控上完成多区域并行监控、智能判定、联动控制和故障自检。我这次就来完整复盘一套可落地的设计侧重讲清楚那些文档里不会写明的取舍和实测经验。1. 需求拆解与选型逻辑为什么是多路为什么是STM321.1 单点报警的天然缺陷市面上一百多块的独立烟雾报警器本质是一个MQ-2或离子式传感器接一个电压比较器浓度超了就响。这类设备的误报率有多高用过的都知道厨房煎个牛排警报响了浴室的蒸汽散不出去也响了。原因在于单传感器单阈值方案无法区分“烟雾浓度高”和“确实着火了”更无法定位火源在哪个区域。多路方案解决的问题有两个空间覆盖和区域定位。在实验室、仓库、居民楼这类场景四个典型监测点比如厨房、卧室、客厅、楼道分别布置烟雾、温度或火焰传感器集中接入一台STM32主机。哪一路报的警主机通过数码管或OLED显示号位同时控制对应区域的声光报警器和联动阀门。这个逻辑用PLC能做用51单片机勉强能做但论外设丰富度、开发效率、资料成熟度STM32是舒适区。1.2 STM32在火灾报警场景的不可替代性选STM32不是因为它跑得快而是因为它在“中等集成度低功耗丰富外设”这个交叉点上太合适。多通道ADCSTM32F103系列有十几个ADC通道完全可以覆盖8路以内的模拟量传感器不需要外扩模拟开关或独立ADC芯片。多组定时器一路定时器做系统心跳一路做ADC触发采样一路留作看门狗喂狗调度不打架。高电平驱动能力GPIO直接配合三极管或MOS管驱动蜂鸣器、继电器省去额外扩展芯片。开发资料成熟标准库和HAL库的例程铺天盖地CubeMX图形化配置外设学生和工程师都能快速上手踩坑时有大量前车之鉴可查。需要注意一点STM32F103C8T6这种小容量芯片的Flash只有64KB代码量控制不好容易爆。做这类报警系统我建议全程用HAL库但不开CubeMX生成所有中间层代码用不到的外设别初始化编译优化选Level 2能省出不少空间。2. 硬件电路设计传感器接口、电源与驱动的完整方案硬件是整个报警系统最容易出“隐性问题”的地方。软件写错了顶多跑飞重启硬件布线不合理会导致传感器数据漂得你怀疑人生。2.1 传感器选型烟感、温感、火焰检测各司其职多路火灾报警不能全用同一种传感器不同火灾阶段的物理特征不一样传感器互补才是正解。传感器类型检测对象输出信号响应速度典型型号烟雾传感器早期阴燃产生的烟雾颗粒模拟电压随浓度升高慢需预热MQ-2、MQ-7温度传感器环境温度异常升高NTC分压/数字单总线中等NTC 10K、DS18B20火焰传感器火焰发出的红外/紫外波段数字高低电平快红外火焰模块MQ-2烟雾传感器是这类设计的绝对主力它内部有一个加热电阻和二氧化锡气敏材料遇到可燃气体或烟雾时电导率变化输出电压随之变化。需要注意的是MQ-2模块有两种输出数字量DO和模拟量AO。很多新手直接接DO口进GPIO以为拧到灵敏度电位器就能用实际测下来DO阈值的重复性很差温度漂移严重。正确做法是读AO模拟量在软件里做阈值判断。NTC热敏电阻作为温度传感器成本几毛钱一个10K电阻分压就能工作。火灾报警场景不需要高精度体温计那样的分辨率NTC足够。火焰红外传感器模块输出的是比较器后的数字信号低电平表示检测到火焰。它的响应速度极快几毫秒就能拉低电平适合做快速联动比如第一时间切断燃气阀。缺点是容易受阳光、白炽灯中的红外成分干扰需要调整模块上的阈值电位器配合遮光筒使用。2.2 模拟信号采集电路分压和滤波是基本功STM32的ADC输入范围是0到3.3V而MQ-2模块的AO输出范围是0到5V直接接上去会烧引脚。正确做法是电阻分压我用的是10K和20K串联输出端对GND接20K分压比例1/3满量程5V降到3.33V正好卡在ADC量程边缘。NTC测温电路同样用电阻分压10K NTC串联10K精密电阻中间节点接ADC输入。温度升高时NTC阻值下降分压值降低软件端通过公式或查表换算温度。公式法用Steinhart-Hart方程查表法要把NTC分度表做成数组工程上查表更稳定不依赖浮点运算。硬性建议**每一路模拟输入到ADC引脚之间串一个100欧到1K的电阻再接一个0.1uF电容到GND组成RC低通滤波。**这能滤掉传感器输出上的高频噪声和50Hz工频干扰。第一次做的时候我图省事没加ADC采样用DMA循环采了100次做平均数据依然在±50mV范围跳后来加了104电容立刻干净了。2.3 声光报警和联动控制驱动电路报警输出我用了两路一路蜂鸣器一路继电器控制电磁阀或风机。蜂鸣器驱动用有源蜂鸣器最简单内部自带震荡源通电就响。PB12引脚通过1K限流电阻接S8050三极管基极发射极接地集电极接蜂鸣器负极蜂鸣器正极接5V电源。三极管饱和导通时集电极电流约30mA完全带得动小蜂鸣器。如果要用无源蜂鸣器需要TIM输出PWM驱动音调可变但代码复杂度上去了报警场景没必要。继电器驱动同样用三极管但必须加续流二极管。继电器线圈是感性负载断电瞬间会产生反向感应电动势没有二极管泄放的话这个尖峰能打穿三极管甚至沿着电源线干扰MCU导致瞬间复位。1N4007或1N4148反向并联在线圈两端极性别接反。注意继电器电源和传感器电源尽量分开走线。MQ-2传感器的加热丝工作电流约150mA继电器吸合瞬间电流更大如果共用一根细长电源线MCU侧电压会被拉低ADC参考电压也跟着波动采集值直接失真。我的做法是外部12V适配器供电经LM2596降到5V给蜂鸣器和继电器再从5V经AMS1117降到3.3V给MCU和传感器三个电压域地线单点接地。3. 软件实现CubeMX初始化、多路采集与报警判定硬件焊好后软件是重头戏。这部分我会把从CubeMX配置到最终烧录验证的完整链路讲清楚直接照着做就能跑通。3.1 CubeMX配置时钟树、ADC和定时器我用的是STM32F103C8T6 HAL库 Keil5环境CubeMX版本6.x。配置项如下时钟外部8MHz晶振PLL倍频到72MHz主频APB1分频到36MHzADC时钟设为12MHzADC最高14MHz别超。ADC1开启4个通道PA0/PA1/PA2/PA3对应IN0/IN1/IN2/IN3扫描模式开启连续转换关闭用定时器触发而不是连续转换这样能精确控制采样节奏。DMA开启循环模式数据宽度半字16位外设地址自动递增。DMA缓存数组设为4个uint16_t。TIM2设置为1ms中断作为系统时基软件里做计数器累加每100ms启动一次ADC转换每500ms读取一次DMA结果并处理报警逻辑。GPIOPB12推挽输出接蜂鸣器PB13推挽输出接继电器PB14/PB15接两个LED指示灯运行灯报警灯火焰传感器数字量输入接PB0-PB3上拉输入。配置完成后CubeMX会自动生成main.c、adc.c、dma.c等文件但实际工程文件不需要全部保留把gpio、tim、adc、dma这些核心文件拖进工程即可。3.2 多路ADC采集DMA循环模式与滤波DMA在这里解决了“CPU反复进中断读ADC寄存器”的问题。配置成循环模式后ADC每次转换完4个通道DMA自动把结果搬运到内存数组CPU无需干预。#define ADC_CH_NUM 4 uint16_t adc_raw[ADC_CH_NUM]; // ADC初始化后启动DMA HAL_ADC_Start_DMA(hadc1, (uint32_t *)adc_raw, ADC_CH_NUM); // 在TIM2中断回调中每100ms触发一次ADC采样 if (software_tick % 100 0) { HAL_ADC_Start_DMA(hadc1, (uint32_t *)adc_raw, ADC_CH_NUM); }这里有个细节采样值必须滤波但滤波算法别选滑动平均。我试过直接对4个通道做10次滑动平均虽然平滑了但火灾报警场景需要快速响应滑动平均会拖慢阶梯信号的爬升响应。正确做法是中值滤波每通道连续采5次排序后取中间值。这样既滤掉脉冲噪声又不会显著增加响应延迟。uint16_t median_filter(uint16_t *buf, uint8_t len) { uint8_t i, j; uint16_t tmp; for (i 0; i len - 1; i) { for (j i 1; j len; j) { if (buf[j] buf[i]) { tmp buf[i]; buf[i] buf[j]; buf[j] tmp; } } } return buf[len / 2]; }实际测试中日照、电吹风这类突然出现的红外和气流噪声中值滤波能压掉大部分单次脉冲干扰。3.3 报警判定去抖、迟滞与区域联动判定逻辑是整个软件的核心我设计了三级状态机正常 - 预警 - 报警。去抖环节很重要。MQ-2的模拟输出在火灾初期不会是平滑上升的直线而是带波动的爬坡。直接拿单次滤波值和阈值比结果就是蜂鸣器响一下停一下比心虚的闹钟还烦人。我的做法是积分判定连续5次采集每次间隔500ms如果至少4次超过阈值才进入预警状态再连续3次确认才正式拉高报警输出。这样既过滤了瞬时波动又保证了在2秒内能响应真实火情。迟滞阈值是避免“报警阈值附近反复横跳”的关键。报警动作值和恢复动作值必须设置成两个不同值中间留出不小于50mV的迟滞带。#define ALARM_THRESHOLD_MV 1800 // 对应MQ-2输出约1.8V分压后 #define RESET_THRESHOLD_MV 1500 // 低于1.5V才解除报警意思是当烟雾浓度升高到1.8V触发报警后浓度得跌回1.5V以下蜂鸣器才停。这样避免了临界状态下蜂鸣器反复通断的“弹振”现象。区域联动逻辑上每一路报警都对应独立的输出动作而不是把所有路都做成“响一个大蜂鸣器”。我的设计第1路厨房报警时蜂鸣器响同时继电器动作切断燃气阀第2路卧室报警时蜂鸣器响LED闪烁继电器动作启动排烟风机第3路客厅报警时蜂鸣器响LED亮不联动设备第4路楼道报警时蜂鸣器响同时触发所有路声光报警表示需要疏散这个逻辑在代码里就是一组if-else和位标志重点在于用状态机把“当前处于什么阶段”理清楚避免多路报警互相覆盖。比如锅炉房和卧室同时报警时不能只显示最后触发的区域号要支持多路状态同时显示。我用一个8位变量alarm_flags每一位代表一路按键切换OLED显示时轮询读取。4. 实测中的误报问题排查与改善系统的软件框架和硬件搭好后真正的挑战才开始。以下是我实测过程中踩过的坑和对应的排查思路这部分在整个项目里最有借鉴价值。4.1 一次误报警的完整排查链路第一版样机装好后放在实验室角落没烧火没点烟某天凌晨突然开始报警。排查过程如下检查报警记录通过串口日志第3路的值在20秒内从1.2V飙升到2.3V。检查传感器硬件第3路是客厅的MQ-2外观无异常万用表测量AO输出稳定。用示波器观察第3路供电电源发现12V输入经过LM2596后的5V输出有周期性跌落跌落到4.5V后再回弹周期约5秒。启动空调压缩机时跌落更深。进一步查指纹MQ-2的AO是相对自身供电电源的比值输出电源跌落时AO电压短暂上升恰好穿越了阈值。根因传感器模拟输出对电源波动敏感加热丝电流变化导致气敏电阻两端电压突变。解决办法分三步在MQ-2模块电源引脚并联100uF电解电容和104瓷片电容吸收瞬时跌落ADC参考电压源用MCU的3.3V LDO独立输出不跟传感器共用软件上把单次采样扩展为“100ms窗口内采20次取中值”进一步抑制工频噪声。改完后连续跑了三天没有再出现空报。4.2 传感器预热和基线校准另外一个容易忽略的点是传感器预热。MQ-2断电重新上电的前3分钟输出会严重漂移加热丝还没把气敏元件加热到工作温度此时读到的电压异常偏高。我的处理是在主控上电后加一个120秒的“初始化预热”阶段串口打印倒计时OLED显示“Warming Up”。预热阶段不进行报警判定预热结束后读取当前各路ADC值作为基线偏移量后续判定使用“当前值-基线值”和阈值比较。这一步解决了“为什么今天开机就报警、明天同样位置又不报警”的玄学问题。提到基线就牵扯到长期老化问题。MQ-2使用3个月以上零点输出电压会因气敏材料老化发生漂移。可做一个技巧每24小时自动在凌晨3点记录一次基线值此时无人活动烟雾浓度最低存入Flash。当然这个功能对毕业设计来说是加分项实现起来不过是RTCFlash存储启动时读回而已。4.3 火焰传感器误触发的红外干扰火焰红外模块让我头疼了很长时间。某一路的数字量输出总是随机出现低电平用示波器抓频率不规律持续几毫秒到几十毫秒不等不像真实火焰的信号。排查中发现模块旁边正好是LED照明灯的电源线LED驱动里的红外成分虽然不多但近场耦合进模块的敏感PIN脚比较器一旦判断超过阈值就输出低电平。处理方案给火焰传感器模块加一个黑色遮光罩只留一个朝向监测区域的窗口缩小接收视角调整模块电位器提高触发阈值让太阳光和灯光都达不到触发电压软件层面对数字量输入做连续确认连续读到10次低电平每次间隔10ms才认为有效报警否则忽略。这三步做完火焰传感通道再没出现过误触发。遮光罩的细节很值得注意双面胶固定时检查传感器开窗方向位置装反了等于没遮。5. 系统调试与扩展从Demo到可交付的小系统当报警系统的基础功能稳定之后我从三个方向做了扩展和打磨让这套东西从“能响的毕设”变成“像个正经产品”的程度。5.1 OLED显示、按键阈值标定与本地调试给系统加了一块0.96寸OLEDI2C接口SCL接PB6SDA接PB7显示信息包括当前日期时间RTC芯片DS3231或STM32内部RTC四路传感器实时电压值、当前状态正常/预警/报警报警历史记录最近5条含区域和时间阈值参数菜单菜单用三个按键操作确认、切换、加减。调试时直接在界面上调整阈值不用反复改代码烧录。这个交互设计其实是项目演示时的加分项评审老师看到实物能直接调整阈值而不是看串口日志印象分完全不一样。5.2 通信扩展CAN总线、RS485与远程监控火灾报警系统在实际场景中往往需要接入上位机或消防控制主机。我给系统预留了两种通信接口RS485接口使用SP3485收发器Modbus-RTU从站模式上位机通过485总线轮询各分机和传感器数值。多个报警分机可以挂在同一条总线上实现楼宇级联网。CAN接口STM32F103C8T6没有CAN外设C8T6的是精简版需要换用STM32F103RCT6或加SPI转CAN芯片MCP2515。CAN适合实时性要求高的联动场景类似消防广播和排烟系统的联动触发。RS485的代码分包格式很简单地址码功能码寄存器地址数据CRC16。我实测过Modbus-RTU轮询1200波特率下10个分机不掉线稳定性足够毕业设计演示。5.3 可靠性设计看门狗、掉电存储与电路保护报警系统最重要的属性是“长期可靠”。我加入了一套可靠性措施这也是之前从实际项目学到的教训独立看门狗IWDG在主循环里周期性喂狗一旦程序跑飞自动重启。看门狗溢出时间设为2秒不干扰正常的500ms判定逻辑。EEPROM存储使用AT24C02存储阈值、基线和报警记录。掉电不丢数据重启后恢复现场。电源反接保护电源输入串联1N5819肖特基二极管反接时后级不会损坏。TVS瞬态抑制管在12V输入端口并联SMBJ15A吸收雷击浪涌和感性负载通断产生的尖峰。这套设计花在电路保护上的时间不多但对于去过现场的老工程师来说看到输入端口有TVS管和续流二极管就知道这项目不是只会跑马灯的入门水平。最后再聊一点个人体会。做火灾报警这类安全相关项目和做普通物联网玩具最大的区别是你必须假设传感器会坏、电源会波动、信号会被干扰然后设计一套逻辑来拥抱这些不确定性。多路采集的意义不是让系统更复杂而是让单路失效不至于导致整体瘫痪。这套系统固化下来后我在四路传感器全都通电的情况下连续跑了将近一周每天记录误报和漏报次数最终确认无误后才敢往下传。希望这篇复盘能帮做类似题目的朋友少走几个弯路尤其是正好卡在误报和去抖问题上的那几段代码可以直接抄走用理解比硬搬更重要。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑