- 基于单片机的多路热电偶温度监测与报警器
点击链接下载protues仿真设计资料:https://download.csdn.net/download/m0_51061483/92081542
- 系统概述
2.1 设计背景与应用场景
在工业生产、实验室环境、食品加工、医疗恒温设备、环境监测等应用中,温度不仅需要实时采集,还需要在温度异常时迅速发出报警提示,以避免设备损坏、材料变质或实验失败。传统的单点温度检测无法满足多测点分布式监控需求,而多路温度监测系统可以同时对多个关键位置进行监控,提高可靠性与安全性。
本系统以单片机为核心控制器,采用 4 路 N 型热电偶作为温度传感器,结合热电偶专用转换模块,实现 0~100℃ 温度范围内的实时监测,并支持为每一路独立设置上下限报警阈值。当任意一路温度超出设定范围时,系统将触发蜂鸣器与 LED 进行声光报警,并在显示屏上提示异常通道与报警类型(高温/低温)。
2.2 系统总体目标
系统实现以下主要目标:
1)完成 4 路 N 型热电偶温度采集并实时显示;
2)支持按键设置每路温度上下限报警值,并可保存;
3)当温度越界时蜂鸣器与 LED 声光报警;
4)在 0~100℃ 范围内保证较高测量稳定性与精度,低温区精度更高;
5)系统运行稳定,具备抗干扰能力与良好的人机交互体验。
- 系统功能设计
3.1 四路温度采集与实时显示
系统通过热电偶转换模块将 N 型热电偶的毫伏级热电势转换为数字温度值。主控单片机周期性读取四路温度数据,并对采集结果进行滤波、校准和单位转换,最终显示在屏幕上。显示内容包括:
- CH1~CH4 温度实时值(单位 ℃)
- 每路的报警状态(正常/高报警/低报警)
- 当前设置模式提示(若进入阈值设置)
由于热电偶信号非常微弱且易受噪声影响,本系统在采样与软件处理上采用了多种抗干扰方法,例如移动平均滤波、异常值抑制、采样延时与屏蔽设计等,以提高显示稳定性。
3.2 按键设置上下限报警值
系统提供按键进行参数设置,支持为四路通道分别设定:
- 上限报警值 HighLimit[i]
- 下限报警值 LowLimit[i]
设置流程一般为:
- 按"设置"键进入设置模式
- 按"通道"键选择 CH1~CH4
- 按"项目"键切换上下限
- 按"加/减"键调整数值
- 按"确认"键保存并退出
每一路通道的阈值独立存储,断电后可通过 EEPROM/Flash 读取恢复。
3.3 越限声光报警
当任意一路温度满足以下条件:
- T[i] > HighLimit[i]:高温报警
- T[i] < LowLimit[i]:低温报警
系统立即触发:
- 蜂鸣器鸣叫(可采用间歇或连续鸣叫策略)
- 对应 LED 点亮或闪烁
- 显示屏给出报警通道与报警类型提示
为了避免温度临界点抖动频繁报警,系统可设计报警回差(Hysteresis),例如:
- 高温报警触发点 HighLimit
- 高温恢复点 HighLimit - Hys
- 低温报警触发点 LowLimit
- 低温恢复点 LowLimit + Hys
这样可以减少误触发,提升报警可靠性。
3.4 测温特性说明(0~100℃)
N 型热电偶在低温区(特别是 0~50℃)线性较好,配合冷端补偿与数字化转换模块可获得较高精度。随着温度升高,热电偶输出电压的变化率与非线性特性会导致误差增大,此外放大器漂移、冷端补偿误差和环境噪声对高温区影响更明显,因此系统在高温区误差相对增大属于合理特性。
本系统重点优化低温段精度,适用于 0~100℃ 温控/监测应用。
- 系统电路设计
4.1 电路设计总体结构
系统硬件电路可划分为以下模块:
1)单片机主控模块
2)4 路 N 型热电偶传感器与接口模块
3)热电偶信号调理/转换模块(带冷端补偿)
4)显示模块
5)按键输入模块
6)声光报警模块(蜂鸣器 + LED)
7)存储模块(EEPROM/内部 Flash)
8)电源模块与稳压/滤波
9)抗干扰与保护设计模块
各模块通过标准数字通信(SPI/I2C/GPIO)与主控相连,形成稳定可靠的多路测温与报警系统。
4.2 单片机主控模块
4.2.1 主控芯片选择与作用
单片机作为系统核心,负责:
- 采集四路温度数据
- 扫描按键输入
- 控制显示刷新
- 判断报警条件并控制蜂鸣器与 LED
- 保存与读取报警阈值参数
- 执行滤波、校准等算法
常见选择包括:
- 8051 系列(如 STC、Nuvoton)
- AVR(如 ATmega328P)
- STM32(Cortex-M0/M3/M4)
本系统不限定具体型号,但应满足:
- 至少具备 SPI 或 I2C 接口(用于热电偶转换模块、显示模块)
- 足够的 GPIO(按键、LED、蜂鸣器控制)
- 稳定的定时器资源(周期采样、蜂鸣器节奏控制)
- 具备 EEPROM 或可用 Flash 模拟 EEPROM(存储阈值)
4.2.2 时钟电路
为保证采样与显示刷新稳定,单片机可使用:
- 外部晶振(如 8MHz/16MHz) + 两个匹配电容
或 - 内部 RC 时钟(精度稍低,但足够)
若系统用于工业场景且需要更精准的采样周期,建议使用外部晶振。
4.2.3 复位电路
复位电路确保系统上电后进入确定状态。常用方式:
- RC 上电复位(电阻+电容)
- 复位按钮 + 上拉电阻
- 监控芯片(若对可靠性要求高)
4.2.4 下载/调试接口
可预留 ISP/SWD/UART 接口,便于程序下载、参数校准与调试输出。
例如:
- 8051:串口 ISP
- STM32:SWD + 串口日志
4.3 四路 N 型热电偶传感器与接口模块
4.3.1 N 型热电偶简介
N 型热电偶属于镍铬硅/镍硅热电偶,具有:
- 良好的抗氧化能力
- 相对稳定的热电势输出
- 适用于较宽温度范围
本系统工作范围为 0~100℃,属于热电偶较低温应用段。
4.3.2 热电偶接线与接口保护
热电偶信号微弱,接线应注意:
- 使用热电偶专用补偿导线,避免引入额外热电势
- 接口处使用端子台或专用插座,保证可靠接触
- 增加 ESD/浪涌保护(TVS 二极管或输入保护电路)
- 采用屏蔽线并单点接地,降低工频与电磁干扰
4.3.3 通道隔离与布局建议
四路热电偶应尽量:
- 走线短
- 远离开关电源、蜂鸣器、电机等强干扰源
- 模拟前端区域单独布线并铺地
- 接口旁预留 RC 滤波或共模滤波器位置
这样可以显著减少热电偶测量抖动,提高低温段精度。
4.4 热电偶信号调理/转换模块(带冷端补偿)
4.4.1 为什么需要转换模块
热电偶输出为毫伏级电压,并且与温度呈非线性关系。如果直接用单片机 ADC 测量,需要高精度放大器、精密 ADC、冷端补偿温度传感器以及复杂的软件线性化计算,系统复杂且误差难控。
因此本系统采用热电偶专用转换模块(常见如 MAX31856、MAX31855、AD849x 等方案),它们集成了:
- 高精度放大与 ADC
- 冷端补偿
- 热电偶类型选择
- 数字输出接口(SPI/I2C)
这样可以大幅降低硬件设计难度并提升精度稳定性。
4.4.2 四路实现方式
实现四路热电偶采集通常有两种方案:
- 方案 A:4 个独立转换芯片
每路热电偶对应一个转换芯片,优点是通道独立、互不影响,软件逻辑清晰;缺点是成本略高。 - 方案 B:多路复用 + 单个高精度转换
通过模拟开关/多路复用器轮询热电偶,再由同一个转换模块处理。优点是成本低;缺点是设计复杂,对切换瞬态与补偿误差要求高。
本系统建议采用方案 A,能更好保证低温段精度与稳定性。
4.4.3 通信接口电路(SPI/I2C)
转换模块一般通过 SPI 或 I2C 与单片机通信,电路设计要点:
- SCK/MOSI/MISO/CS(SPI)或 SCL/SDA(I2C)走线短且加上上拉/串联电阻(视需要)
- 电平兼容:单片机与转换芯片电压一致(如 3.3V)
- 若采用 5V 单片机,需要电平转换电路
- 通道 CS 独立(SPI 多从机)
4.4.4 冷端补偿说明
热电偶测量的是"测量端与冷端的温差",必须知道冷端温度才能计算实际温度。转换模块内部集成冷端温度传感器,并自动完成补偿。
注意:冷端补偿的准确性与芯片周围温度一致性有关,因此 PCB 布局应保证:
- 转换芯片远离发热源
- 采用良好接地与铜皮散热,使芯片温度更接近接线端温度
- 避免大电流走线经过芯片附近
4.5 显示模块
4.5.1 显示器类型选择
常见显示模块包括:
- 1602/2004 字符 LCD
- OLED(0.96/1.3 英寸,I2C/SPI)
- TFT 彩屏(SPI/并口)
本系统显示内容主要为温度数值与报警状态,使用 1602/2004 LCD 或 OLED 即可。
4.5.2 显示内容组织建议
为了实现直观显示,可采用多页显示:
- 页面 1:CH1、CH2 温度 + 状态
- 页面 2:CH3、CH4 温度 + 状态
或使用大屏 OLED 一页显示 4 路: - CH1: xx.x℃
- CH2: xx.x℃
- CH3: xx.x℃
- CH4: xx.x℃
并在异常时在对应行增加 "HI/LO/!" 标记。
4.5.3 接口电路与注意事项
- I2C OLED:需要 SCL/SDA 上拉电阻(如 4.7k)
- LCD 并口:需要更多 GPIO,并注意电源去耦
- 背光电流较大时注意供电能力与噪声
4.6 按键输入模块
4.6.1 按键类型与数量规划
本系统常用 4~5 个按键:
- SET:进入/退出设置
- CH:通道选择
- ITEM:上下限选择
- UP:数值增加
- DOWN:数值减少
(可选 OK/保存键,也可用 SET 长按保存)
4.6.2 硬件消抖与软件消抖
按键抖动会导致误触发,硬件上可加入 RC 滤波,但更常见的是软件消抖:
- 周期扫描按键(如 10ms)
- 连续检测稳定状态达到阈值才认为有效
- 支持短按与长按(长按加速调节)
4.6.3 按键连接方式
- 上拉输入:GPIO 上拉电阻,按键按下接地
- 下拉输入:GPIO 下拉电阻,按键按下接 VCC
建议使用上拉输入方式,抗干扰更好且节省电阻(可用内部上拉)。
4.7 声光报警模块(蜂鸣器 + LED)
4.7.1 蜂鸣器驱动电路
蜂鸣器分为有源与无源:
- 有源蜂鸣器:输入高电平即可鸣叫,驱动简单
- 无源蜂鸣器:需要 PWM 或方波驱动,可控制音调
为了实现报警提示,本系统建议使用有源蜂鸣器,并通过 NPN 三极管或 MOSFET 进行驱动,避免单片机 IO 直接带载:
- IO 输出控制三极管导通
- 蜂鸣器接 VCC
- 三极管发射极接地
- 若为电感性负载,需并联续流二极管(部分蜂鸣器可省略,但加上更稳妥)
4.7.2 LED 指示电路
LED 可分为:
- 系统运行指示(心跳灯)
- 报警指示(红灯闪烁)
LED 需要串联限流电阻(如 330Ω~1kΩ)。报警时可让 LED 闪烁,以提高提醒效果。
若需要对应每路独立 LED,也可设置 4 个通道报警 LED,更直观定位异常通道。
4.7.3 报警策略设计
建议的报警策略:
- 有一路越界:蜂鸣器间歇鸣叫(例如 200ms 响、800ms 停)
- 多路越界:蜂鸣器快速间歇鸣叫,LED 快闪
- 报警解除:蜂鸣器停止,LED 恢复正常状态
4.8 存储模块(EEPROM/内部 Flash)
4.8.1 存储内容
需保存的参数主要包括:
- CH1~CH4 上限阈值 HighLimit
- CH1~CH4 下限阈值 LowLimit
- 报警回差 Hys(可选)
- 显示模式与单位设置(可选)
4.8.2 存储器选择
- 外置 I2C EEPROM(如 24C02/24C08)
- 单片机内部 EEPROM(部分 MCU 自带)
- Flash 模拟 EEPROM(STM32 常用)
4.8.3 写入策略与寿命保护
EEPROM 有写入寿命限制,因此建议:
- 仅在用户按确认键后写入
- 写入前检测参数变化,若无变化不写入
- 可加入校验字节,防止掉电导致数据损坏
4.9 电源模块与稳压/滤波
4.9.1 供电方案
系统可由:
- 5V USB 供电
- 12V/24V 外部适配器 + 降压模块
- 电池供电(若需要便携)
若热电偶转换芯片与 OLED 使用 3.3V,则需要稳压输出 3.3V。可采用 LDO 或 DC-DC。
4.9.2 滤波与去耦
为了保证热电偶低电平测量稳定,必须重视电源品质:
- 每个芯片电源引脚附近放置 0.1uF 去耦电容
- 电源入口放置 10uF~100uF 电解/钽电容
- 模拟/数字地合理分区,单点汇接
- 蜂鸣器等大电流负载建议单独走线并加滤波
4.10 抗干扰与安全保护设计
4.10.1 信号屏蔽与接地
热电偶线优先使用屏蔽线,并将屏蔽层单端接地,减少地环路干扰。PCB 采用完整地平面可降低噪声。
4.10.2 ESD 与浪涌保护
热电偶接口与按键接口可能被人体触碰,应加入:
- TVS 二极管
- 串联电阻/磁珠
- RC 滤波
4.10.3 软件抗干扰措施
- 温度数据滤波与异常值丢弃
- 看门狗复位防死机
- 参数存储校验防止错误读写
- 报警回差避免临界抖动
- 程序设计
5.1 软件总体架构
5.1.1 程序结构划分
系统软件可划分为以下模块:
1)系统初始化模块
2)温度采集模块(4 路)
3)数据滤波与校准模块
4)显示管理模块
5)按键扫描与人机交互模块
6)报警判断与执行模块
7)参数存储管理模块
8)定时调度与主循环模块
整体运行方式推荐采用"主循环 + 定时任务"结构:
- 定时器中断提供 1ms/10ms 节拍
- 主循环根据标志位执行采样、显示刷新、按键处理等任务
- 避免在中断中执行耗时操作,提升系统实时性和稳定性
5.1.2 任务周期建议
- 按键扫描:10ms
- 温度采样:200ms~500ms(根据需要调整)
- 显示刷新:200ms(OLED 可更快,LCD 可更慢)
- 报警判断:每次采样后立即判断
- 蜂鸣器节奏:由 10ms 节拍控制
5.2 系统初始化模块
5.2.1 硬件初始化内容
- GPIO 初始化(按键输入、蜂鸣器、LED 输出)
- SPI/I2C 初始化(温度模块、显示模块)
- 定时器初始化(周期节拍)
- 看门狗初始化(可选)
- 读取存储参数(阈值、回差)
- 初始化显示界面并提示系统启动
5.2.2 默认阈值策略
若检测到 EEPROM 参数无效(校验失败),系统应加载默认值:
- LowLimit:0℃
- HighLimit:100℃
或更安全的默认范围,例如 10℃~80℃,避免误报警。
5.3 温度采集模块
5.3.1 采集流程
对每路通道执行以下步骤:
1)选择对应的转换芯片(SPI CS 拉低)
2)读取温度寄存器或数据帧
3)解析温度值(可能包含符号位、小数位)
4)转换为摄氏温度浮点或定点格式
5)存入温度数组 Temp[i]
5.3.2 采样数据格式设计
为了降低单片机资源消耗,推荐使用"定点数"表示温度:
- 例如以 0.1℃ 为单位存储:253 表示 25.3℃
这样可以避免频繁浮点运算,提高速度。
5.3.3 异常检测
热电偶可能出现开路、短路或反接,转换芯片通常会提供故障标志位。软件应检测:
- 传感器断线:显示 "OPEN" 并报警或提示
- 读数异常:忽略并保留上次有效值
- 通道故障:允许用户确认后关闭该通道报警(可选扩展)
5.4 数据滤波与校准模块
5.4.1 滤波必要性
热电偶测量受噪声影响,尤其在低温段,显示波动会影响用户判断,因此必须进行滤波。
5.4.2 移动平均滤波
对每一路维护一个长度 N 的采样队列,例如 N=5:
- 新值入队
- 计算平均值作为显示值
移动平均能有效抑制随机噪声,适用于温度缓慢变化场景。
5.4.3 中值滤波与异常值抑制
当系统可能受到突发干扰导致瞬间跳变,可加入:
- 若当前值与上一次差值大于阈值(如 20℃),判为异常并丢弃
- 或采用 3 点中值滤波,抵抗尖峰噪声
5.4.4 校准方式
可提供软件校准系数:
- TempCal[i] = TempRaw[i] + Offset[i]
Offset[i] 可在出厂时测量并写入 EEPROM,使 4 路一致性更好。
由于系统强调低温段精度,校准可在 25℃ 与 80℃ 两点标定,或仅在常用温区做偏移校准即可。
5.5 显示管理模块
5.5.1 显示刷新机制
显示模块不应每毫秒刷新,否则占用总线资源并影响采样。建议:
- 每 200ms 刷新一次屏幕
- 当进入设置模式时可提升刷新频率,以便用户操作更流畅
5.5.2 界面状态机设计
界面可分为:
- 正常显示界面
- 设置界面(选择通道)
- 设置界面(选择上下限)
- 设置界面(数值调整)
- 保存提示界面
使用状态机能使界面逻辑清晰,避免大量 if-else 混乱。
5.5.3 报警提示显示
在发生报警时,界面建议突出显示:
- 报警通道闪烁
- 显示 "HI" 或 "LO" 标识
- 若多路报警,循环显示或同时显示标记
5.6 按键扫描与交互模块
5.6.1 按键扫描实现思路
每 10ms 扫描一次所有按键,记录:
- 当前电平
- 上一次电平
- 稳定计数器
当计数器达到阈值(如连续 3 次相同)则确认按下/释放事件。
5.6.2 短按、长按与加速调节
在阈值设置时,UP/DOWN 可以支持:
- 短按:+0.1℃ 或 +1℃
- 长按:连续快速增加/减少(例如每 100ms 变化一次)
这样用户设置更方便。
5.6.3 参数限制与合理范围
为防止设置错误,建议限制:
- LowLimit 最小值:0℃
- HighLimit 最大值:100℃
- LowLimit < HighLimit
若用户设置冲突,系统可自动纠正或提示"ERR"。
5.7 报警判断与执行模块
5.7.1 报警判断逻辑
每次获得滤波后的温度值后,执行:
- 若 Temp[i] > HighLimit[i] → AlarmHigh[i]=1
- 若 Temp[i] < LowLimit[i] → AlarmLow[i]=1
并结合回差判断解除条件。
5.7.2 报警输出控制
系统维护一个全局报警标志:
- AnyAlarm = AlarmHigh 或 AlarmLow 任意为真
若 AnyAlarm=1:
- 蜂鸣器进入报警节奏
- LED 闪烁
否则: - 蜂鸣器关闭
- LED 恢复正常(如心跳灯)
5.7.3 报警保持与静音设计(可选)
为了提高用户体验,可设计:
- 报警保持:报警发生后保持提示一段时间
- 静音键:用户按下后蜂鸣器静音,但 LED 仍提示
- 若温度恢复正常则自动退出报警
这些属于可扩展功能,但结构上可以预留。
5.8 参数存储管理模块
5.8.1 数据结构设计
建议使用结构体管理参数:
- uint16_t high[4]
- uint16_t low[4]
- uint16_t hys
- uint8_t checksum
5.8.2 校验机制
可采用简单校验:
- 所有字节求和取低 8 位
或 CRC8/CRC16
读取时校验失败则加载默认参数并提示用户。
5.8.3 写入时机
只在以下情况写入:
- 用户确认保存
- 参数发生改变
这样能大幅延长 EEPROM 寿命。
5.9 定时调度与主循环模块
5.9.1 节拍与任务标志位
使用定时器产生 1ms 中断,在中断内:
- 计数并产生 10ms 标志:key_task
- 计数并产生 200ms 标志:temp_task、display_task
- 控制蜂鸣器节奏:buzzer_task
主循环中根据标志位执行对应任务,形成良好的软实时系统。
5.9.2 看门狗设计
在主循环末尾喂狗,如果程序卡死则自动复位。对长期运行系统非常重要。
- 程序示例代码(模块化示例)
c
#include <stdint.h>
#include <stdbool.h>
/* =========================
参数与宏定义
========================= */
#define CH_NUM 4
#define TEMP_MIN_X10 0 // 0.0℃
#define TEMP_MAX_X10 1000 // 100.0℃
#define DEFAULT_LOW 0 // 0.0℃
#define DEFAULT_HIGH 1000 // 100.0℃
#define DEFAULT_HYS 5 // 0.5℃ 回差
/* =========================
全局变量
========================= */
volatile uint32_t g_ms = 0;
volatile bool flag_10ms = false;
volatile bool flag_200ms = false;
int16_t temp_raw_x10[CH_NUM] = {0};
int16_t temp_filt_x10[CH_NUM] = {0};
uint16_t low_limit_x10[CH_NUM] = {DEFAULT_LOW, DEFAULT_LOW, DEFAULT_LOW, DEFAULT_LOW};
uint16_t high_limit_x10[CH_NUM] = {DEFAULT_HIGH, DEFAULT_HIGH, DEFAULT_HIGH, DEFAULT_HIGH};
uint16_t hys_x10 = DEFAULT_HYS;
bool alarm_hi[CH_NUM] = {0};
bool alarm_lo[CH_NUM] = {0};
bool any_alarm = false;
/* =========================
硬件抽象接口(需用户实现)
========================= */
// SPI/I2C 读取某一路热电偶转换芯片温度,返回 0.1℃单位
extern bool Thermo_ReadTempX10(uint8_t ch, int16_t *out_temp_x10);
// 显示接口
extern void Display_ShowNormal(int16_t t0, int16_t t1, int16_t t2, int16_t t3,
bool a0, bool a1, bool a2, bool a3);
// 按键扫描接口:返回按键事件(用户可用枚举表示)
typedef enum {
KEY_NONE = 0,
KEY_SET,
KEY_CH,
KEY_ITEM,
KEY_UP,
KEY_DOWN,
KEY_OK
} key_event_t;
extern key_event_t Key_ScanEvent10ms(void);
// 蜂鸣器与 LED 控制
extern void Buzzer_On(void);
extern void Buzzer_Off(void);
extern void LED_AlarmOn(void);
extern void LED_AlarmOff(void);
extern void LED_HeartbeatToggle(void);
// EEPROM/Flash 参数读写接口
extern bool Param_Load(uint16_t low[CH_NUM], uint16_t high[CH_NUM], uint16_t *hys);
extern bool Param_Save(uint16_t low[CH_NUM], uint16_t high[CH_NUM], uint16_t hys);
/* =========================
简单移动平均滤波(N=5)
========================= */
#define AVG_N 5
static int16_t avg_buf[CH_NUM][AVG_N] = {0};
static uint8_t avg_idx = 0;
static int16_t Filter_MovingAvg(uint8_t ch, int16_t new_x10)
{
avg_buf[ch][avg_idx] = new_x10;
int32_t sum = 0;
for (uint8_t i = 0; i < AVG_N; i++) sum += avg_buf[ch][i];
return (int16_t)(sum / AVG_N);
}
static void Filter_UpdateAll(void)
{
for (uint8_t ch = 0; ch < CH_NUM; ch++) {
temp_filt_x10[ch] = Filter_MovingAvg(ch, temp_raw_x10[ch]);
}
avg_idx++;
if (avg_idx >= AVG_N) avg_idx = 0;
}
/* =========================
报警判断(带回差)
========================= */
static void Alarm_CheckAll(void)
{
any_alarm = false;
for (uint8_t ch = 0; ch < CH_NUM; ch++) {
int16_t t = temp_filt_x10[ch];
// 高温报警
if (!alarm_hi[ch]) {
if (t > (int16_t)high_limit_x10[ch]) alarm_hi[ch] = true;
} else {
if (t < (int16_t)(high_limit_x10[ch] - hys_x10)) alarm_hi[ch] = false;
}
// 低温报警
if (!alarm_lo[ch]) {
if (t < (int16_t)low_limit_x10[ch]) alarm_lo[ch] = true;
} else {
if (t > (int16_t)(low_limit_x10[ch] + hys_x10)) alarm_lo[ch] = false;
}
if (alarm_hi[ch] || alarm_lo[ch]) any_alarm = true;
}
}
/* =========================
蜂鸣器节奏控制(间歇鸣叫)
========================= */
static void Alarm_OutputTask10ms(void)
{
static uint16_t buz_cnt = 0;
static bool buz_state = false;
if (!any_alarm) {
Buzzer_Off();
LED_AlarmOff();
buz_cnt = 0;
buz_state = false;
return;
}
LED_AlarmOn();
// 200ms 响 + 800ms 停(周期 1000ms)
buz_cnt += 10;
if (buz_cnt <= 200) {
if (!buz_state) { Buzzer_On(); buz_state = true; }
} else if (buz_cnt <= 1000) {
if (buz_state) { Buzzer_Off(); buz_state = false; }
} else {
buz_cnt = 0;
}
}
/* =========================
温度采样任务(200ms)
========================= */
static void Temp_SampleTask200ms(void)
{
for (uint8_t ch = 0; ch < CH_NUM; ch++) {
int16_t t;
if (Thermo_ReadTempX10(ch, &t)) {
// 异常值抑制:限制在 0~100℃
if (t < TEMP_MIN_X10) t = TEMP_MIN_X10;
if (t > TEMP_MAX_X10) t = TEMP_MAX_X10;
temp_raw_x10[ch] = t;
}
// 若读取失败,可保留上次值或做断线处理扩展
}
Filter_UpdateAll();
Alarm_CheckAll();
}
/* =========================
显示任务(200ms)
========================= */
static void Display_Task200ms(void)
{
bool a0 = alarm_hi[0] || alarm_lo[0];
bool a1 = alarm_hi[1] || alarm_lo[1];
bool a2 = alarm_hi[2] || alarm_lo[2];
bool a3 = alarm_hi[3] || alarm_lo[3];
Display_ShowNormal(temp_filt_x10[0], temp_filt_x10[1], temp_filt_x10[2], temp_filt_x10[3],
a0, a1, a2, a3);
}
/* =========================
参数加载(启动时)
========================= */
static void Param_Init(void)
{
uint16_t low[CH_NUM], high[CH_NUM], hys;
if (Param_Load(low, high, &hys)) {
for (uint8_t i = 0; i < CH_NUM; i++) {
low_limit_x10[i] = low[i];
high_limit_x10[i] = high[i];
}
hys_x10 = hys;
} else {
// 加载失败,使用默认值
for (uint8_t i = 0; i < CH_NUM; i++) {
low_limit_x10[i] = DEFAULT_LOW;
high_limit_x10[i] = DEFAULT_HIGH;
}
hys_x10 = DEFAULT_HYS;
}
}
/* =========================
简化的设置逻辑(示例)
========================= */
static void UI_Task10ms(void)
{
static bool in_setting = false;
static uint8_t sel_ch = 0;
static bool sel_high = true; // true=high, false=low
key_event_t ev = Key_ScanEvent10ms();
if (ev == KEY_NONE) return;
if (!in_setting) {
if (ev == KEY_SET) {
in_setting = true;
sel_ch = 0;
sel_high = true;
}
return;
}
// 设置模式
if (ev == KEY_SET) {
// 退出不保存
in_setting = false;
return;
}
if (ev == KEY_CH) {
sel_ch = (sel_ch + 1) % CH_NUM;
} else if (ev == KEY_ITEM) {
sel_high = !sel_high;
} else if (ev == KEY_UP) {
if (sel_high) {
if (high_limit_x10[sel_ch] < TEMP_MAX_X10) high_limit_x10[sel_ch] += 1;
} else {
if (low_limit_x10[sel_ch] < TEMP_MAX_X10) low_limit_x10[sel_ch] += 1;
}
} else if (ev == KEY_DOWN) {
if (sel_high) {
if (high_limit_x10[sel_ch] > TEMP_MIN_X10) high_limit_x10[sel_ch] -= 1;
} else {
if (low_limit_x10[sel_ch] > TEMP_MIN_X10) low_limit_x10[sel_ch] -= 1;
}
} else if (ev == KEY_OK) {
// 保存并退出
Param_Save(low_limit_x10, high_limit_x10, hys_x10);
in_setting = false;
}
// 约束逻辑:low < high
if (low_limit_x10[sel_ch] >= high_limit_x10[sel_ch]) {
if (sel_high) high_limit_x10[sel_ch] = low_limit_x10[sel_ch] + 1;
else low_limit_x10[sel_ch] = high_limit_x10[sel_ch] - 1;
}
}
/* =========================
定时器中断(1ms)
========================= */
void SysTick_ISR_1ms(void)
{
g_ms++;
if (g_ms % 10 == 0) flag_10ms = true;
if (g_ms % 200 == 0) flag_200ms = true;
}
/* =========================
主函数
========================= */
int main(void)
{
// 用户需补充:硬件初始化(GPIO/SPI/I2C/Timer/Display)
Param_Init();
while (1) {
if (flag_10ms) {
flag_10ms = false;
UI_Task10ms();
Alarm_OutputTask10ms();
LED_HeartbeatToggle();
}
if (flag_200ms) {
flag_200ms = false;
Temp_SampleTask200ms();
Display_Task200ms();
}
// 可选:喂狗
}
}
- 系统精度与误差分析
7.1 低温段精度较高的原因
在 0~50℃ 范围内,热电偶输出电压变化较为稳定,环境热梯度较小,冷端补偿误差相对可控,配合滤波与校准,系统可获得更高精度。此时测量噪声主要来自电源纹波和 EMI,通过良好硬件布局与软件滤波即可有效抑制。
7.2 高温段误差相对增大的原因
在 50~100℃ 范围内:
- 热电偶非线性更明显
- 热电偶线材与接线端温差更大,冷端补偿更敏感
- 环境干扰与 PCB 温升可能导致转换芯片冷端温度读数偏差
- 放大器/ADC 漂移对高温段影响更明显
因此高温段误差相对增大是由多因素叠加导致的。通过加强冷端区域散热设计、提高供电稳定性、增加校准点、适当降低采样频率(减少噪声)等方式可进一步改善。
7.3 提升精度的工程措施建议
- 采用高精度热电偶转换芯片并保证其参考温度稳定
- 优化 PCB:模拟地与数字地规划、短走线、远离高电流区域
- 热电偶接口使用屏蔽线与单点接地
- 软件端采用滤波 + 异常值抑制 + 校准偏移
- 为每路通道预留独立校准偏移参数,提高一致性
- 总结
本系统以单片机为核心,通过 4 路 N 型热电偶实现 0~100℃ 温度范围的实时监测与显示,并支持为每路设置上下限报警阈值。当温度越界时,系统通过蜂鸣器与 LED 实现声光报警提示,从而满足多点温度安全监控需求。硬件部分采用热电偶专用转换模块实现高精度采集与冷端补偿,并配合良好的电源滤波、接口保护和抗干扰布局保证测量稳定性;软件部分采用模块化结构,实现温度采样、滤波校准、显示管理、按键交互、报警控制以及参数存储等功能,使系统具备良好的可靠性、可维护性与扩展性。通过合理的报警回差策略与人机交互设计,系统能够在工业与实验场景中稳定运行,尤其在低温区具有更高精度表现,满足多路温度监测与报警的实际应用需求。