资讯详情

嵌入式测温双通道方案:PIC18F87J50+PJ85718DM区分本地与远程温度

📅 2026/10/22 6:38:46 | 华诺云谱 👁 阅读
嵌入式测温双通道方案:PIC18F87J50+PJ85718DM区分本地与远程温度
做嵌入式测温最怕的不是读不到数而是读到的数根本不是你想要的温度。我在做某风机盘管控制器的时候被现场调试卡了整整一天控制算法明明没有问题机组却总是把加热器误判成过热保护。后来把面板拆开才发现测控板上那颗传感器测到的根本不是风道里的回风温度而是板载芯片自己散发出来的热量。这个问题很有代表性很多工程师习惯把“本地温度”当成“被控温度”用或者反过来把外部探头的读数直接当成“板卡健康度”来监控两头都错位。我当时换了一个思路用一颗PIC18F87J50做主控外挂一颗PJ85718DM数字温度传感器在同一颗芯片上同时取本地温度和远程探针温度。一个通道看板卡自身的健康状态另一个通道专门盯风道、水管的实际温度这样既不会把芯片发热误判成环境温度又能在传感器断线时立刻识别出来。这套方案从硬件到软件都不复杂但里面藏着几个容易翻车的细节。下面我把完整链路拆开讲一遍包括为什么选这两颗器件、I2C读时序怎么做、HVAC现场怎么抗干扰、以及最后怎么把两路温度安全地送到上位机。1. 本地温度与远程温度在一个系统里分别解决什么问题1.1 先从一次“测出来很准但控制失效”的故障说起我常看到一种典型设计MCU板上放一颗温度传感器直接读ADC然后拿去控制风机的转速或者加热器的启停。从单一测量点来看数据确实没毛病芯片手册给的精度也写得清清楚楚但整个系统就是运行不正常。原因出在“测温对象”和“控制对象”不是同一回事。板载传感器感受到的是PCB温度而PCB温度是MCU功耗、周围功率器件发热、机箱散热条件共同作用的结果。它和风道里的回风温度、冷水管里的出水温度之间存在一个不确定的偏差而且这个偏差会随着负载变化。只要功率管一发热板温立刻上去控制系统就会误以为环境温度飙升逻辑自然乱了。1.2 远程温度才是真正的被控对象在HVAC场景里真正值得采集的是风道温度、回风温度、冷冻水供水/回水温度这类远端测点。它们距离控制板少说也有一两米有时候长达十几米。这种测量点必须把传感器探头延伸到物理测点附近而不是把导线拉长去“感受”沿途温度。PJ85718DM这一类芯片刚好解决这个问题它内部自带一个片内测温通道同时留出了外接测温元件的输入引脚。两个通道在内部ADC完成转换通过同一个数字接口输出这样“本地”——芯片自身的结温或板温——和“远程”——探头所在的测点温度——就都被完整地采集下来了。1.3 两种数据的不同用途我把两路数据的用途分得很清楚数据来源本质典型用途外接探头故障时的表现本地温度通道半导体结温跟随PCB发热板卡过热保护、器件寿命估算、程序降频依据通道本身一般不会失效异常时偏差大远程温度通道外接半导体/热敏探头所在点温度风道/水管/回风温度采集参与PID控制断线通常表现为读数极低或极高容易被识别这个区分不要只在文档里写代码里也要分开处理。本地温度用于保护动作远程温度用于控制逻辑两者不混用。这样才能避免我把控制板放在机柜里时柜内温度稍微一高整个空调系统就“谎报”环境温度的情况。2. 硬件连线之前先想清楚PIC18F87J50和PJ85718DM怎么配合2.1 引脚分配与I2C上拉电阻的选择PIC18F87J50自带I2C/SPI串行模块这在选型上省了很多事。PJ85718DM对外输出数字接口把I2C的SCL、SDA接到MCU的MSSP对应引脚即可。需要注意I2C总线不能靠MCU内部弱上拉硬扛必须外加电阻否则速率一高波形就开始变形。上拉电阻的取值有些讲究。我习惯在3.3V系统里先贴4.7kΩ如果总线速度用到400 kHz且线上挂的从机数量不多再降到2.2kΩ。电阻太小会让低电平下拉过载电阻太大会导致上升沿变缓、数据位错乱。手边没有示波器时可以在I2C时钟线上并联一个几百皮法的电容做简单滤波也可以用下面这种常规配置参数推荐值上拉电阻4.7kΩ / 2.2kΩSDA/SCL对地电容100pF~330pF传感器供电3.3V与MCU共地必须单点可靠接地关键是SDA、SCL这两条线不要走得太远也不要和AC220V的强电线扎在一起。PJ85718DM如果像常见数字温度芯片一样采用两线制通信一旦总线线上耦合了干扰整个温度读数都会跳。2.2 供电、去耦和远端探头接线给PJ85718DM供电我建议直接从PIC18F87J50的同一组3.3V电源输出取中间串一只小磁珠或者10Ω电阻旁边放一个0.1μF陶瓷电容加一个10μF电解电容。很多不稳定问题其实不是芯片算法问题而是电源纹波直接在ADC结果里体现出来了。远程探头那边的走线尤其要注意。PJ85718DM外接测温元件时探头线属于高阻抗信号线不要和继电器输出线、风机调速线平行走线。如果现场必须长距离走线优先把探头线做成双绞线并在芯片输入引脚附近对地并一只几百皮法的滤波电容。这样做付出的成本很低但效果立竿见影。2.3 为什么我不直接用热敏电阻ADC的方案有人可能会问既然PIC18F87J50自带ADC那为什么不直接接个NTC热敏电阻再接个分压电阻读ADC我在前面几个项目里恰恰是从NTC方案转过来的。NTC方案不是不能用但它有几个麻烦热敏电阻阻值-温度曲线是非线性的需要表格或公式换算分压电路会因为电源电压波动产生误差长线引入的压降和噪声很难定量估算。PJ85718DM这类数字温度传感器把基准、ADC和线性化都做到芯片里了MCU只要通过接口读寄存器精度和稳定性反而更好管。算上MCU内部的线性化开销数字方案在HVAC这种环境里更省心。3. 完整采集链路从启动转换到拿到可用的温度值3.1 寄存器与转换时序的总体认识PJ85718DM的具体寄存器地址可能因批次和厂商略有差异但数字温度传感器的寄存器框架基本一致一个配置寄存器决定分辨率、转换模式和工作状态一个或多个温度寄存器存放转换结果有些型号还有状态寄存器或报警寄存器。我在项目中把配置寄存器设置为连续转换模式分辨率设置为12位左右典型转换时间在几十到两百毫秒这个范围。启动后不立刻去读寄存器而是先等待转换结束因为刚上电或刚写完配置就读拿到的往往是上一次或半转换的旧值这个细节伤过很多人。下面这段是典型的I2C读取骨架Mask掉了具体寄存器号重点看时序习惯uint8_t read_temp16(uint8_t reg) { uint8_t buf[2] {0, 0}; i2c_start(); i2c_write(PJ85718_ADDR_WR); // 写地址 i2c_write(reg); // 目标寄存器 i2c_stop(); i2c_start(); i2c_write(PJ85718_ADDR_RD); // 读地址 buf[0] i2c_read(1); // 读高字节回应答 buf[1] i2c_read(0); // 读低字节回非应答 i2c_stop(); return (buf[0] 8) | buf[1]; }3.2 数据格式与温度换算温度寄存器的格式通常会采用二进制补码。比如某款芯片约定高位字节的bit15到bit7是符号和整数位bit6到bit0是小数位低位字节再扩展更高分辨率。分辨率12位时数据往往左对齐最低有效位代表0.0625℃。换算公式很简单float raw_to_celsius(uint16_t raw) { int16_t signed_raw (int16_t)raw; return signed_raw * 0.0625f; }如果读回来是0xFFFF别急着算浮点数先判定是否为断线或故障数据。很多HVAC控制器出现“-200℃”这种离谱数值都是因为把异常原始数据处理成温度又送去参与运算了。3.3 滑动平均和中值滤波怎么选HVAC现场最大的干扰源是压缩机和风机启停。温度本身是慢变量我不建议直接拿单次采样值参与控制。我的做法是分两级先做数据合法性判断再做滤波。中值滤波适合剔除个别尖峰。比如连续取5次排序后取中间值就算某一次因为电磁干扰跳成-50℃中值结果也不会被拉飞。滑动平均适合抑制随机噪声但对尖峰反应迟钝。如果系统对温度变化不敏感我更推荐“中值简单平均”的组合效果非常稳。#define TEMP_BUF_SIZE 5 uint16_t temp_history[TEMP_BUF_SIZE]; uint8_t temp_idx 0; float filtered_temperature(uint16_t cur_raw) { temp_history[temp_idx] cur_raw; if (temp_idx TEMP_BUF_SIZE) temp_idx 0; // 拷贝并排序取中值 uint16_t sort_buf[TEMP_BUF_SIZE]; for (int i 0; i TEMP_BUF_SIZE; i) sort_buf[i] temp_history[i]; for (int i 1; i TEMP_BUF_SIZE; i) { uint16_t key sort_buf[i]; int j i - 1; while (j 0 sort_buf[j] key) { sort_buf[j 1] sort_buf[j]; j--; } sort_buf[j 1] key; } return raw_to_celsius(sort_buf[TEMP_BUF_SIZE / 2]); }注意排序操作在8位MCU上稍显浪费但对温度这种低频采集来说完全可接受不需要做什么高深优化。3.4 校准出厂准不代表系统准数字传感器出厂精度再高装到设备里还会有系统级偏差主要来源是探头安装位置和导热介质。传感器探头如果贴在风道外壳表面而不是插进气流当中测得的就是壳体温度至少偏差几度。这不是芯片的问题是安装的物理问题。我在程序中预留了一组偏移量本地温度偏移和远程温度偏移。用高精度水银温度计或已校准的参考探头实测后把这些偏移写进EEPROM。实际换算公式就从raw*0.0625变成raw*0.0625 offset不要小看这一步它能让整机标定变得特别省时间。4. 在HVAC现场环境里采样时机和走线抗干扰怎么处理4.1 把采样时机和电网干扰错开HVAC系统里大功率器件启停瞬间供电线上会产生明显的浪涌和跌落。如果温度转换刚好发生在压缩机触点弹跳的那几百毫秒内高阻抗探头线很容易感应到噪声转换结果会异常。我的处理方式很保守不从软件层面去跟电网“抢时间”而是在主循环里规定温度采样只发生在继电器动作后至少50ms。也就是先把压缩机/风机的控制命令执行完等触点稳定后再去启动一次温度转换。温度量变化本来就很慢晚几十毫秒完全无感但稳定性显著提高。4.2 探头的电气隔离与防雷击设计HVAC设备经常装在屋顶或外墙雷雨季节探头线很容易感应出过电压。PJ85718DM这类芯片的输入引脚耐压能力有限不能直接暴露在外面。我一般会在探头走线的入口处加一个串联电阻比如1kΩ在芯片引脚和地之间并联一个小电容。如果设备有接地条件还可以加一支双向TVS管。这样做不会影响正常测温响应速度但能拦住大部分静电和感应浪涌。4.3 踩过的锅断线读数把我骗了两天这个项目里最让我印象深刻的故障现象是系统偶发报出-40℃低温然后控制逻辑以为风道温度过低直接关闭了加热器。最开始我一直怀疑探头坏了换了好几只探头还是同样的问题。后来抓了几天数据才发现PJ85718DM外接探头断线时寄存器读出来是0xFFFF换算成温度正好是负几十度附近。MCU完全不知道探头已经没了还像正常数据一样参与控制。从那以后我在代码里加了一条硬规则原始值大于某个阈值或等于0xFFFF一律视为无效点直接把对应通道的故障标志置位绝不让异常值进入控制环路。这个处理比任何滤波都重要。5. 把两路温度变成上位机能认的数据常做的是Modbus和串口映射5.1 从传感器寄存器到Modbus寄存器表PIC18F87J50自带UART和USB模块在做嵌入式设备时我通常会在这颗芯片上构建一个简单的主从协议。如果是工业HVAC设备最常见的就是Modbus RTU。温度数据在传感器端是16位Modbus寄存器也正好是16位直接映射即可。我建议把本地温度和远程温度放在连续的寄存器里再放一个状态寄存器表示测量值是否有效。Modbus寄存器地址数据类型内容0x0000uint16只读本地温度单位0.01℃0x0001uint16只读远程温度单位0.01℃0x0002uint16只读bit0本地有效bit1远程有效bit2通信故障0x0010uint16读写本地温度报警上限0x0011uint16读写远程温度报警上限主控芯片在后台定时更新这组寄存器上位机通过串口或总线的功能码来读取这样把“传感器采集”和“人机界面”两个任务拆得干干净净。5.2 断线、报警与自动恢复策略有了状态寄存器控制逻辑的判断就可以更严格。每次读取到无效温度时不要直接清掉报警状态而是维持一个连续故障计数。只有连续读到3次有效数据才能把故障位清除防止触点抖动导致报警反复闪烁。如果远程探头长时间失效我会让MCU输出一个独立的故障干接点信号提醒现场维护人员检查探头接线。这个做法在HVAC工程项目里很实用不然等到温度失控了才发现探头掉线损失就大了。5.3 串口和USB的实际选择PIC18F87J50内部有USB模块很多做调试的人喜欢直接USB连上位机。但到了工业现场USB线长距离传输和电气隔离都比较麻烦我更推荐用UART外接RS485收发器走两根线就能覆盖几十米甚至上百米。使用RS485时记得加上终端匹配电阻和偏置电阻。如果总线上只有一个主站加一个从站终端电阻放在从站端即可如果总线采用菊花链接多个设备终端电阻要放在物理最远端。温度数据虽然慢但通信波形不对一样会导致帧错误。6. 几件容易被忽略的事给准备照着搭这套系统的人提个醒6.1 看门狗要喂但要分主从两级PIC18F87J50的看门狗定时器要打开这是底线。但如果I2C总线上PJ85718DM因为异常进入锁死状态MCU光喂自己的狗没用。我从调试中发现I2C死锁最常见的是SDA被从机拉低。遇到这种情况比较稳妥的处理是先把总线释放再给传感器一个硬件复位机会。我的做法是把PJ85718DM的电源引脚做成可由MCU的一根I/O口控制的低边开关一旦发现连续两次读取超时就切断传感器电源100ms再恢复。这个“断电重启”动作虽然粗暴但确实能解决大部分数字传感器锁死问题。6.2 校准点的选取决定整机精度不要只在校准一次后就觉得万事大吉。至少要在两个温度点做标定比如0℃和50℃。分别记录实测温度和芯片读数算出偏移和增益系数把两个参数一起写进EEPROM。如果现场不方便准备恒温源可以用冰水混合物和热水浴做粗略校准比根本不校准强太多。校准表建议做成这样存到MCU的EEPROM里typedef struct { int16_t offset_local; // 本地通道偏移单位0.0625℃ int16_t gain_local; // 本地通道增益修正默认256 int16_t offset_remote; // 远程通道偏移 int16_t gain_remote; // 远程通道增益修正 uint16_t magic; // 识别数据是否有效 } calib_t;读取后先校验magic字段如果发现EEPROM数据被清空就回退到默认配置避免用全零参数算出一堆无意义的温度。6.3 显示层和控制层之间要做差分判断最后提醒一个容易忽略的点不要只看绝对温度要会看差值。本地温度代表板子温度远程温度代表现场温度两者之差在某一个稳定工况下是相对固定的。如果实际读数里这个差值突然变得很大往往说明传感器或者探头线已经不在正常状态了。我后来的项目里都会在代码里加一个“温差合理性判断”|本地温度-远程温度|超过某个阈值比如15℃就置一个提示位。这个看似简单的逻辑救回过好几次因为探头从风道里掉出来导致的误控制事故。真正做完整个项目后我的体会是温度监测并不难难点是让每一度都用在正确的位置上。本地温度别当环境温度用远程温度别被断线骗还要留好一个顺手可靠的通信出口。PIC18F87J50加上PJ85718DM这套组合刚好能在成本、可靠性和开发速度之间找到一个让人满意的平衡点。如果你也在做HVAC控制板不妨先把第一路温度接到MCU旁边把第二路探头疼到风道深处跑几天数据看看大概率会比只看一个点稳得多。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑