2026/10/22 6:41:49

HVAC温度监测系统:PIC18F87J11+PJ85718DM方案详解

HVAC温度监测系统:PIC18F87J11+PJ85718DM方案详解 HVAC和嵌入式监控打了好几年交道项目里最容易被低估的一个环节就是温度监测。看起来不就是读个温度吗可一旦涉及本地多路采集、远程上报、联动控制、现场抗干扰整个复杂度就起来了。这次这套方案核心是两片东西PJ85718DM 数字温度传感器和 PIC18F87J11 这颗自带以太网控制器的单片机。PJ85718DM 负责把温度数字化PIC18F87J11 负责采集、滤波、判断阈值再把温度数据通过网口送到远程监控端。适合新风机、空调箱、机房环境、冷冻水系统这类暖通场景也适合一般的嵌入式设备温度监测。如果你正在搭类似的系统这篇文章从选型、电路、固件到踩坑可以直接当参考。1. 方案整体设计与选型思路1.1 温度监测系统的分层架构做温度监测第一件事不是写代码而是把系统的层次拆清楚。一个完整的本地与远程温度监测系统我习惯分成四层感知层、采集层、传输层、应用层。感知层是温度传感器本身解决“温度怎么变成电信号”采集层是单片机解决“信号怎么变成数字、怎么处理”传输层解决“数据怎么送到远端”有有线网络就用以太网没有就走串口接4G或Wi-Fi透传应用层是监控室的上位机、组态软件或者云平台解决“数据怎么展示、超温怎么告警”。标题里的 PJ85718DM 和 PIC18F87J11 正好落在前两层而 PIC18F87J11 独特的地方在于它自带了以太网控制器也就是说采集层干完活可以直接接传输层中间不需要再外挂一颗网络芯片。这是这套方案能做成单板的原因。1.2 为什么选 PJ85718DM 而不是 NTC 方案入行久的人可能有印象早些年做温度监测低成本首选几乎都是NTC热敏电阻加单片机ADC。NTC方案不能说不能用但在批量项目里问题非常多每颗NTC的阻温曲线不完全一致需要逐点标定ADC基准电压稍有波动读数和真实温度就差一截长期运行后还有漂移。如果把传感器放在冷冻水管、风管这些不方便重新拆装的现场后期维护成本相当高。PJ85718DM这类I2C接口数字温度传感器直接把温度到数字的转换都在传感器内部完成出厂时已经校准过。以我自己用的这颗为例测温范围能做到-55°C到125°C12位分辨率下温度分辨率是0.0625°C典型精度在-10°C到85°C范围内是±0.5°C。对暖通场景来说这个精度和分辨率完全够用。更关键的是I2C接口只要两根线传感器有3个地址引脚一条总线上最多能挂8个这对多点温度监测太合适了。一颗NTC就要占一路ADC通道和一路地线8个点在布板上会非常痛苦。1.3 PIC18F87J11 在这套方案里承担了什么有人可能会问用个8位单片机读I2C传感器随便一颗芯片都行为什么非选PIC18F87J11。核心原因就是它的以太网控制器。这颗芯片内部集成了10M以太网的MAC和PHY也就是说想实现远程温度上报直接在硬件上接一个带隔离变压器的RJ45座子就行不必再买W5100、ENC28J60之类的外部网络芯片。对整个物料清单来说省的不只是一颗芯片的钱还省了PCB面积和调试工作量。除了网口PIC18F87J11的周边资源也够用两个MSSP模块可以接I2C或SPI两个EUSART串口可以接RS-485或4G模块还有DMA、比较器、PWM和12位ADC。这意味着同一个硬件平台不仅能做温度监测后续接压力传感器、湿度传感器、控制风机转速和阀门开度都有对应外设。所以我说它是那种“能往上长”的方案。这个项目用下来它的选型逻辑并不是性能最强而是外围匹配度高、扩展余地大一颗芯片就把采集和远程通信都解决了。2. 硬件电路连接与关键参数设计2.1 PJ85718DM 的接口连接与地址规划PJ85718DM这类I2C接口的温度传感器引脚数不多。供电引脚VDD、地GND、I2C时钟SCL、数据SDA还有3个地址引脚A2、A1、A0以及一个可选的过温报警输出OS。上拉电阻是必须的SCL和SDA各接一颗阻值选4.7kΩ还是2.2kΩ取决于总线长度和上拉电平。我自己的经验是传感器到单片机距离在10厘米以内、总线上挂4到5颗的话4.7kΩ没问题要是传感器被引到现场远端、线缆有1米以上就换2.2kΩ同时总线速率降到100kHz这样不容易被线缆电容拖垮。地址规划这点特别重要。假设传感器3个地址引脚都接地7位地址就是0x48如果把A0接VDD地址变成0x49。8个传感器的地址规划我一般做成张表直接固化在固件里也写在项目文档里。下面是我在某跨平台系统里用过的一组规划传感器序号A2 A1 A0I2C 7位地址位置说明1号0000x48冷冻水供水温度2号0010x49冷冻水回水温度3号0100x4A送风温度4号0110x4B回风温度5号1000x4C主机房环境温度这里有个隐藏问题I2C地址冲突。有些传感器型号出厂默认地址都是0x48如果你只挂一颗什么都不用管挂多颗就要把A0到A2组合区分开而且必须保证每颗芯片的地址引脚焊接正确。我遇到过现场有一批板子的A2焊盘虚焊导致两传感器地址一样总线上一发地址命令就乱套。后续批量生产时地址引脚相关的焊盘我会要求生产端做AOI检测避免这个问题。2.2 PIC18F87J11 的以太网接口设计远程温度上报靠的是PIC18F87J11的内置以太网控制器。硬件上要注意虽然网络控制器在芯片内部物理层信号仍然需要一颗网络变压器来隔离然后才能接到RJ45座子。这颗变压器可以用带网络滤波功能的RJ45集成座插座内部直接含变压器这样外围器件少很多也可以用分立变压器加普通RJ45座。分立方案屏蔽和EMC更好处理集成方案省事根据项目实际来定。网络变压器的中心抽头处理是一个容易出错的地方。不同厂商的变压器中心抽头可能要求接电源或者接电容到地如果没有按推荐电路接典型表现是网口指示灯正常、协商也正常但数据通信丢包严重或者一收发大包就断。这类问题示波器看不明显网络分析仪又不常用排查起来很折磨人。我的做法是每个项目的以太网变压器选型确定后第一版PCB就严格按数据手册里的参考电路画不自己做任何改动。这是最稳妥的。内置PHY接出来的信号是差分对TDP/TDN、RDP/RDN四种。PCB布线时这两对差分线要做等长处理长度差控制在5mm以内尽量少打过孔。很多工程师觉得10M以太网频率不高随便拉线就行但我实测过走线太差会导致链路在短网线时正常、换长网线或者经过网络面板后就频繁丢包。差分对做等长、包地、远离晶振和电源纹波大的区域这几条做到位网络稳定性会有质的提升。2.3 电源与IO保护电路HVAC现场和普通办公环境最大的区别是干扰源多。变频器、接触器、风机启停都会造成电源跌落和群脉冲干扰。整个系统的供电我建议外部先接一个隔离DC-DC把24V或12V现场电源转成5V再用LDO降到3.3V给PIC18F87J11和传感器供电。传感器VDD如果允许尽量用同一个3.3V域避免不同电源域之间需要电平转换增加故障点。PIC18F87J11是3.3V器件传感器工作电压如果是3.3V到5.5V需要确认接口电平兼容。我在某些5V供电的传感器型号上吃过亏直接接了3.3V单片机结果传感器输出的高电平接近5V把单片机的IO引脚打坏。解决方案是要么选3.3V供电版本要么SDA/SCL线上加电平转换芯片或者用MOSFET电平转换电路。标题里的PJ85718DM如果按3.3V供电设计接口电平就是匹配的但采购时必须和供应商确认供货版本避免混料。2.4 传感器远距离引线的防干扰处理本地温度监测传感器不一定都装在主控板上有些要放在风管里、水管表面、室外机旁边这就涉及传感器引线。PJ85718DM的I2C总线在长距离传输时抗干扰能力有限如果引线超过2米就不建议直接用普通排线。我在某冷库项目里用屏蔽双绞线延长I2CSCL和SDA各走一根双绞线对屏蔽层单端接地实测能稳定跑3米再长就要用I2C总线延长芯片或者改用单总线方案。传感器如果贴在金属管道上要注意传感器封装和管壁之间的绝缘。金属管壁可能会带来地环路或者热传导差异导致读数异常。安装时用导热硅胶加绝缘垫片既能保证热耦合又避免电气连接。另外传感器尽量避开电磁阀、变频器强电走线区域实在避不开就加磁环这个对HVAC现场特别有效。3. 固件实现与关键代码解析3.1 I2C 驱动初始化与寄存器配置固件的第一步是初始化I2C模块把PIC18F87J11的MSSP模块配成主模式。PIC18F87J11有两个MSSP模块我这里以MSSP1为例。配置要点是引脚设为输入模式、使能I2C、设置主模式、计算波特率。假设系统时钟16MHz目标I2C速率100kHzSSP1ADD就等于16MHz除以4再除以100kHz减1算出来是39。#include xc.h #define I2C_CLOCK 100000UL #define FOSC 16000000UL void I2C1_Init(void) { // 引脚由TRIS寄存器配置为输入具体引脚号以原理图为准 // 使能I2C主模式 SSP1CON1 0x28; // 0b00101000: 使能SSP, I2C主模式 SSP1CON1bits.SSPEN 1; // 再次确认使能 SSP1ADD ((FOSC / 4UL) / I2C_CLOCK) - 1UL; // 16MHz/4/100kHz - 1 39 }这里要提醒一下I2C时钟源取的是“系统时钟直接分频”系统时钟变成48MHz时SSP1ADD的计算结果会变成119还在寄存器允许范围内但如果超过127就要降速率或者换时钟方案。配置时最好把I2C速率定义成宏方便后续调整。启动和停止条件在主模式下是通过操作SSP1CON2寄存器实现的。发送启动条件后必须等待硬件清除对应标志位再继续下一步操作否则后续字节会丢失。这也是I2C驱动最常见的时序坑连续操作时缺少等待导致偶发通信失败。void I2C1_Start(void) { SSP1CON2bits.SEN 1; // 发启动条件 while(SSP1CON2bits.SEN); // 等待完成 } void I2C1_Stop(void) { SSP1CON2bits.PEN 1; // 发停止条件 while(SSP1CON2bits.PEN); // 等待完成 } unsigned char I2C1_WriteByte(unsigned char data) { SSP1BUF data; while(!SSP1STATbits.BF); // 等待发送完成 return SSP1CON2bits.ACKSTAT; // 0表示从机应答1表示无应答 } unsigned char I2C1_ReadByte(unsigned char ack) { SSP1CON2bits.RCEN 1; // 使能接收 while(!SSP1STATbits.BF); // 等待接收完成 SSP1CON2bits.ACKDT ack; // 0ACK, 1NACK SSP1CON2bits.ACKEN 1; // 发送应答位 while(SSP1CON2bits.ACKEN); return SSP1BUF; }寄存器配置方面PJ85718DM这类温度传感器常用寄存器是指针寄存器、温度寄存器、配置寄存器、Tos上限寄存器和Thyst下限寄存器。读温度前先把指针写到温度寄存器地址然后发重复起始条件再发读命令就能读出两个字节的温度数据。如果你的PJ85718DM寄存器布局不是这套以手册为准但I2C操作流程是相通的。3.2 温度读取、数据转换与软件滤波以传感器地址0x48为例读取温度的函数流程是启动、写从机地址加写位、写温度寄存器指针、重复启动、写从机地址加读位、读高字节、读低字节、停止。两个字节合成16位数据后右移4位就是12位有效温度值。这个值乘以0.0625就是实际温度值但我更倾向于在固件里直接用放大16倍的定点数处理也就是“温度码 实际温度 × 16”这样避免浮点运算带来的代码体积和性能开销。#define TEMP_ADDR 0x48 int16_t readTemperature(uint8_t addr) { int16_t raw; I2C1_Start(); I2C1_WriteByte((addr 1) | 0); // 从机地址 写 I2C1_WriteByte(0x00); // 选择温度寄存器 I2C1_Start(); // 重复起始 I2C1_WriteByte((addr 1) | 1); // 从机地址 读 uint8_t hi I2C1_ReadByte(0); // 高字节返回ACK uint8_t lo I2C1_ReadByte(1); // 低字节返回NACK I2C1_Stop(); raw (int16_t)((hi 8) | lo); return (raw 4); // 12位有效数据 }温度读取之后不要直接拿去显示或者上报原始读数里多少会带一点噪声尤其在HVAC现场。我常用两级滤波先做5次采样去最大最小取中间值再做滑动平均。中值滤波能干掉尖峰滑动平均能平缓波动。具体实现时5次采样间隔50毫秒中值结果进入长度为8的滑动窗口窗口平均值作为最终输出。这套组合对风机气流波动、电磁干扰引起的瞬间跳变非常有效。滤波还有个隐蔽的好处减少系统告警误报。如果直接用原始读数做阈值判断可能因为一个噪声尖峰触发高温报警。加了滤波温度变化趋势变得稳定告警阈值判断就可靠很多。当然代价是响应速度变慢但在暖通这种热惯性很大的场景里响应慢一点完全无所谓监测的是趋势而不是瞬间值。3.3 阈值判断与过温联动逻辑PJ85718DM硬件上如果能支持Tos上限和Thyst下限我建议把阈值写入传感器让传感器硬件输出过温报警信号而不光靠单片机软件轮询。这样即使单片机死机过温告警仍然能通过硬件引脚触发继电器或者蜂鸣器可靠性高一个等级。写入Tos和Thyst的流程与读温度类似只是把指针地址分别指向对应寄存器。以12位格式为例假设要设置Tos为85°C温度码就是85乘以16等于1360左移4位变成0x5500注意只有12位有效高4位是符号扩展位。写入时先写高字节再写低字节。这套计算方式只要做过一次后面改阈值就是改一个宏定义的事。软件侧我也保留阈值判断作用不是做保护而是改变远程上报的状态字。比如把温度分为正常、偏高、超限三级远程监控端收到的不只是温度值还有设备健康状态这样监控大屏不用每条数据都做二次计算直接显示状态就行。状态字定义成位标志将来如果增加湿度、压力等监测项扩展起来也比较方便。3.4 远程上报协议与主循环框架远程上报我用的是最简单的自定义TCP协议设备主动连接到监控服务器指定端口建立TCP长连接周期性上报文本帧。为什么不用HTTP或Modbus TCPHTTP请求头冗余太多每次都要解析Modbus TCP功能强大但应用层写起来较繁琐不适合快速交付。自定义帧格式干脆直接调试时用串口助手或者网络调试工具就能看到明文数据。帧格式这样定义 T:设备编号:传感器序号:温度值:状态码:校验换行举例 T:01:03:2450:2:F5温度值用整数表示实际温度的16倍2450表示2450除以16等于153.125十进制显示就是153.1°C但HVAC通常不会到这么高这个只是示例。状态码0表示正常、1表示偏高、2表示超限。末尾F5是前面所有字符的异或校验和。这个校验对防偶尔的粘包、断包很有用远程端解析时如果不校验脏数据会直接进数据库后面统计数据就乱了。主循环用定时标志驱动。1秒定时到了就巡检一遍8个传感器更新滤波结果检查阈值组帧发送到TCP连接。如果TCP连接断开就尝试重连重连间隔设置成5秒。这些逻辑不复杂用一个标志位加一个switch状态机就能搞定。volatile uint16_t tick_1s 0; void main(void) { // 系统初始化I2C、以太网协议栈、串口等 init_system(); while(1) { if(tick_1s 1000) // 1秒定时到 { tick_1s 0; update_all_temperature(); // 顺序读取8个传感器并滤波 check_threshold(); // 与阈值比较更新状态码 report_to_remote(); // 通过TCP发送文本帧 } process_network(); // 处理TCP协议栈事件 } }以太网协议栈部分如果是自己移植协议栈工作量在于TCP重传、ARP应答、DHCP状态机这几个模块。如果直接用项目支持的协议栈库要做的就是配置MAC地址、IP地址获取方式、初始化Socket。MAC地址建议从芯片唯一ID或外部EEPROM读取不要所有设备烧成同一个否则在一个局域网里会出现IP冲突之外更诡异的通信问题。4. HVAC 场景落地本地采集与远程监测4.1 冷冻水系统与风管温度监测点设计HVAC项目里温度测点不是随便放的。以中央空调冷冻水系统为例最关键的测点是冷冻水供水和回水温度。供水温度是冷源侧制冷效果的直接体现回水温度代表了末端负荷两者温差拉大说明建筑热负荷在增加。温差数据也是控制冷冻水泵变频、调节冷水机组台数的关键依据。这套系统里1号传感器测供水、2号测回水位置就装在供回水总管上传感器探头插入管道上的测温套管里而不是贴在管壁外面。风系统里新风机组的送风温度和回风温度同样重要。送风温度决定房间送风是否偏冷或偏热回风温度近似于房间平均温度两者一起可以用来做风机盘管或表冷器的控制。3号和4号传感器分别放在送风管和回风管中。安装时要特别注意传感器探头要伸进风管气流中心不能贴风管壁不然测的是管壁温度而不是空气温度同时要避开加热盘管或表冷器下游太近的位置那里温度场不均匀读数代表性差。4.2 多点温度如何影响控制逻辑有了多点温度数据控制逻辑就能做得比单点温度更合理。比较典型的应用是PID调节电动二通阀以回风温度或房间温度为目标值输出控制二通阀开度调节冷冻水流量。这个控制环路的反馈如果只用本地温度系统调节会有滞后因为冷水从冷源到末端本身就有传输延迟。如果把供水温度也纳入前馈当供水温度偏低或偏高时提前修正阀门输出控制效果会平滑很多。远程温度在这套逻辑里的价值不是直接参与PID而是给监控中心提供全局视角。几台空调箱分布在楼上楼下本地控制器各管各的如果集中在监控室看每个送风口的温度曲线就能发现大楼整体冷热不均的问题。哪个区域温度偏高、哪台新风机供回水温差小一眼就能看出来。然后运维人员可以在远程下发温度设定值或者控制模式而不需要逐台去现场按键。4.3 本地告警与远程监控协同本地告警和远程告警要做成两条独立通道。本地依赖传感器硬件OS引脚和单片机继电器输出温度超过85°C时强制切断相关设备或开启报警灯。远程告警依靠TCP上报状态字监控端软件发现状态异常后弹出告警条并记录日志。两条通道互不依赖的好处是网线断了本地保护还在单片机复位了硬件过温保护还在。HVAC现场最怕的就是只有一层保护真出事时所有通道都失效。我在某个项目里还加了一路RS-485接口作为以太网之外的备用远程通道。平时以太网正常时485口不做主要上报只响应Modbus RTU轮询一旦网络断线本地控制器检测不到心跳就把温度数据转由485口上报到网关。这套双通道冗余设计对机房这类不能长时间无人值守的场所很有价值成本也不高因为PIC18F87J11的EUSART接口本来就空闲着。5. 常见问题与排查技巧实录5.1 I2C 总线偶发无响应现象是系统运行几天后某个传感器读数突然变成0xFFFF复位又正常。排查后发现是I2C总线长度过长、线缆分布电容超过允许值加上上拉电阻偏大导致时钟线边沿变缓从机偶发无法识别时序。解决办法是把上拉电阻从4.7kΩ改成2.2kΩ同时把I2C速率从400kHz降到100kHz。后续新做的项目只要总线上超过3个传感器我都直接用2.2kΩ并且让PCB走线尽量短传感器假如需要延长线尽量让延长段SDA和SCL各用一对双绞线并套上磁环。5.2 温度读数固定偏高有一块板子的温度读数始终比实际温度高2°C左右换传感器也一样。检查发现是传感器位置太靠近板上的LDOLDO的发热直接加热了传感器。这种自热问题在传感器紧挨着功率器件时非常常见。解决办法是把传感器挪到PCB边缘或者用开槽把传感器和热源隔开。另外传感器本身有一个自热参数功耗越低自热越小所以工作模式下能关断就关断测量间隙让传感器进入低功耗状态能减少至少0.1°C的自热误差。5.3 远程TCP偶发断连网络好的时候能用好几天坏的时候一小时断好几次。抓包发现断连前往往有TCP重传超时。检查以太网差分线的对称性和变压器中心抽头电路最终定位到网络变压器的中心抽头电容选型不对造成了共模噪声泄漏。把电容值和变压器厂商参考设计对齐后问题消失。这里要强调一下网络变压器和电容不是随便选的必须跟变压器型号配套。如果你用的是带变压器的RJ45座那么问题更可能出在铺地设计上RJ45下方的地平面要完整不能有大面积走线切断。5.4 变频器启动时温度跳变变频器一启动温度读数就开始跳。这个问题比前几个更隐蔽因为变频器电磁干扰不只影响I2C也影响PIC的ADC、复位和以太网通信。针对温度跳变我做了三件事第一传感器供电和单片机供电之间加磁珠第二I2C线改成屏蔽双绞线并在传感器端加100pF对地电容第三加大软件滤波深度。实测干扰改善彻底读数平稳。其实嵌入式系统和强电设备共存时EMC问题不能靠软件兜底硬件上的隔离和滤波要一步到位软件滤波只是补充。5.5 多传感器地址冲突与批次管理批量调试时有一批板的地址配置和设计文档不一致查下来是贴片时地址电阻贴错位置。这个问题的成本在于需要逐台拆机核对非常浪费时间。之后我在固件里加了一个地址自检流程上电时按地址表逐次扫描哪些地址有应答、哪些没有输出到串口日志。批量生产时用这个日志就可以快速排查地址问题把调试时间从小时级降到分钟级。建议你也把这个功能保留在日常固件里现场排查会省很多事。6. 经验补充从这套方案延伸出去温度监测做完之后自然就会想做湿度、压力、风速这些参数。PIC18F87J11的ADC、I2C和串口外设其实都已经预留好了。硬件设计时如果把传感器接口做成统一的插座不直接焊死后续扩展就有很大空间。我在后续版本里加了湿度传感器和风管压差开关硬件板型没变只是固件里多读几个寄存器而已。这套方案真正的价值在于底子打得稳数字传感器接口标准、主控外设富余、远程通信通道独立可靠。按这个思路做起点即便只是监测一个温度点后面长出来的功能也会比预想的多。