
温度监测这活儿从家电温控器到机柜里的过热保护再到大型楼宇的HVAC风管温度采集听起来都只是“读个数”但真正动起手来尤其要同时兼顾本地和远程两个测温点的时候里面的门道并不少。我前阵子在一个小型HVAC控制器项目里用PJ85718DM这颗数字温度传感器配合STM32F373VC做主控把板级本地温度和几十米外的风管远端温度一起测了整体跑下来比较稳定中间也踩了一些坑。今天就把这套方案的选型思路、硬件设计、固件处理以及调试中遇到的典型问题完整梳理一遍给做嵌入式温控、暖通空调控制的朋友一个可参考的样本。1. 方案选型为什么是这两颗芯片1.1 需求拆解本地和远程测温根本不是一回事很多人觉得温度监测就是MCU接个传感器读数但“本地温度”和“远程温度”在工程上的诉求差别很大。本地温度通常指MCU所在电路板的板级温度或者是处理器自身的结温它关注的是设备会不会过热、散热系统是否正常工作对响应速度有一定要求但对绝对精度没那么苛刻能到正负1到2摄氏度就够用。远程温度则是设备之外的物理量比如HVAC系统的送风温度、回水温度、冷凝器盘管温度。这类测点位置分散线缆可能要走几米甚至几十米而且处于工业现场干扰和共模噪声都不能忽视。更重要的是暖通控制逻辑往往需要正负0.5摄氏度的精度因为冷热量平衡计算稍微偏一点压缩机启停频率就会明显变化能耗差距会拉得很大。对比项本地温度监测远程温度监测测点位置PCB板面或MCU附近风道、管道、盘管等远端传感器接口数字I2C即可走线短I2C/SMBus需长距离传输精度要求正负1~2摄氏度可接受最好做到正负0.5摄氏度时延要求响应快秒级允许较长时间常数故障影响导致设备过热保护直接导致温控逻辑紊乱所以选型时不能只看传感器分辨率还要把信号传输距离、抗干扰、MCU处理能力、系统整体成本放一起权衡。PJ85718DM这种带SMBus报警功能的数字传感器配合STM32F373VC自带的高性能模拟前端和丰富外设正好能兼顾这两类测点。1.2 PJ85718DM一颗细节够用的数字温度传感器PJ85718DM是一颗I2C/SMBus兼容的数字温度传感器常见封装为SOIC-8或者MSOP-8工作电压范围可以覆盖2.7V到5.5V直接3.3V供电就行。它的温度数据寄存器是12位分辨率LSB对应0.0625摄氏度这对HVAC场景足够了。内部集成了温度上限TH和下限TL寄存器当温度越限时可以拉低ALERT引脚这个特性在做自动告警时非常实用主控不用频繁轮询也能第一时间知道温度异常。这类传感器的地址通常通过A0、A1引脚配置一条I2C总线上可以挂多颗物理层上支持多测点扩展。实际做项目时如果一块板子上既要测板温又要测环境温度完全可以放两颗PJ85718DM地址分别配置成不同值。不过我这里更常用的做法是本地温度直接用STM32F373VC内置温度传感器远程风管温度用PJ85718DM这样硬件成本更低校准压力也更小。1.3 STM32F373VC主控的底气来自模拟外设STM32F373VC这颗芯片属于STM32F3系列内核是Cortex-M4F带FPU主频72MHz。256KB Flash和32KB SRAM在温控器这种应用里属于“富余量很大”的配置跑实时控制算法、通信协议栈都不成问题。但真正让我选它的原因不是CPU性能而是它集成的模拟外设组合内置3个16位Sigma-Delta ADC支持差分输入和可编程增益还有两个12位DAC两个比较器一个运放。这套模拟外设组合在温度监测系统里能派上大用场。16位Sigma-Delta ADC可以直接测量NTC热敏电阻或者热电偶的微弱信号做高精度冗余测温比较器可以配合DAC实现纯硬件的过温保护完全不占CPU运放则可以调理模拟传感器信号。也就是说这套方案并不仅仅局限于PJ85718DM的I2C数字测温必要时能无缝切换到模拟测温通道做备份这是普通M0/M3内核芯片不具备的弹性。2. 硬件设计从传感器焊盘到长线传输2.1 PJ85718DM 最小电路和上拉电阻计算PJ85718DM的硬件连接相当简单SDA、SCL加上拉电阻VDD和GND之间放一个0.1uF陶瓷电容必要时再并联一个1uF到10uF的电解电容做低频去耦。A0、A1地址引脚直接接GND或者VDD来配置器件地址。上拉电阻的选择是个值得认真算的参数。I2C总线的上拉电阻太小灌电流变大低电平可能拉不到0.3VDD以下上拉电阻太大信号上升沿变缓通信速率上不去。标准I2C模式下总线电容通常按每米线缆100pF估算对于板级短走线总线电容大概在50pF到100pF之间上拉电阻取4.7k到10k都合适。但如果远程传感器走线较长总线电容会涨到几百甚至上千pF此时如果还按常规用4.7k上升沿会很差。我一般按下式估算上拉电阻上限R_pullup_max t_rise / (0.8473 * C_bus)其中t_rise对于100kHz标准模式是1000ns对于400kHz快速模式是300ns。假设总线上有3颗传感器加上2米线缆C_bus估算为300pF100kHz下的R_pullup_max大约是1000 / (0.8473 * 300) ≈ 3.94k。所以这时候上拉电阻选3.3k比4.7k更稳妥而板级场景用10k也没问题。2.2 本地和远程布线的差距本地温度传感器走线短布局相对随意但依然要遵守一个原则不要放在电源模块、功率器件等发热源正上方否则测出来的根本不是环境温度而是热应力伪影。我习惯把本地测温点放在板子边缘或者远离MOS管、电感的位置。远程测温的硬件设计就要谨慎很多。PJ85718DM本身的静态功耗只有微安级但长线带来的寄生电容和共模干扰是主要风险。我的做法是远程线缆采用屏蔽双绞线屏蔽层单端接地接到主控板的地平面。SCL和SDA双线必须绞合避免两条平行导线形成环形天线。I2C速率降到100kHz甚至更低不仅能改善上升沿还能降低EMI辐射。如果传输距离超过3米建议在靠近主控端加I2C总线缓冲器比如PCA9600这类器件把长线电容和主控I2C控制器隔离开。还有一点容易被忽略远程传感器的供电和信号线最好分开走不要共用一对双绞线。否则传感器瞬态电流变化会耦合到SDA上导致通信误码。远程PJ85718DM的电源可以在远端加一个LC滤波有效抑制现场的变频器、继电器干扰。2.3 STM32F373VC 外围配置要点主控部分STM32F373VC的VDDA和VREF引脚需要干净的低噪声电源。温度测量精度很大程度上依赖参考电压的稳定性所以VDDA前加磁珠和1uF电容VREF引脚并联0.1uF和4.7uF电容尽量靠近引脚放置。如果要用内部温度传感器做本地测温备份需要注意STM32F373内置温度传感器的读出值精度一般出厂校准点只在30摄氏度左右有一个典型值实际用起来需要自己做两点校准。我在这套项目里没把它当作主测温通道只用于过温保护逻辑也就是感测CPU是否过热这和板级环境温度不是同一个概念逻辑上要区分开。NRST引脚上拉10k电阻并接0.1uF电容到地BOOT0通过10k电阻下拉这些都是常规操作。另外STM32F373VC支持多种低功耗模式HVAC设备如果长期待机可以考虑在空闲时让MCU进入STOP模式由PJ85718DM的ALERT引脚中断唤醒实现低功耗温度监控。3. 固件实现轮询、滤波与告警3.1 I2C 初始化和传感器寄存器读写固件方面先搞定I2C驱动。PJ85718DM的7位地址可以通过A0、A1引脚配置常见默认地址是0x48。我习惯用HAL库里的I2C阻塞式接口做轮询读取因为温度数据的实时性要求不高没必要用中断或DMA增加复杂度。配置寄存器需要设置分辨率、比较模式、故障排队。启动时初始化一次即可/* 使用I2C1连接PJ85718DM */ I2C_HandleTypeDef hi2c1; void PJ85718_Init(void) { uint8_t config 0x00; uint8_t TH 0x1C, TL 0x14; /* 上限28°C下限20°C */ /* 配置寄存器12位分辨率比较模式ACTIVE LOW */ config (0x03 5) | (0x00 4) | (0x00 1); HAL_I2C_Mem_Write(hi2c1, 0x48 1, REG_CONFIG, I2C_MEMADD_SIZE_8BIT, config, 1, 100); /* 写入温度告警阈值 */ HAL_I2C_Mem_Write(hi2c1, 0x48 1, REG_TH, I2C_MEMADD_SIZE_8BIT, TH, 1, 100); HAL_I2C_Mem_Write(hi2c1, 0x48 1, REG_TL, I2C_MEMADD_SIZE_8BIT, TL, 1, 100); }读取温度的代码更简单PJ85718DM的温度寄存器是16位数据分高字节和低字节float PJ85718_ReadTemp(void) { uint8_t buf[2]; int16_t raw; if (HAL_I2C_Mem_Read(hi2c1, 0x48 1, REG_TEMP, I2C_MEMADD_SIZE_8BIT, buf, 2, 100) ! HAL_OK) { return TEMP_READ_ERROR; } raw (buf[0] 8) | buf[1]; /* 12位数据右移4位后乘以0.0625 */ raw 4; return (float)raw * 0.0625f; }3.2 滤波算法别让噪声骗了温控逻辑原始温度数据直接拿来用是不行的。HVAC现场的风机、变频器、继电器切换都会在传感器线上耦合出尖峰毛刺直接反映在读数上就是温度的“跳变”。有一次我调试时看到远端温度在0.5秒内从23.1摄氏度跳到28.7摄氏度又跳回来显然不是真实物理量。常用的处理办法是滑动平均滤波加一阶低通。滑动平均窗口取8到16个点能有效抑制周期性噪声一阶低通可以平滑突然的阶跃变化。我最终采用的是16点滑动平均配合一个时间常数为2秒的一阶低通效果比较理想。#define FILTER_WINDOW_SIZE 16 typedef struct { float buffer[FILTER_WINDOW_SIZE]; uint8_t index; float sum; } MovingAverage; float MovingAverage_Filter(MovingAverage *filter, float new_value) { filter-sum - filter-buffer[filter-index]; filter-buffer[filter-index] new_value; filter-sum new_value; filter-index (filter-index 1) % FILTER_WINDOW_SIZE; return filter-sum / FILTER_WINDOW_SIZE; }一阶低通的系数选择要看采样频率。如果每秒读一次温度时间常数2秒对应的滤波系数alpha约为0.39公式是y[n] y[n-1] alpha * (x[n] - y[n-1])alpha 1 - exp(-Ts / Tau) 1 - exp(-1 / 2) ≈ 0.393滤波虽然能稳定读数但也牺牲了响应速度。如果温控系统里有过热保护逻辑建议同时保留原始值检测一旦原始温度超过硬保护阈值立即触发告警而不是等滤波后的值慢慢爬上来。滤波器只用于控制逻辑的稳态判据。3.3 本地和远程温度的处理逻辑本方案里远程温度由PJ85718DM负责本地温度由STM32F373VC内置传感器负责再加上板载NTC做第三种监测三者形成交叉验证。固件里我把采集任务分成两个层次快速任务每100ms读取一次PJ85718DM和板载NTC做滤波预处理慢速任务每1秒做一次控制逻辑计算包括温差判断、告警判断、历史数据存储。这样分层的目的是温度控制的执行周期可以放慢但数据采集周期足够快让滤波算法有充足的数据点。CPU占用率非常低程控器还能空闲处理PID、RS485通信和触摸屏刷新。如果希望本地也是一颗PJ85718DM那就更简单了同一套I2C驱动轮询两个地址。唯一要留意的是两颗传感器在总线上要分时启动转换避免同时供电造成总线电源跌落。固件里在切换传感器地址后加一个小延时即可。3.4 告警触发逻辑和ALERT引脚的使用PJ85718DM的TH、TL寄存器提供硬件比较告警。配置成比较模式后当测量温度高于TH或低于TLALERT引脚就会拉低。我的做法是把这个引脚接到STM32F373VC的一个EXTI输入一旦温度越限立即产生中断MCU从低功耗状态唤醒执行保护动作。这里有个细节TH和TL寄存器只有8位对应1摄氏度步进。如果你需要0.5摄氏度的告警精度光靠硬件寄存器不够必须在固件里做主控侧比较。我的方案是TH、TL设置保守值比如上限50摄氏度、下限0摄氏度用于极端情况下的硬件保护。精确告警阈值比如27.5摄氏度在主控固件里用滤波后数据比较。这样既保证了硬件保护的绝对可靠性又保证了正常告警的精度。告警触发后还要有一个迟滞区间比如温度升到70摄氏度触发告警要降到60摄氏度才解除避免继电器在阈值附近反复吸合断开。固件里用两个状态变量加上滞回带就能实现。4. 实测数据、精度校准与现场整改4.1 测试环境与实测数据我在实验室做了一套测试工装主控板用STM32F373VC远程传感器用约10米长的屏蔽双绞线连接到一个自制的小型风道模拟箱里用电阻加热丝控制温度参考温度计用高精度铂电阻温度计。实测数据如下设定温度PJ85718DM读数铂电阻参考值偏差15.0°C15.3°C15.1°C0.2°C20.0°C20.4°C20.2°C0.2°C25.0°C25.2°C25.1°C0.1°C30.0°C30.3°C30.2°C0.1°C35.0°C35.6°C35.3°C0.3°C整体偏差控制在0.3摄氏度以内对于HVAC风管测温来说达到中上水平。如果直接开标准模式100kHz、不滤波近距离读数波动在正负0.2摄氏度左右经过滤波之后波动降到正负0.06摄氏度效果很明显。4.2 两点校准的实操步骤PJ85718DM这类传感器出厂有基本精度但如果你需要更高的绝对精度或者系统里有系统性偏置自己做两点校准也很方便。第一步让传感器稳定在低温点比如用冰水混合物模拟0摄氏度环境读取原始值T_raw1记录参考值T_ref1。 第二步让传感器稳定在高温点比如用恒温箱设定50摄氏度读取T_raw2和T_ref2。 第三步计算增益和偏移gain (T_ref2 - T_ref1) / (T_raw2 - T_raw1) offset T_ref1 - gain * T_raw1然后在固件里对每个转换结果做校正T_corrected gain * T_raw offset校准过程要注意传感器必须完全达到热平衡一般要稳定5到10分钟再读数。如果现场条件不允许可以在实验室先把一批传感器的增益偏移统计出来做批量校准。4.3 长线传输的一次整改记录项目刚联调时远程传感器在200kHz速率下频繁出现通信错误表现为I2C总线卡死MCU进入HardFault。排查过程很典型先看波形。用示波器抓SCL和SDA发现SDA线的上升沿明显变缓低电平有台阶说明总线电容过大上拉电阻驱动力不足。把I2C速率降到100kHz后通信恢复但抗干扰能力依然一般一旦附近继电器吸合就出错。进一步检查发现远程电缆的屏蔽层没接只是悬空感应噪声全打在信号线上。把屏蔽层单端接地后误码率立刻下降一个数量级。接着又在传感器供电端并联了100uF电解电容波形明显干净。这里要强调一个容易被忽略的点长线I2C通信速率和线缆长度的关系不是线性的。线缆长度超过2米与其追求400kHz不如踏踏实实用100kHz然后通过增加重试机制来保证可靠性。温度数据本来就是缓变信号通信慢一点毫无影响但通信断了就是大问题。5. 工程问题排查与避坑记录5.1 常见问题速查表现象可能原因排查方法I2C通信超时上拉电阻过大总线电容过大测波形上升沿减小上拉电阻通信偶发误码线缆屏蔽层悬空、供电干扰屏蔽层单端接地传感器电源加LC滤波温度读数跳变滤波不充分、现场电磁干扰加滑动平均低通滤波必要时降低速率本地温度虚高传感器靠近发热器件检查PCB布局远离功率器件告警反复触发温度在阈值附近波动无滞回固件增加滞回带远程无温度输出地址配置错误、总线死锁示波器看ACK检查A0/A1引脚配置5.2 几条值得记住的实操心得第一不要把PJ85718DM挂在主I2C总线上跟其他高速设备共享。温控器板上可能还有EEPROM、触摸屏控制器它们和温度传感器共用总线时一次大电流通讯就可能在温度信号上打出一个毛刺。我给温度传感器分了独立I2C总线虽然多占两个引脚但调试起来省心太多。第二ALERT引脚的默认极性和你要的触发模式必须对应上。PJ85718DM的ALERT通常低有效如果固件配置成上升沿触发就会完全错过告警事件。这个问题非常隐蔽我踩过一次排查了整整一天。第三STM32F373VC内部温度传感器确实可以做本地温度参考但是它的测量转换需要特定的采样时间而且两个参考值校准点电压和斜率存放在系统存储区不同芯片之间有差异。如果项目对本地温度绝对值要求高我的建议还是外接一颗数字传感器别省这颗传感器的钱。第四滤波不是万能的。低速滤波能让温度曲线平滑但并不能修复一个有问题的硬件设计。如果现场通信误码率很高先解决硬件问题否则固件里的重试和滤波只是把问题往后拖延。最后再说一个细节远程传感器安装的时候传感器探头要尽量接触被测物体表面或者置于气流主流区不能贴在管道保温层外壁上也不能离加热器太近。这些是看起来跟芯片无关、但决定系统精度的环节软件再强也补偿不了传感位置的系统性偏差。这套PJ85718DM配合STM32F373VC的组合测本地和远程温度都够用系统成本也压得住。如果你正在做类似的嵌入式或者HVAC温控项目硬件上多留意长线通信和去耦软件上把滤波和告警做分层基本就能避开我踩过的大部分坑。