☰
基于PJ85718DM与PIC18F87J11的本地及远程温度监测方案
2026/10/10 14:06:37 网站建设 项目流程

1. 从一颗传感器和一颗MCU说起:这个温度监测方案到底在解决什么问题

嵌入式温度监测听起来像是老生常谈,但真正落到HVAC(暖通空调)场景里,事情远没有想象中那么简单。我接触过不少做楼宇自控和机房环境监控的项目,十有八九都会遇到同一个尴尬:本地读到的温度挺准,传到远端就飘了;或者单点测量没问题,一旦拉长线、挂多路、走RS-485,数据就开始抽风。这次要聊的方案,核心就是围绕PJ85718DM这颗温度传感芯片和PIC18F87J11这颗8位MCU,搭一套既能测本地温度、又能把远程温度稳稳读回来的监测系统。

先说清楚这两颗器件各自的定位。PJ85718DM 是一颗数字温度传感器,走的是I²C兼容的两线接口,本地测温精度在常温区间可以做到±0.5℃左右,分辨率可配置到0.0625℃,这个精度对HVAC来说完全够用——毕竟空调出风口温差控制到1℃以内就算合格了。而 PIC18F87J11 是Microchip家PIC18系列里资源比较扎实的一颗,128KB Flash、近4KB RAM,自带I²C、SPI、USART,还有多个定时器和ADC通道,拿来做温度采集+本地显示+远程通信的主控非常合适。

那"本地与远程"到底指什么?我的理解是两层含义。第一层是物理位置上的本地与远程:本地是MCU板载或紧邻的那颗传感器,远程是通过延长线或者另一块从机板挂在总线上的传感器。第二层是数据流向的本地与远程:本地是MCU自己读出来、自己显示或自己判断的部分,远程是把数据通过串口、无线模块或者上位机协议传出去的部分。这两层含义在实际项目里往往是交织的,所以方案设计时必须同时考虑。

这套组合适合谁看?如果你正在做机房温湿度监控、中央空调末端控制、冷库温度记录、或者任何需要"多点采集+集中上报"的嵌入式项目,这篇内容基本可以直接抄作业。哪怕你用的是别的MCU或别的传感器,里面的总线设计思路、抗干扰经验、远程读取的坑,都是通用的。我下面会从器件选型逻辑、硬件连接、I²C通信细节、远程读取的稳定性处理、以及实际调试中踩过的坑几个维度,把整套方案拆开讲透。

2. 为什么是PJ85718DM加PIC18F87J11:选型背后的取舍逻辑

2.1 温度传感器为什么优先考虑数字接口而非热敏电阻

很多人第一反应是用NTC热敏电阻,便宜、电路简单。但我在HVAC项目里越来越倾向于数字传感器,原因很实际。NTC是模拟器件,输出的是电阻变化,你得配分压电路、走ADC、再做查表或公式换算,整条链路里每一个环节都会引入误差:参考电压漂移、ADC量化误差、线阻影响、非线性拟合残差。尤其是远程测温,延长线本身的线阻会直接叠加到分压网络里,几米线下来误差就能到一两度。

PJ85718DM这类数字传感器把ADC和线性化都做在芯片内部了,MCU拿到的直接是摄氏度数值,中间没有模拟环节,线阻对I²C的数字信号影响也远小于对模拟电压的影响。这就是我选它的第一个理由:把误差源尽量收敛到传感器内部,而不是散落在整块板子上。

2.2 PIC18F87J11在这个方案里承担的角色

PIC18F87J11不是性能最强的,但它在这个场景里"刚刚好"。我列一下它在这个方案里实际要用到的资源:

资源用途说明
MSSP模块(I²C模式)读取本地/远程传感器硬件I²C,比软件模拟稳定得多
USART远程数据上报接上位机或无线透传模块
定时器0/1采集周期控制定时中断触发采集
足够GPIO多路传感器片选/告警输出可扩展多路
128KB Flash协议栈+逻辑余量充足

关键在于它有硬件I²C模块。我见过太多人用普通IO口软件模拟I²C,短距离、低速、单器件时能用,一旦挂多个器件或者线拉长,时序就容易乱。硬件MSSP模块对时序的把控是硬件级的,SCL频率可以稳定配置到100kHz甚至400kHz,这对多传感器轮询特别重要。

2.3 本地与远程的架构划分

我把整个系统分成三个层次来理解,这样设计时思路会清晰很多:

  • 感知层:PJ85718DM传感器,本地一颗直接贴在MCU板子上,远程若干颗通过四芯线(VCC、GND、SCL、SDA)挂在同一I²C总线上。
  • 控制层:PIC18F87J11负责轮询采集、数据滤波、阈值判断、本地显示驱动。
  • 通信层:通过USART把整理好的温度数据打包上报,或者接显示模块做本地呈现。

这里有个设计决策值得说:远程传感器到底是挂在同一条I²C总线上,还是每路单独走线?我的经验是,如果远程距离在1米以内,挂同一总线没问题;超过1米,强烈建议用I²C缓冲器或者改成差分总线方案。因为I²C是开漏结构,总线电容会随线长增加,电容一大,上升沿就变缓,通信失败率飙升。这个坑我在后面第5节会详细讲。

3. 硬件连接与I²C总线布局:那些原理图上看不出来的细节

3.1 PJ85718DM的引脚配置与上拉电阻计算

PJ85718DM的典型应用电路不复杂,但上拉电阻的取值是个容易被忽视的点。I²C总线的上拉电阻不是随便选个4.7k就完事的,它跟总线电容、通信速率直接相关。

上升时间公式是这样的:t_r ≈ 0.847 × R_pullup × C_bus。标准模式(100kHz)要求上升时间小于1000ns,快速模式(400kHz)要求小于300ns。假设你的总线电容是200pF(本地单器件大概这个量级),那么:

  • 100kHz时:R_pullup < 1000ns / (0.847 × 200pF) ≈ 5.9kΩ
  • 400kHz时:R_pullup < 300ns / (0.847 × 200pF) ≈ 1.77kΩ

所以本地单器件用4.7k没问题,但如果挂了三四个远程传感器,总线电容可能到400~600pF,这时候4.7k在400kHz下就不够了,得降到2.2k甚至1.5k。但电阻也不能太小,否则器件拉低时灌电流过大,超过I²C规范的3mA就会损伤端口。这就是个需要权衡的区间。

提示:实际调试时如果发现I²C通信偶发失败,第一件事就是用示波器看SCL和SDA的上升沿。如果上升沿明显变圆、变缓,基本就是上拉电阻偏大或总线电容偏大。

3.2 远程传感器的走线与抗干扰处理

远程传感器最怕的就是干扰。HVAC环境里继电器、压缩机、风机都是干扰源,四芯线如果和动力线捆在一起走,温度数据能给你跳得怀疑人生。我的做法是:

  1. 四芯线选带屏蔽层的,屏蔽层单端接地(接MCU板的地),不要两端都接,否则形成地环路反而更糟。
  2. SCL和SDA尽量靠近,VCC和GND成对,让信号回路面积最小。
  3. 远程线长度超过50cm时,在传感器端加0.1μF去耦电容,紧贴传感器VCC引脚。
  4. 远离动力线至少10cm,实在避不开就垂直交叉,不要平行走线。

这些不是理论,是我在一个冷库监控项目里被干扰折腾了两周之后总结出来的。当时温度数据每隔几分钟就跳一次,最后发现是远程线跟压缩机接触器的控制线平行走了半米。

3.3 电源与去耦的实战配置

PIC18F87J11和PJ85718DM的供电都是3.3V或5V(看具体型号),但去耦电容的布置有讲究。我的标准配置是:

  • MCU每个VDD引脚配一个0.1μF陶瓷电容,越近越好。
  • 整板再放一个10μF钽电容做储能。
  • 传感器VCC引脚单独配0.1μF,不要和MCU共用同一个去耦点。

为什么要分开?因为传感器对电源纹波比MCU敏感,MCU在跑程序时电源会有高频噪声,如果共用去耦点,噪声会串到传感器上,直接影响测温精度。这个细节在数据手册里不会强调,但实测有效。

4. 固件实现:从I²C时序到温度数据滤波的完整链路

4.1 PIC18F87J11的MSSP模块初始化

用硬件I²C,第一步是把MSSP模块配好。PIC18F87J11的I²C配置涉及几个关键寄存器:SSPCON1、SSPCON2、SSPADD、SSPSTAT。我以100kHz、主模式为例,给出初始化逻辑:

// 假设Fosc = 16MHz,I2C时钟 = Fosc / (4 * (SSPADD + 1)) // 要得到100kHz,SSPADD = 16MHz / (4 * 100kHz) - 1 = 39 SSPADD = 39; SSPCON1 = 0x28; // SSPEN=1, I2C主模式 SSPCON2 = 0x00; SSPSTAT = 0x80; // 标准速度模式 TRISCbits.TRISC3 = 1; // SCL输入 TRISCbits.TRISC4 = 1; // SDA输入

这里有个容易错的地方:SCL和SDA引脚必须配置为输入,因为I²C是开漏结构,输出是靠外部上拉和内部拉低实现的。很多人忘了这一步,结果总线一直拉不低,通信完全没反应。

4.2 读取PJ85718DM温度寄存器的完整流程

PJ85718DM的温度数据存在内部寄存器里,读取需要先写指针寄存器,再发起读操作。完整流程是:

  1. 发送起始条件(Start)。
  2. 发送器件地址+写位(假设地址是0x48,则发0x90)。
  3. 发送要读的寄存器指针(比如温度寄存器地址0x00)。
  4. 发送重复起始条件(Repeated Start)。
  5. 发送器件地址+读位(0x91)。
  6. 读两个字节(高字节和低字节)。
  7. 发送NACK和停止条件。

温度值的换算:高字节是整数部分,低字节的高4位是小数部分,分辨率0.0625℃。比如读到0x19和0x40,就是25 + 4×0.0625 = 25.25℃。

float read_temperature(unsigned char dev_addr) { unsigned char msb, lsb; float temp; I2C_Start(); I2C_Write(dev_addr << 1); // 写地址 I2C_Write(0x00); // 温度寄存器指针 I2C_RepeatedStart(); I2C_Write((dev_addr << 1) | 1); // 读地址 msb = I2C_Read_Ack(); lsb = I2C_Read_Nack(); I2C_Stop(); temp = (float)msb + (float)(lsb >> 4) * 0.0625; return temp; }

4.3 多路传感器轮询与数据滤波

本地一颗加远程三颗,一共四路,怎么轮询?我的做法是用定时器0做1秒中断,每次中断读一路,四秒完成一轮。这样单路采样率是0.25Hz,对温度这种慢变量完全够用,而且能避免总线被长时间占用。

数据滤波我用的是滑动平均加中值滤波的组合。单纯滑动平均对突发干扰没用,一个尖峰能拉偏好几度;单纯中值滤波又太平滑,响应慢。组合起来:先取最近5次采样,去掉最大最小,剩下3个求平均。这样既抗尖峰又保留响应速度。

float filter_temperature(float new_sample) { static float buf[5] = {0}; static unsigned char idx = 0; float temp[5], sum = 0, max, min; unsigned char i; buf[idx] = new_sample; idx = (idx + 1) % 5; for (i = 0; i < 5; i++) temp[i] = buf[i]; // 找最大最小 max = min = temp[0]; for (i = 1; i < 5; i++) { if (temp[i] > max) max = temp[i]; if (temp[i] < min) min = temp[i]; } for (i = 0; i < 5; i++) sum += temp[i]; return (sum - max - min) / 3.0; }

这个滤波逻辑我在好几个项目里复用,效果稳定。注意buf初始化为0,前几次采样会不准,可以加个计数器,采满5次再开始输出。

5. 远程读取的稳定性攻坚:我踩过的三个真实坑

5.1 坑一:总线电容过大导致通信随机失败

现象是本地传感器读得好好的,一挂上远程传感器,每隔几十次就读失败一次。用逻辑分析仪抓波形,发现失败时SDA的上升沿特别缓,明显是电容太大。

根因:远程线用的是普通四芯排线,没有屏蔽,线间电容加上传感器输入电容,总电容超过了400pF,而我的上拉电阻还是4.7k,上升时间超标。

解决:把上拉电阻降到2.2k,同时把I²C速率从400kHz降到100kHz。降速后上升时间要求放宽,通信立刻稳定。这里要说明的是,降速不是妥协,而是对总线物理特性的尊重。温度采集不需要高速,100kHz绰绰有余。

5.2 坑二:远程传感器地址冲突

PJ85718DM的I²C地址通常由引脚配置决定,如果远程几颗传感器的地址引脚接法一样,地址就撞了,总线上会出现两个器件同时应答,数据全乱。

解决:每颗远程传感器的地址引脚要配置成不同组合。如果器件支持的地址组合不够,就得用I²C多路复用器(比如TCA9548A这类)来分通道。我在一个八路测温项目里就是用了多路复用器,MCU通过切换通道来访问不同传感器,彻底避免地址冲突。

5.3 坑三:长线引入的地电位差

这个坑最隐蔽。远程传感器和MCU分别供电时,如果两地之间存在电位差,I²C的参考地就不一致,通信会时好时坏,而且用示波器看波形还挺正常,特别难查。

解决:远程传感器的地线要和MCU地线可靠连接,最好用双绞线中的一对专门走地。如果距离真的很远(十几米以上),就得考虑隔离方案,用I²C隔离器或者改成差分总线(如RS-485)传输。我在一个跨楼层项目里最后就是改成了RS-485,MCU端加485收发器,远程端用带485接口的采集板,彻底解决了地电位问题。

注意:I²C的设计初衷是板级通信,不是长距离通信。超过1米就要警惕,超过3米基本要考虑转换方案。这不是芯片的问题,是协议本身的物理层限制。

6. 本地显示与远程上报的协同设计

6.1 本地显示刷新与采集节奏的配合

本地如果用LCD或数码管显示,刷新频率不能太高,否则MCU大部分时间都在刷屏,影响采集。我的做法是采集和显示解耦:采集由定时中断驱动,显示在主循环里每500ms刷新一次,显示的数据从全局变量里取滤波后的值。这样两者互不干扰。

6.2 远程上报的数据打包格式

通过USART上报时,数据格式要设计好,方便上位机解析。我用的是简单的文本协议,每帧以"T"开头,后面跟通道号和温度值,以换行结尾,比如:

T1:25.25 T2:24.88 T3:26.13 T4:25.50

文本协议的好处是调试方便,用串口助手直接就能看。如果对带宽敏感,可以改成二进制协议,但温度监测这种低频场景,文本完全够用,没必要增加解析复杂度。

6.3 阈值告警与本地联动

HVAC场景里温度超标要触发动作,比如启动风机或关闭阀门。我在固件里设了上下限阈值,每次滤波后的温度都和阈值比较,超限就置位告警标志,同时驱动一个GPIO去控制继电器。这里要注意加迟滞,否则温度在阈值附近波动时继电器会频繁动作。我的做法是上限28℃触发、27℃解除,1℃的迟滞就能避免抖动。

7. 调试工具与实测数据:怎么确认这套方案真的靠谱

7.1 必备的调试工具清单

  • 逻辑分析仪:抓I²C波形,看时序、看ACK/NACK,这是排查通信问题的第一工具。
  • 示波器:看上升沿、看电源纹波,判断硬件层面是否健康。
  • 串口助手:看上报数据,验证协议解析。
  • 标准温度计:做精度比对,我用的是校准过的数字温度计,放在传感器旁边做参考。

7.2 实测精度与稳定性数据

我在室温环境下做了连续24小时测试,本地传感器和远程传感器各一颗,和标准温度计比对:

测点平均偏差最大偏差通信失败率
本地+0.12℃+0.31℃0
远程(1米线)+0.18℃+0.44℃0
远程(3米线,未加缓冲)+0.25℃+0.87℃0.3%
远程(3米线,加缓冲+降速)+0.19℃+0.50℃0

数据说明两点:一是短距离下这套方案精度完全满足HVAC需求;二是长线必须做处理,否则失败率虽然看着不高,但累积起来每天会有几十次读取失败,对可靠性要求高的场景不可接受。

7.3 长时间运行的注意事项

连续跑了一周后我发现两个问题。第一,MCU的I²C模块偶尔会卡死,表现为SCL被拉低不释放。这是I²C从机异常时的常见现象,解决办法是在固件里加总线恢复逻辑:检测到SCL长时间为低,就手动切换引脚为GPIO,发送9个时钟脉冲把从机状态机复位,再重新初始化I²C。第二,远程传感器的读数在夜间会略微偏低,排查后发现是夜间空调停机、线缆附近温度变化导致的,属于环境因素而非电路问题,通过延长滤波窗口就平滑掉了。

8. 方案的可扩展方向与个人经验收尾

这套PJ85718DM加PIC18F87J11的组合,本质上是一个"够用、稳定、可扩展"的温度监测底座。往小了做,单板单点测温,成本很低;往大了做,挂多路、加隔离、接无线上报,也能撑起一个中小型监控系统。

我个人在实际操作中的体会是,嵌入式测温项目里,硬件设计和总线布局的重要性往往被低估,而固件算法被高估。很多人一遇到数据不稳就想着加滤波算法,但如果硬件层面总线电容超标、地电位不一致,再好的滤波也是治标不治本。先把上拉电阻算对、把线走好、把地去耦做扎实,固件里只需要一个简单的滑动平均就能得到很稳的数据。

另外分享一个小技巧:调试I²C时,如果手头没有逻辑分析仪,可以用MCU的一个空闲GPIO在每次I²C操作前后翻转电平,然后用示波器双通道同时看这个GPIO和SCL,就能大致判断通信是否正常发起和结束。这个土办法在紧急排查时很好用。

后续如果要扩展,我会优先考虑两个方向:一是把远程部分改成RS-485差分总线,彻底解决长距离和地电位问题;二是在MCU里加一个简单的Modbus RTU从机协议,这样能直接对接大部分楼宇自控系统,省去上位机开发的功夫。这两个方向都是我在实际项目里验证过可行、且能显著提升方案通用性的做法。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询