PJ85718DM与PIC18F66K40实现本地远程双通道温度采集方案
做暖通空调控制器这些年我接手过不少因为测温点没选好导致整个控制逻辑翻车的项目。最常见的情况就是控制器主板上只有一个板载温度传感器测来测去测的都是主板自己发热之后的温度跟风机盘管出风口的实际温度差了十万八千里。后来在嵌入式设备里做远程测温才算把这个问题真正解决。这里要聊的方案是用 PJ85718DM 配合 PIC18F66K40 这颗 MCU把本地温度和远程温度一起采集、一起处理再通过 UART 或者 RS-485 上送给上位机或者主控面板。这套思路在嵌入式板卡监控和 HVAC 系统里都很实用特别适合那种测温点离主板比较远、又不想铺一堆模拟信号线的场景。1. 为什么“本地温度”和“远程温度”要分开测而不是只测一处很多人一听说测温第一反应就是“MCU 自带 ADC接个 NTC 热敏电阻不就行了吗”。这话对了一半。如果测温点就在主板上、离 MCU 引脚不超过几厘米那 NTC 确实够用。但 HVAC 设备不是这个逻辑典型的场景包括风管机需要测送风温度传感器要装在风管内部离控制主板可能有半米到一两米远。冷水机组要测进出水温度探头要泡在水管里或者贴在管壁外侧。压缩机排气温度属于高温点传感器要固定在压缩机附近而那块区域电磁干扰很重。嵌入式工控板需要同时监控板载芯片温度和机箱内环境温度两个温度点物理位置分离。这些场景有一个共同特点一个测温点在主板上本地另一个在远处远程。如果都用 NTC 加长引线ADC 的参考电压会因为导线压降和电磁干扰变得非常不可靠。而且 NTC 是非线性的换一个测温点就要重新做分压电路、重新校准量产的时候一致性很难保证。用 PJ85718DM 这样的数字温度采集前端配合 PIC18F66K40 做主控逻辑就清晰多了。本地通道负责测控制板自身温度远程通道通过专门设计的传感器探头去测远处的温度点。两个温度值都以数字形式通过 I2C 总线传给 MCU中间没有模拟信号长距离传输抗干扰能力完全不一样。2. 硬件架构PJ85718DM 与 PIC18F66K40 的分工与选型逻辑2.1 PJ85718DM 在系统里扮演的角色按照这颗器件在市面上常见的定位PJ85718DM 本身是一款带 I2C 接口的温度采集前端芯片支持本地温度测量也支持通过外接二极管型探头做远程温度测量。也就是说它天生就是“双通道温度采集”的料专门配套这种一个本地点加一个远程点的应用。远程测温的工作原理这里稍微展开一下。芯片内部有一路恒流源会依次给外部二极管施加两个不同大小的电流然后测量两次正向压降的差值也就是 ΔVBE。因为二极管的正向压降与温度相关但具体绝对值受工艺影响很大而两个电流下的压降差值跟绝对温度呈现线性关系所以芯片可以基于这个差值算出探头的温度。这个数学关系是稳定的不依赖二极管的绝对精度这也是远程测温能用普通二极管当探头的原因。在 HVAC 场景里这个探头可以做成很小的封装贴在管壁上也可以做成金属套管插到风道里成本低、响应快、布线方便。测温点离主板哪怕有个三米五米只要探头线缆屏蔽做得还行温度误差依然能控制在较小的范围内这在模拟方案里很难做到。2.2 PIC18F66K40 为什么适合当这个主控PIC18F66K40 是 64 引脚的 8 位 MCU有 64KB 的 Flash 和 4KB 的 RAM在这个项目里属于“性能够用、成本合理、开发顺手”的选择。我选它主要看中几点第一它有硬件的 I2C 外设。PJ85718DM 走 I2C 通信MCU 这边的 MSSP 模块配置好之后读温度数据就是标准的寄存器读写操作不需要用 GPIO 去模拟时序代码简洁、时序也稳定。第二它有足够的 UART 资源内置两个 EUSART。一个可以拿来跟调试串口通信另一个可以接 RS-485 收发器走 Modbus 之类的现场总线把温度数据上报给集中控制器。第三它支持内部振荡器。HVAC 设备的主板空间有限外部晶振有时候会因为湿度、振动导致起振不稳定用内部振荡器可以省掉一颗外部晶振减少一个故障源。而且这颗 MCU 的内部振荡器精度足够支撑 UART 通信对于这种温度采集类的应用完全够用。第四它的 ADC模块带计算功能可以做简单阈值判断、累加平均等操作虽然本项目温度数值主要由 PJ85718DM 给出但这个 ADC 能力依然可以留着做备用比如读取拨码开关、0-10V 模拟输入之类的辅助功能让主板一板多用。2.3 系统整体框图简单描述一下数据流PJ85718DM 的本地通道和远程通道分别得到两个温度数字量通过 I2C 上报给 PIC18F66K40MCU 做滤波、标定、阈值判断之后把结果通过 UART 输出UART 再经过外部收发器转成 RS-485 信号接入控制总线。同时 MCU 可以把告警信号直接送到指示灯、继电器或者蜂鸣器实现脱机运行。这套结构的好处是传感器相关的模拟部分全部收敛在 PJ85718DM 周边很小的范围内主板上的其余部分都是数字电路整体设计难度大大降低。3. 电路设计远程测温通道的布线与抗干扰硬件方案确定之后真正决定成败的是电路板布局。远程测温通道虽然走的是数字协议但温度探头本质上还是二极管信号幅度只有几百毫伏线缆稍微处理不好读回来的温度就会跳动甚至完全错误。3.1 远程温度探头的选型与连接远程探头最常用的实现方式是用一颗小信号三极管把集电极和基极短接当作二极管来用。这种接法的测温特性比普通开关二极管更接近理想二极管模型因为三极管的 VBE 特性一致性更好。实际选型时不同型号的三极管 VBE 曲线会有差异最好在软件里预留一个偏移修正参数批量校准时把差异“拉回来”。这一点在动手画板子之前就要想清楚。探头接到 PJ85718DM 的远程通道引脚时注意正负极性不能接反否则读出来的温度会完全乱掉。线上串联一个几百欧姆的限流电阻一方面能抑制部分高频毛刺另一方面万一探头短路也不会损坏芯片。3.2 线缆布线与滤波远程探头的走线不要跟 AC 电源线、继电器输出线走同一个线槽这个不用多说。在 HVAC 设备里继电器吸合瞬间的电流冲击和电机启停产生的干扰都会耦合进高阻态的传感线。如果探头线必须经过干扰区建议采用双绞线或者带屏蔽层的线缆并且屏蔽层在主板侧单点接地。芯片端可以预留一颗小电容比如 1nF 的 NP0/C0G 电容接在远程通道的正负引脚之间滤掉射频干扰。但电容也不能加太大否则会拖慢恒流源切换时引脚电压的建立时间导致测温精度变差。我个人的经验是刚开始先不加滤波电容等实际测到干扰再逐步加小容量的电容不要一开始就把电容焊得很大。3.3 电源和去耦设计PJ85718DM 的供电建议直接从 3.3V 轨取并且用一个 100nF 的陶瓷电容加一个 10μF 的电解电容做去耦。如果系统中还有继电器、电机这些大负载那么传感器供电最好经过一个小型的 LC 滤波或者磁珠避免负载切换时电源跌落反映到温度数据上。PIC18F66K40 的供电同样需要去耦每个电源引脚都要放一个 100nF 电容尽量靠近引脚放置。I2C 总线的上拉电阻按常规做法选 4.7kΩ 即可。如果总线上挂了多个设备上拉电阻可以适当调小但前提是总线的总负载电容在允许范围内。I2C 上传的稳定性比速度重要100kHz 的标准模式在这个应用里已经足够了。3.4 本地温度通道的说明PJ85718DM 的本地通道测量的是芯片自身封装附近的温度。在实际应用中这颗芯片如果放在主板热源附近测到的就是主板温升之后的环境温度如果把它单独放置在离热源较远的位置测得的就是更接近环境的温度。这个特性需要结合产品定义去摆放。比如监控机箱环境温度时芯片最好放在进风口附近如果是要监控主板温度就放在功率器件旁边。这里有一个常见的误区本地通道测的是芯片周围温度不是芯片内部结温。如果需要结温得用热阻模型去推算不能直接把本地温度当成结温用。4. 固件实现I2C 采集、数字滤波与标定硬件焊接好之后接下来就是固件。PIC18F66K40 的开发用自带的集成开发环境配合 C 编译器流程很成熟。下面是固件里几个核心模块的设计思路和实现细节。4.1 I2C 初始化与器件探测I2C 初始化代码很简单关键是配置好主模式、时钟速率和地址。PJ85718DM 的具体 I2C 器件地址要参考它的数据手册通常是 7 位地址可能存在地址引脚可以调整 I2C 地址的情况这样同一总线上可以挂多颗芯片分别测不同设备的多点温度。void I2C_Init(void) { // 将 PIC18F66K40 的 MSSP 配置为主模式时钟设为 100kHz // 具体寄存器数值根据实际振荡器频率计算 SSP1CON1 0x28; // 使能 I2C 主机模式 SSP1ADD 0x4F; // 由实际时钟和波特率计算得到 }初始化之后做一次地址扫描。如果总线上的设备没有应答说明焊接或者地址设置有问题这时候不要急着去读数据先把连接问题查清楚。I2C 读温度数据通常分两步先写寄存器地址再连续读两个字节的温度数据。温度数据的格式可能包含符号位和分辨率位具体按照芯片手册中的定义解析成带小数点的摄氏温度。4.2 连续采集与滑动平均温度数据读出来之后不能直接使用因为传感器本身会有量化噪声HVAC 环境里还会有气流波动、压缩机震动带来的读数扰动。我习惯在固件里做一个环形缓冲区取最近八次到十六次的采样做滑动平均。这样既能滤掉高频抖动又不会像低通滤波那样引入明显的滞后。滑动平均的代码结构大致如下#define TEMP_SAMPLES 8 float temp_buffer[TEMP_SAMPLES]; uint8_t temp_index 0; float temp_sum 0.0f; float Filter_AddSample(float new_sample) { temp_sum - temp_buffer[temp_index]; temp_buffer[temp_index] new_sample; temp_sum new_sample; temp_index (temp_index 1) % TEMP_SAMPLES; return temp_sum / TEMP_SAMPLES; }每次轮询周期建议 500ms 到 1s 一次。太快没有意义太慢又会影响告警响应。实际测试中1 秒一个采集周期滑动平均窗口取 8 个点温度显示已经非常稳定了。4.3 异常值剔除滑动平均有一个弱点如果某一次采样因为干扰跳变到离谱的值比如误读了 255 摄氏度整个平均值会被带偏。所以我在做滤波之前会先做一个合理性判断当前采样值与上一次有效值的差值超过设定阈值比如 5 摄氏度时就丢弃这次采样不进入滑动平均缓冲区。这相当于给数据多加了一道“安检门”。温度变化是惯性系统正常情况下一秒内不会有剧烈的跳变所以这个阈值完全能够接受。这一招在排查干扰问题时特别有效很多看起来“测量不准”的问题其实都是个别坏点污染了滤波结果。4.4 标定与偏移修正传感器虽然一致性很好但批量生产的设备总会有个体差异。我在固件里预留了四个标定参数分别对应本地温度偏移、远程温度偏移、远程温度斜率修正和远程通道噪声阈值。这四个参数存放在 Flash 的一个独立区域产线上校准时通过上位机写入不需要重新烧录固件。标定流程也很直接把设备放在恒温环境中参考标准温度计读数用“实际值减去读数值”得到偏移量写入 Flash。如果要求更高可以做两点标定用两个不同的温度点算出一个斜率和偏移从而修正传感器响应曲线的细微偏差。HVAC 设备一般±0.5℃的精度就够用单点偏移校准通常已经能满足要求。5. 数据上送与告警面向 HVAC 的通信协议设计温度采集和处理完成之后数据必须能够传给上层。在 HVAC 系统里最常用的方式是通过 RS-485 总线把温度值上报给集中控制器同时本地用数码管或者液晶屏显示。这里重点说一下 UART 数据帧的设计和告警阈值逻辑。5.1 UART 数据帧格式PIC18F66K40 的 UART 输出可以直接接 RS-485 收发器。数据帧格式不需要太复杂但一定要包含帧头、设备地址、数据长度、数据区和校验字段。我常用的帧格式大致如下帧头(0xA5) 地址(1字节) 命令(1字节) 温度数据(4字节) 状态字(1字节) CRC(2字节)温度数据我用大端方式传分别存放本地温度和远程温度各占两个字节整数部分和小数部分分开这样解析端处理起来比较直观。CRC 用常见的 16 位校验不追求高强度只要能把传输错误兜住就行。5.2 告警阈值与滞回HVAC 设备里告警不能做成“一越界就报警一恢复就复位”那样在临界点附近会导致继电器反复吸合释放非常烦人。正确做法是设置滞回阈值。比如高温告警设定值为 60℃恢复值为 55℃温度升到 60℃以上才触发告警降回 55℃以下才解除告警。这 5℃的差值就是滞回区间能大幅减少临界抖动。#define HIGH_TEMP_ALARM 60.0f #define HIGH_TEMP_RESET 55.0f void ProcessAlarm(float remote_temp) { static uint8_t alarm_active 0; if (!alarm_active remote_temp HIGH_TEMP_ALARM) { alarm_active 1; SetRelay(1); } else if (alarm_active remote_temp HIGH_TEMP_RESET) { alarm_active 0; SetRelay(0); } }同样的逻辑也适用于低温告警。本地温度和远程温度可以各设一组阈值互不干扰。5.3 本地显示与扩展接口除了上送数据设备面板上通常还需要本地显示。PIC18F66K40 的资源完全够用可以用数码管显示当前温度也可以用带 I2C 接口的液晶屏接在第二个 I2C 总线上。显示内容可以选择本地温度和远程温度循环切换也可以在告警触发时强制显示告警温度点。扩展接口方面这颗 MCU 还有剩余的 GPIO 和定时器可以将来扩展成按键输入、风扇调速 PWM 输出之类。硬件设计上把空余引脚引到排针产品迭代时不用改板子就能加功能。6. 实测调整与常见问题排查链路方案跑通是一回事跑得稳定是另一回事。这里把我在实际调试中遇到的几个典型问题列出来这些问题几乎每个做过这个方案的人都会碰到。6.1 排查问题一I2C 读不到 ACK现象是单片机扫描地址时总线无响应读回来的数据全是 FF。排查顺序我建议按下面的链路走第一步用示波器看 SCL 和 SDA 波形确认有没有波形变化。如果 SCL 一直拉高或者一直拉低说明总线被某个设备锁死了。这时候把总线上所有设备断开只留 MCU 和传感器问题大概率就能定位。第二步检查上拉电阻。I2C 是开漏输出没有上拉电阻总线就拉不起来上拉电阻太大总线电容又会导致沿变缓严重时高电平识别不了。3.3V 系统配 4.7kΩ 是最稳的起点。第三步检查器件地址。地址引脚如果被悬空或者接错电平地址就会算错。最直接的办法是对着数据手册的地址表把地址引脚的电平逐一确认一遍再用读地址加 1 的方式做一次寻址测试。6.2 排查问题二远程温度读数偏大或者偏小这个现象通常是三个原因。第一二极管型号和芯片内置的运算参数不匹配导致系统误差。解决方法是做软件偏移修正或者换用芯片厂家推荐的探头型号。第二线缆过长导致压降增加这个误差是可重复的系统误差同样可以通过偏移修正。第三远程探头附近有热源干扰比如探头贴在压缩机外壳上测到的其实是外壳温度而不是空气温度这个不是电路问题是安装问题。6.3 排查问题三温度读数跳动如果本地温度很稳只有远程温度在跳重点排查远程通道的走线和滤波。很多情况是滤波电容加得不够或者线缆屏蔽层没有接好。我一般先把屏蔽层单端接地再在芯片端逐步增加电容直到跳动量降到可以接受的范围。如果本地和远程都跳就要怀疑电源。拿示波器看供电轨是不是有周期性跌落尤其是继电器吸合瞬间。如果电源跌落超过 100mV就很可能会通过芯片内部的模拟电路影响测温结果。这时候在传感器供电前加磁珠或 LC 滤波通常能明显改善。6.4 排查问题四上电后前几秒读数为异常值有些芯片上电瞬间内部 ADC 或者 VBE 测量电路还在建立过程中此时读取温度会得到无效数据。固件里一定要做初始化延时比如上电后等 200ms 再开始首次采集并且丢弃前几次采样结果。别小看这个步骤没有这段延时系统每次启动都可能记录到一次虚假告警。6.5 我自己的处理习惯从项目角度我最推荐的做法是把调试接口留足。主板上预留一个 4 针调试口引出 MCU 的调试 UART 和 I2C 信号线这样在整机调试时可以直接挂逻辑分析仪看不经过协议栈转换的原始 I2C 帧定位问题比只盯着最终温度值高效得多。PI85718DM 温度数据异常时我能一眼看出是传感器芯片读出来的原始值就有问题还是 MCU 软件解析处理出了偏差。温度监测在嵌入式系统里看起来是件小事但它影响的是整套控制逻辑的判断依据。一个稳定的、可信赖的温度数据源才是后面 PID 调节、压缩机启停控制、故障保护的前提。方案做完之后再回头看最开始的 NTC 方案你会发现在复杂应用场景里数字传感器搭配合适的主控芯片才是更省心、更可靠的一条路。