资讯动态

PIC18F97J60与PJ85718DM结合:打造本地+远程温度监测节点

发布时间:2026/10/22 6:42:21 来源:尧图企业网站定制
做嵌入式的朋友应该都有这种经历现场要能看到温度远端也要能看到温度尤其是 HVAC、机房、冷库、洁净区这些场合你既不能只做一块本地数显表也不能只做纯无线云端方案因为现场调试的人要数据远程值守的人也要数据。最近我把 PJ85718DM 这颗 I2C 温度传感器和 PIC18F97J60 这个自带以太网控制器的单片机组合在一起做了一个既能本地显示、又能远程访问的温度监测节点。整个项目从画原理图到固件调通大概花了一周包含传感器上挂接、网页服务器、TCP/IP 协议栈裁剪、现场部署今天把完整思路、接线、驱动、网络配置和踩过的坑都整理出来希望能给正在做类似嵌入式温度采集或 HVAC 环境监控的朋友一个可直接参考的方案。这个方案最大的价值在于PIC18F97J60 本身集成了以太网 MAC 和 PHY不需要再外挂 ENC28J60 之类芯片整个板子布线简单很多。PJ85718DM 是标准的 I2C 数字输出温度传感器不需要额外处理模拟信号直接读寄存器就能得到温度值。两者组合起来很适合做分布式环境监测里的一个节点本地显示当前温度同时通过网络提供远程访问页面运维人员只要打开浏览器就能看到每台设备附近的实时温度不用跑到现场去拿手持表一个个测。需要说明的是PJ85718DM 虽然叫这个型号但不同批次的数据手册细节可能稍有差异我这里以我手头的规格为准讲解其他同类型 I2C 温度传感器驱动思路完全通用你只需改一下寄存器地址和分辨率配置即可。1. 项目需求拆解与整体方案设计1.1 这类项目到底在解决什么问题先说应用场景。暖通空调里最典型的就是风管送风温度、回风温度、机房环境温度、冷热水管表面温度这些数据如果只靠现场仪表看那运维人员就必须频繁巡检而且巡检记录往往不能实时汇总。嵌入式环境监测也一样比如配电柜内部温度、控制柜温度现场装个表头是基本要求但远程监控才是更核心的价值。标题里说的“本地与远程温度”拆开看其实是两个需求本地温度是指系统在现场通过 LCD 或者 LED 数码管显示当前温度供巡检人员直接读取远程温度是指同一个数据通过网络传送给上层监控平台无论是网页、Modbus TCP、还是普通 UDP 报文只要网络可达远端就能看到。PJ85718DM 负责把温度物理量变成数字PIC18F97J60 负责处理显示和网络这是很自然的硬件分工。这种方案相比常见的“单片机 串口屏 上位机”结构最大的优势是不依赖上位机软件。浏览器就是客户端不需要安装任何专用软件这在现场维护时非常省事。我在实际项目里就遇到过这种尴尬客户现场笔记本上没有装厂商提供的组态软件远程调试根本进行不下去后来改成网页版数据后任何一台电脑都能看问题直接消失了。1.2 为什么选 PIC18F97J60 而不是其他方案市面上做以太网温湿度节点很多人第一反应是 ESP8266 或者 STM32F4 W5500但 PIC18F97J60 在这种场景下有它独特的地位。首先是硬件简单它内置了 10Base-T 以太网 MAC 和 PHY外部只需一个隔离变压器和一个 RJ45 座不像 ENC28J60 那样还要额外 SPI 接口和配套软件驱动更不像 W5500 那样需要较大内存来跑协议。其次是可靠性PIC 系列在工业和 HVAC 领域用了很多年抗干扰和长期稳定性经过了大量现场验证这在冷库、室外空调机组这种恶劣环境里很重要。PIC18F97J60 的具体资源也够用128KB 的 Flash 程序空间、大约 3.8KB 的 SRAM跑一个精简的 HTTP 服务器和温度采集逻辑绰绰有余。有人可能会觉得才 3.8KB RAM 太少了但嵌入式以太网节点本来就是靠“小而精”的协议栈吃饭的我们后面会把协议栈裁剪得很干净只保留 ARP、IP、ICMP、TCP、HTTP 和必要的 UDP完全能稳定运行。再说 PJ85718DM。它是一颗 I2C 接口的数字温度传感器不需要额外运放和基准电压温度分辨率能做到 0.0625°C 左右在 HVAC 这种应用里已经很够用了。传感器的精度比分辨率更重要我手头这颗在 -20°C 到 70°C 范围内典型误差约 ±0.5°C满足绝大多数环境监控需求。1.3 系统整体架构和各模块职责系统的数据流向是这样的PJ85718DM 周期性地把温度值放在内部寄存器里单片机通过 I2C 读出原始数据在固件里换算成真正的摄氏温度然后分两条路输出。一条是本地显示通过一块 1602 LCD 实时刷新另一条是远程访问单片机内部的 TCP/IP 协议栈处理 HTTP 请求把温度值动态填充到网页模板里返回给浏览器。这里有个容易忽略的问题本地显示和远程访问的数据必须同源不能在两个地方分别采集否则现场和远程数值对不上运维人员会怀疑设备坏了。我用的是同一个变量LCD 刷新的数据源和网页填充的数据源是同一个全局温度值这样无论从哪个端看读数完全一致。整个系统还需要一个稳定的电源和正确的晶振配置。PIC18F97J60 的以太网 PHY 需要精确的时钟我这边用的是 25MHz 外部晶振这样才能保证 10Base-T 的网络通信正常。电源部分用一个 3.3V 线性稳压器给单片机供电传感器也工作在 3.3V减少 I2C 电平转换的麻烦整体功耗很低一个普通的 5V/1A 适配器就能带起来。2. 硬件电路设计与连接细节2.1 PJ85718DM 的引脚定义与典型接法PJ85718DM 的引脚很少常见的有 VDD、GND、SDA、SCL、A0、A1 这几个。A0 和 A1 是地址配置引脚通过接到 VDD 或 GND 可以组合出不同 I2C 地址这样一条总线上就能挂多颗传感器。对于我的节点板子上只挂了一个传感器和一块 I2C 转接的 LCD所以地址问题不大但设计时还是留了两个 0 欧电阻方便以后扩展。硬件连接需要注意三点一是 VDD 和 GND 之间要放一个 100nF 去耦电容而且电容要尽量靠近传感器引脚否则在工业现场容易读到跳动数据二是 SDA 和 SCL 必须加上拉电阻一般用 4.7kΩ如果总线上的设备多了可以换成 2.2kΩ三是传感器到单片机的连线不要太长HVAC 现场如果传感器和主板距离超过 30cm建议用双绞线并加 TVS 保护我实际做的最长线缆是 1 米左右短距离直连完全没有问题。I2C 总线上挂多个设备时还要注意地址冲突。PJ85718DM 的默认地址通常是 0x48 或 0x49而 I2C 转接的 LCD 地址一般是 0x27 或 0x3F只要不相同就能共存。我建议上电之前先用 I2C 扫描程序把所有设备地址列出来省得后面协议栈调通以后才发现传感器数据根本读不到。2.2 PIC18F97J60 最小系统与以太网接口电路PIC18F97J60 的最小系统比普通单片机多一点内容它需要一个 25MHz 晶振给以太网 PHY 提供基准时钟需要标准的复位电路需要对 MCLR 引脚做上拉和去耦还需要把以太网模块对应的引脚引到隔离变压器和 RJ45 座子上。10Base-T 只需要两对差分线一对 TX 一对 RX比 100M 的电路简单很多。网络变压器这一块我直接用了带网络变压器的 RJ45 座就是把变压器和接口集成在一起这样布线最省事。如果买不到集成座也可以外接一个 10Base-T 隔离变压器再连普通 RJ45 座但要注意 TX、TX-、RX、RX- 的极性不能接反接反了最典型的症状是网口指示灯不亮ping 不通但万能表又量不出明显短路非常浪费排查时间。以太网链路指示灯也要接出来LINK 和 ACT 两个状态能帮你快速判断网络连接是否正常。我习惯把这两个 LED 放在板子边缘调试时一目了然上电后 LINK 灯亮说明物理层已经协商成功ACT 灯闪烁说明有数据流量如果 ACT 灯常亮或者不亮很可能就是协议栈配置有问题。2.3 本地显示与电源设计本地显示我用了 1602 LCD通过 I2C 转接板挂在同一条 I2C 总线上。为什么不用并口 LCD因为 PIC18F97J60 的 IO 虽然不少但很多引脚已经被以太网模块占用了并口 LCD 会消耗大量 GPIO而且走线也更复杂。I2C 转接板只需要两根信号线和传感器共用总线非常划算。电源设计上我用一个 5V 适配器供电板子上先用一个二极管做防反接然后经过 3.3V LDO 稳压。PIC18F97J60 和 PJ85718DM 都工作在 3.3VLCD 转接板也能接受 3.3V这样整个系统不需要电平转换。唯一要注意的是如果液晶屏的背光电流比较大最好直接从 5V 通过一个限流电阻供电不要从 LDO 后面取否则 LDO 压差大、电流大发热会很厉害。关于模拟地和数字地这个系统没有复杂的模拟前端所以不需要分割地平面。我在设计时把传感器地、单片机地、网络接口地全部接到同一块铺铜上只在电源入口处放一个磁珠并联大电容就能达到不错的抗干扰效果。不要过度设计地分割否则反而容易形成地环路导致网络通信异常。3. 固件开发传感器驱动与以太网协议栈3.1 I2C 驱动与温度寄存器读取PIC18F97J60 内部有硬件 I2C 模块也就是 MSSP 模块可以工作在主机模式。我们在固件里要做的事情很简单初始化 I2C 模块为主机模式设置波特率在 100kHz 或 400kHz然后按照 PJ85718DM 数据手册的读寄存器时序把温度寄存器原始值读回来。初始化代码大体是这样void i2c_init(void) { SSPCON1 0x28; // I2C master mode SSPADD 49; // 100kHz 8MHz Fosc? 实际按振荡频率调整 SSPSTAT 0x80; // SMBus 规范禁用斜率控制 TRISBbits.TRISB4 1; // SDA input TRISBbits.TRISB3 1; // SCL input }实际使用的引脚集合要根据你选用的单片机封装和数据手册确定不同封装下 I2C 引脚位置会变。PJ85718DM 的温度寄存器一般是 16 位读取时需要先发送器件地址加寄存器地址然后连续读两个字节。读回来之后按数据手册给的 LSB 值转换比如常见的是 0.0625°C/LSB那真实温度就是(raw 4) * 0.0625或者为了节省浮点运算你也可以直接用定点方式temperature_int raw * 625 / 10000。这一步看起来简单但最容易踩的坑是有些传感器在上电之后默认处于睡眠模式必须先发送一条配置命令唤醒才能读到有效数据。我一开始按数据手册习惯读温度寄存器结果读回来全是 0xFF排查了很久才发现是唤醒步骤漏了。所以无论用哪颗传感器第一步一定要完整读一遍数据手册的操作时序不要只看寄存器地址表。3.2 TCP/IP 协议栈的选择与内存裁剪PIC18F97J60 本身不带 TCP/IP 协议栈需要移植。我当时用了原厂那个比较经典的独立协议栈里面包含了应用层、TCP、UDP、IP、ICMP、ARP 还有数据包收发驱动。完整版本很庞大直接编译链接进去Flash 和 RAM 都很紧张所以必须裁剪。裁剪的核心思路是只用情况下需要的模块。我做这个项目只需要 HTTP 服务器、ARP、IP、ICMP、TCP不需要 DHCP 客户端时就把 DHCP 关掉IP 地址直接用静态配置。DHCP 这种功能在嵌入式设备上看着方便但在现场调试时反而会增加变量因为你不知道最后拿到的是什么 IP所以我干脆在配置里写死 IP 地址再用一个拨码开关选择最后一位这样部署时根据机柜编号设置不同 IP 即可。TCP 缓冲区是 RAM 占用的大头一个 TCP 连接通常需要发送缓冲区和接收缓冲区每块 1KB 左右两个连接加起来就会吃掉一半内存。对于温度监测这种低频数据一个并发连接就够用了所以我把最大并发 TCP 连接数改成 1发送缓冲 1024 字节接收缓冲 512 字节丈量下来稳定性反而更好因为不会出现多个连接抢占缓冲区导致的随机通信失败。ARP 缓存表也要改小。现场就那么几个上位机保留四个缓存项已经足够了每项大约占几十字节虽然不多但嵌入式开发就是要把每一字节抠出来。3.3 网页页面与动态温度填充远程温度功能的实质是一个运行在单片机上的微型 HTTP 服务器。浏览器发来 GET 请求单片机从 Flash 里取出预先存储的 HTML 页面把页面里的特殊温度标识符替换成实际的温度字符串然后通过 TCP 回给浏览器。这里我用了协议栈自带的网页文件系统机制简单说就是把你写好的 HTML 文件转成一个数组烧录到 MCU 的 Flash 里然后在页面模板中用类似!TEMP!这样的占位符标记温度位置。HTTP 服务器解析到这种标记时会调用注册的处理函数把温度值填进去。我的页面模板大致长这样html headmeta http-equivrefresh content3/head body 当前温度!TEMP! °C br更新于!TIME! /body /htmlmeta refresh设置为 3 秒这样页面在浏览器里会自动刷新实现“准实时”效果不需要写 JavaScript 轮询也不需要 WebSocket非常省资源。这个技巧对老式浏览器和工控机上锁定的旧系统特别友好因为所有现代浏览器都支持这种最基本的刷新方式。网页内容不要写太大。8KB 左右的 HTML 页面在 128KB Flash 里完全不是问题但页面越大每个 TCP 包要分片发送的次数越多刷新延迟会上升。我最终把页面控制在 2KB 以内整个页面一次或者两次 TCP 分段就能发完远程打开页面的速度基本是秒开。4. 调试过程与现场排查记录4.1 从读寄存器到本地显示先把温度读稳项目调试我习惯分两步走。第一步先把 I2C 驱动调通第二步再把网络加上因为如果你连本地数据都读不准后面网络部分调起来更痛苦出问题都不知道是协议栈的问题还是传感器的问题。调传感器时我接了一个逻辑分析仪查看 SDA 和 SCL 上的波形重点看三个方面起始条件、器件地址有没有 ACK、寄存器地址有没有 ACK。最常遇到的情况是器件地址不对导致传感器不回 ACK这时候要把 A0、A1 的接法和实际 I2C 地址对应起来查一下。温度读数稳定以后发现数值在整数部分完全没问题但小数部分偶尔会跳变比如 25.12°C 和 25.18°C 之间跳。这不一定是程序 bug可能是传感器自身分辨率或电源纹波引起的。我处理办法很简单软件上做三次连续读取取平均每 200ms 刷新一次这样显示值就很平稳了。对于 HVAC 监控温度变化本来就慢没必要追求毫秒级实时性平均值更能反映真实环境趋势。4.2 以太网连接与 HTTP 网页调试网络调试的第一步是先 ping 通。给单片机烧录好固件插上网线把电脑 IP 改成同一网段比如单片机是 192.168.1.100电脑就是 192.168.1.50然后命令行里 ping 192.168.1.100。如果 ping 不通先从物理层查起看网口的 LINK 灯亮不亮。LINK 灯不亮基本就是变压器接线问题或者晶振没起振LINK 灯亮了但 ping 不通就要查协议栈配置、MAC 地址是否有效、ARP 缓存对不对。ping 通之后我直接用浏览器访问。第一次打开页面发现显示出来的是乱码排查后发现是 HTML 文件转数组时编码不是 UTF-8中文标题全部成了乱码。这个很好解决用记事本把 HTML 另存为 UTF-8 编码再重新转数组即可。如果你用的是英文页面就不会遇到这种问题但中文字符乱码是很多刚接触网页嵌入式的朋友容易忽略的细节。还有一个印象深刻的问题就是页面打开后温度一直显示!TEMP!原样没有被替换。这个通常是占位符名字和注册的替换函数名不一致导致的。我在页面模板里写的是!TEMP!但代码里注册处理函数时用的是TEMP字符串看起来没问题结果大小写或者空格不一致替换就静默失败了。调试的方法很简单打印出网页文件系统解析到的标识符和代码里的注册字符串逐字节对比肉眼核对一遍就发现了。4.3 常见问题与排查速查表下面这张表是我在这次项目里总结出的常见问题后续做其他传感器 以太网节点时也反复用到。现象可能原因解决方法I2C 读取为 0xFF传感器未唤醒/未上电先发送唤醒命令检查 VDD 供电I2C 总线卡死无 ACK上拉电阻缺失或过强加 4.7kΩ 上拉或调整阻值温度跳动剧烈电源纹波大/接线过长去耦电容靠近传感器用屏蔽双绞线网口 LINK 灯不亮变压器接线错/极性反对照数据手册检查 TX/RX 极性网口 LINK 亮但 ping 不通晶振频率或协议栈配置错误确认 25MHz 晶振静态 IP 配置正确页面返回乱码HTML 编码不是 UTF-8另存为 UTF-8 后重新转数组占位符原样显示替换函数名与模板不一致逐字节检查标识符拼写系统周期性重启看门狗未喂狗或电源跌落在主循环喂狗加大电源电容这张表对后面的项目非常有用尤其是像“LINK 灯亮但 ping 不通”这种情况表面上看是协议栈问题实际上 60% 都是晶振和 IP 配置的问题先把这两点排除掉再往上层找原因能省很多时间。4.4 现场部署中的几个细节这个节点最后部署在一个模拟 HVAC 环境的测试场所里我总结了几个现场才暴露出来的细节问题。第一个是网线长度。PIC18F97J60 是 10Base-T在 A 类或者更长的屏蔽双绞线上 100 米都没有问题但我建议现场尽量走弱电桥架别和 220V 动力电缆绑在一起。如果和动力电缆平行走线超过 5 米偶发通信中断的几率会明显上升。第二个是电源共地问题。现场用的适配器往往是开关电源开关电源的地和单片机的地之间可能存在十几伏的压差如果传感器金属外壳接触到了安装支架形成地环路温度读数就会漂移。我在安装时给传感器探头加了绝缘片同时把探头金属部分与支架隔离问题就消失了。第三个是 IP 冲突。多台设备部署在同一个网段里如果 IP 都是手动配置的很容易出现两台设备配了同一个 IP结果一台能访问一台不能。我给每块板子加了一个三位拨码开关用二进制拨出 IP 地址最后一位从 2 到 250 都可以设置部署时按机柜号拨码永远不会冲突。5. 扩展思路与进一步优化方向5.1 多传感器与模拟量扩展PJ85718DM 支持多个器件挂接在同一条 I2C 总线上通过 A0 和 A1 引脚组合地址理论上一条总线上最多可以挂多颗同型号传感器。这个特性非常适合 HVAC 里的多点温度监测比如一个空气处理机组需要同时测送风温度、回风温度、混合温度用一颗单片机加三颗传感器就能搞定不需要额外的采集模块。如果现场还有湿度需求可以在这个基础上加一颗 I2C 湿度传感器或者选择内部带湿度测量的复合传感器。读数逻辑基本一致只是多读一个寄存器网页上多加一个刷新占位符。如果现场需要测量风管表面平均温度或者测水流温度也可以把 PJ85718DM 的封装形式换掉换成探测头形式的传感器或者通过延长线接到被测表面。螺纹式安装接头在 HVAC 行业非常常用直接拧到风管上的温度插孔里非常方便。5.2 从 HTTP 网页到 Modbus TCP网页显示适合人看但很多 HVAC 上位机支持的是 Modbus 协议。如果你想把这个温度节点接入到楼宇自控系统里我可以把 HTTP 服务器旁边再加一个小型的 Modbus TCP 服务器在原来的 TCP 监听端口之外额外监听 502 端口然后实现几个常见的 Modbus 功能码。实现 Modbus TCP 比想象中简单尤其是只需要保持寄存器读取的时候。温度值放在保持寄存器里上位机通过读保持寄存器功能码就可以周期性地获取温度。这样同一个硬件节点既支持浏览器直接访问也支持标准 Modbus 接入实际交付时客户基本上只用其中一种接口但两种都留着能兼容不同项目需求。5.3 长期运行稳定性与数据记录嵌入式温度节点和普通开发板最大的区别是它要 7x24 小时不关机运行。所以在代码层面要特别注意看门狗处理和网络异常恢复。我在主循环里喂狗同时用定时器每 5 秒检查一次 TCP 连接状态如果发现协议栈某个连接处于异常关闭状态又不释放就强制重新初始化网络模块。数据记录方面如果只想存最近几天的温度曲线不需要外接 SD 卡直接用 Flash 里剩余的空间记录即可但要注意 Flash 写入寿命是有限的频繁写入会磨损 Flash。我在项目里用的是一个简单的环形缓冲每 5 分钟写一次每天写 288 条记录配一个时间戳既满足现场事故回溯需求又不会消耗太多 Flash 寿命。如果客户需要长期历史曲线那就老老实实加 SD 卡或者把数据定时上报给上位机数据库嵌入式节点本身只做实时采集和短时缓存。5.4 时钟同步的替代方案如果你需要记录温度变化的时间节点那系统里必须有一个可靠的时钟。PIC18F97J60 本身没有内置实时时钟我最初是外挂了一颗带电池的 RTC 芯片I2C 接口价格不高但是电池和晶振都要额外占面积。后来我试了一个更简单的方案每次设备联网成功后通过一个简单的时间服务器接口获取当前时间然后利用单片机内部的定时器做秒累计只要设备不掉电时间误差一天不超过几秒完全能满足温度监测记录的需求。这个方案的缺点是一掉电时间就丢失需要重新同步所以如果现场可能频繁停电还是老老实实用 RTC 加电池或者做好断电后重新启动时自动请求时间。取决于你的部署环境我在室内机房用网络时间同步方案已经跑了很久没出过太大问题。最后分享一个我自己的体会这种嵌入式温度监测节点真正决定成败的不是单片机性能也不是传感器精度而是扎扎实实的细节处理。I2C 上拉、晶振布局、电源去耦、网络匹配每一个环节都可能是暗坑。我建议在做板子之前先用开发板和杜邦线把传感器到网页的整条链路先打通确认传感器标定值、协议栈稳定性和页面显示效果再开始画正式 PCB。这样画板子的时候你已经知道哪些地方容易干扰哪些地方需要预留测试点而不是一边画板一边担心固件写不出来最后调试时把硬件和软件问题搅在一起反而更浪费时间。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑