
最近在做一台HVAC控制器配套的嵌入式板卡又碰到了“板上要测环境温度、设备外部还要测一路远端热源温度”的老需求。一开始拆给两块独立的温度传感器做后来越想越不对劲线缆多点逻辑多点标定也麻烦。最后换成PJ85718DM单芯片双通道方案配合PIC18F85J50做主控一套I2C总线读两路温度清爽多了。这套组合适合谁主要是在做嵌入式板级监测、HVAC控制器、智能电表、储能机柜这类场景的朋友。你要同时关心电路板自身的温度和远端探头那边的温度又不想多挂一堆器件那PJ85718DM这类双通路温度芯片是很好的切入点。PIC18F85J50这边本身带有两个I2C/SPI可复用的MSSP模块GPIO数量也宽裕接一颗传感器芯片绰绰有余做中央逻辑控制、报警输出、通信上报都不挤。下面这篇文章我不打算写成一个芯片数据手册的翻译稿而是把从硬件连接、寄存器配置、温度换算到报警策略、I2C调试踩坑、HVAC现场误差校准的完整过程展开讲一遍。你照着走基本能复现出一套可用的本地/远程双路温度监测系统。1. 为什么把本地与远程温度放进同一颗传感器芯片1.1 现场需求拆解温度测量的两个“世界”做嵌入式的人很容易踩一个误区觉得温度测量嘛一个传感器点一个温度多点就多挂几个芯片简单粗暴。但实际工程里本地温度和远程温度是两种完全不同的“世界”。本地温度关注的是电路板自身的热状态比如主控芯片表面温度、电源模块散热、板上环境温度。这个测量点离主控近走线短干扰可控对探头形状没有要求传感器芯片直接贴着板子放就行。远程温度则关注的是被控对象或远端环境的热状态比如HVAC系统里的冷凝管表面温度、风道出风口温度、压缩机外壳温度。这个测量点往往离主控几十厘米甚至几米远线缆要走过强电区域、震动环境对探头防护、线缆抗干扰能力的要求完全不同。我最初给某项目的HVAC控制器设计温度采集时为了图简单用了两颗完全独立的数字温度传感器一顆一颗贴板子上另一顆封装在金属探头里引线出来。结果遇到一堆糟心事两颗传感器要占用两路通信接口或者两个地址软件里要维护两套配置、两套校准参数板生产的时候校准数据还要分开烧录。更头疼的是两颗传感器本身的测温特性可能不一致在同一个温区里本地和远程两个读数总是存在那零点几度的系统性偏差排查起来非常难受。用单芯片双通道方案就顺手很多。PJ85718DM这类芯片把本地温度传感器和远程温度测量电路封装在同一颗芯片里内部有一个测量本地的温度传感器外部再通过一对引脚接远程探头。两路温度由同一个转换核心在不同时间片轮询完成读出来天然就是同一基准、同一线性化算法的产物比两颗不同批次芯片之间的匹配度稳定得多。1.2 PJ85718DM与PIC18F85J50的分工这套系统里两颗芯片的定位非常清晰PJ85718DM是温度采集前端负责两路温度信号的测量、转换、报警比较。它自己的本地通道就是芯片内部温度传感器不需要外部元件远程通道则是通过DP、DN两个引脚接外部探头通常接一个二极管形式的小信号晶体管或者直接接专用的温度探头。报警输出引脚可以直接驱动风扇、继电器做主控之外的硬件级保护。PIC18F85J50则是系统主控负责通过I2C总线读取PJ85718DM的温度寄存器做温度换算、显示、上报、逻辑判断必要时对报警信号做软件二次确认。它工作电压范围宽内部有多个通信模块跑这类温度监测任务很稳。两路温度数据都挂在同一条I2C总线上主控只需用一个器件地址就能把本地温度和远程温度都读回来。这一点在后期维护时特别有用——固件不用为第二颗传感器单独维护一套驱动。1.3 单芯片方案 vs 多传感器方案我把之前用的“两颗独立数字传感器”方案和现在的“单芯片双通道”方案放在一起对比数字是实际项目里的真实评估对比项两颗独立传感器单芯片双通道方案通信接口占用2路I2C地址或分时复用1个I2C地址搞定局部温度同步性两芯各自转换存在时间差同一转换核心轮询差异极小通道间匹配误差受批次、封装影响可能超过±0.5℃芯片内校准匹配误差更小PCB面积与线缆元器件多线束多元件少远程线缆只需一对屏蔽线故障排查复杂度需要区分是哪颗传感器异常只需要看一个器件回归成本相对偏高综合成本偏低对量产设备来说元器件种类的减少意味着备料、贴片、测试全环节都能简化。对现场维护来说一个器件地址、一对远程探头线也让问题定位变得直接。这不是性能上“够用不够用”的问题而是整个链路的工程成本问题。2. 硬件连接与引脚规划2.1 I2C总线的上拉与电平匹配PJ85718DM的接口引脚就是标准I2CSDA、SCL外加一个报警输出引脚有的叫FAULT或ALERT具体以你拿到的芯片型号为准。PIC18F85J50的工作电压是3V-3.6V级别PJ85718DM也按3.3V供电设计两边电平匹配很直接不需要额外的电平转换。上拉电阻是I2C最容易出错的地方。我第一次搭这套硬件时随手从板子上拆了两个10kΩ的上拉电阻焊上去结果400kHz快速模式下面SDA线上的上升沿软绵绵的逻辑分析仪能看到SCL正常但从机ACK信号频繁读不到。后来才反应过来总线上的等效电容在那里摆着10kΩ上拉在400kHz下的RC充电时间常数太大了SDA被拉低释放之后根本来不及在半个位周期内回到高电平阈值。实际按3.3V供电、400kHz快速模式来配我建议上拉电阻选2.2kΩ到4.7kΩ之间。总线不长传感器和主控在同一块板上走线不超过十几厘米的情况下2.2kΩ最稳。如果是100kHz标准模式上拉可以放宽到4.7kΩ功耗低一些。另外如果总线上还挂了别的器件比如EEPROM、实时时钟要注意所有上拉加在一起后的等效阻值。并联过多上拉电阻会把逻辑低电平拉得太高导致低电平判定失败。稳妥的做法是一根总线上总共就一组上拉其他器件都不再各自外加上拉。2.2 远程二极管通道的接法与滤波PJ85718DM的远程温度测量通道原理上利用的是PN结正向压降随温度变化的特性。大多数这类芯片的远程通道都设计成“电流激励电压测量”模式芯片内部往远程探头灌一个恒流或者用你测量前端的脉冲电流然后测量PN结上的正向压降通过内部查表和补偿电路换算成温度。实际工程里我们不会真的去买昂贵的专业温度二极管而是拿手边的小信号三极管顶上去把基极和集电极短接借用它的基极-发射极结当二极管用。一个是低成本一个是这种封装的探头响应速度快、一致性也不错。你别把漏电流大的功率管或者光耦里的红外发光管拿来测那个压降特性和设计值偏差很大远端读数容易偏高。我实际布板时远程通道走线是这样安排的DP、DN两根线尽量紧挨着走不要分开绕否则容易引入环路感应的干扰。在DN和DP之间靠近芯片引脚端放一个2.2nF到10nF的电容做差模滤波。如果远程探头线要引出板外HVAC设备经常这样用屏蔽双绞线或带屏蔽层的探头线屏蔽层在传感器芯片那一端单点接地不要两端同时接地避免形成地环路噪声。远程走线尽可能短。线越长寄生电容和串联电阻越会被放大温度读数要么波动要么整体偏移。2.3 引脚分配建议PIC18F85J50这芯片的I2C资源并不少它内部有多个MSSP模块能同时跑I2C和SPI。我在项目里的分配思路是这样的外设模块说明PJ85718DM 温度传感器MSSP1I2C快速模式专门读取温度地址唯一外部EEPROM或按键MSSP2I2C或SPI不占用温度采集总线互不干扰报警输出任意GPIO接PJ85718DM的FAULT引脚同时配合中断输入LED指示独立GPIO报警状态可视化这样做的理由很简单温度采集这条链路要保证实时性。虽然I2C总线可以挂多个器件但一旦总线上有其他器件频繁通信会有位级仲裁和等待温度读取的确定性就差了。两路MSSP模组把采集和存储分开固件写起来也干净。另外一个容易被忽略的细节是GPIO分配一定要给每条I2C线留测试点。我说的是板子生产测试用的那种小焊盘不是绝对必要但如果你像我一样碰到过I2C上拉电阻虚焊、怎么调代码都读不到设备的场景你就会知道板子上有个能夹示波器探针的测试点是多幸福的事。3. 寄存器配置与温度换算3.1 初始化流程PJ85718DM这类芯片上电后不会立刻开始转换要先等内部上电复位完成然后再通过I2C写入配置寄存器。我的初始化顺序是系统上电后等待至少10ms让传感器芯片内部稳定。发送I2C起始条件写器件地址写位读回器件ID/版本寄存器做自检。写配置寄存器设置分辨率、转换速率、报警模式、远程通道使能。如果芯片支持写远程通道的温度上限、下限寄存器。回读刚才写的寄存器确认写入成功。这一步看起来简单但很值得养成习惯。很多芯片的ID寄存器不参与功能却能在系统调试时帮你快速区分“总线没通”和“器件没上电”。我见过不止一个人把配置写进没有收到ACK的地址还自信满满地去读温度结果读回来的数据在总线上根本没人应答折腾半天。3.2 配置寄存器里的关键项这一节我用一个表格把关键配置项和推荐值列出来具体位定义你以手头数据手册为准配置项可选范围我的推荐值理由本地通道分辨率8/10/12位12位温度监测追求细腻度远程通道分辨率8/10/12位12位远程探头对精度更敏感转换速率1/4/8次每秒等4次每秒平衡功耗与响应速度远程通道使能开启/关闭开启核心功能报警模式比较器/中断根据应用选择见后续章节有一点不要搞混分辨率越高单次转换时间越长。在需要快速响应过热的场景里如果非要选最高分辨率转换时间可能会拖到几十毫秒甚至上百毫秒级别报警的实时性反而被拖累。常规HVAC控制里4次每秒的转换速率配合12位分辨率已经足够控制环路的温度采样周期一般也在几百毫秒级别。3.3 温度数据拼接与换算温度数据一般存在高字节和低字节两个寄存器里。12位分辨率下数据寄存器是左对齐还是右对齐不同芯片不一样。我以常见的右对齐方式举例高字节里是温度整数部分和高3位小数低字节里是低8位小数。换算公式很直白对于12位分辨率每个LSB对应的温度是1/16 ℃即0.0625℃。你把高字节左移8位再和低字节按位或得到16位原始值然后右移4位因为12位只有高12位有效得到带符号的10位整数部分2位小数部分等等我捋一下12位右对齐时高字节的bit11到bit4才是数据低字节的bit3到bit0是小数的低位。实际换算时常规做法是// 伪代码读取温度高字节和低字节拼出12位数据 uint16_t raw (reg_high 8) | reg_low; int16_t signed_raw (int16_t)(raw 4) 4; // 处理符号位对齐到16位 float temperature_c signed_raw * 0.0625f; // 12位分辨率下每LSB0.0625℃这个0.0625的来历很简单满量程0x1000对应4096个LSB分成0到255度这种量程。你不需要记这些只需要记住12位分辨率下LSB是1/16度换算时乘以0.0625即可。如果选了10位分辨率每个LSB对应0.25℃8位分辨率下则是1℃每LSB。代码里最好用配置好的分辨率动态选择缩放因子不然改了个配置忘了改系数整个系统的温度显示会整体错乱。远程温度和本地温度在寄存器布局上通常是独立的地址换算方式完全一致。我实际代码里写了一个通用函数传入寄存器起始地址统一读取和换算float read_temperature_c(uint8_t msb_reg, uint8_t lsb_reg) { uint16_t raw i2c_read_reg(msb_reg) 8; raw | i2c_read_reg(lsb_reg); int16_t sign_adjusted (int16_t)(raw 4) 4; return (float)sign_adjusted * 0.0625f; }注意一点读取两个寄存器时最好用I2C的重复起始位连续读取避免中间被其他总线器件插入操作读到高低字节不是同一时刻转换结果的情况。个别芯片还提供了“数据寄存器冻结”的功能可以在读一组数据期间锁定转换结果有的话务必打开。4. 报警阈值设定与抗误报设计4.1 阈值与滞回温度报警这件事难点不在怎么开报警而在怎么不瞎报警。HVAC设备运行的时候温度本来就是波动的压缩机启停、风机转速变化、室外气温波动都会让远程探头读数上下跳。如果你把报警阈值卡得很紧实测中一天能误报几十次运维人员到最后直接把报警屏蔽了那这套系统就白做了。我的经验是报警阈值一定要设两个值——报警门槛和恢复门槛也就是“滞回”。举个例子。某台HVAC设备的冷凝管温度正常运行时在45℃到55℃之间波动我设的报警上限是60℃恢复门槛设到55℃。当温度冲到60℃以上触发报警后要等温度回到55℃以下才解除报警而不是回到59℃就解除。否则温度在报警点附近反复横跳报警状态就会变成高频抖动继电器、风扇会被反复启停搞坏。阈值的具体数值要结合你设备的热特性去统计不能拍脑袋。我建议你先让设备在正常工况和各种极端工况下跑几天记录温度波形再去定阈值。4.2 比较器模式与中断模式的取舍PJ85718DM这类芯片的报警输出引脚一般支持两种行为模式这在配置寄存器里选。两种模式的差异非常关键模式行为适用场景比较器模式温度超过阈值FAULT引脚拉低回落到阈值以下引脚自动释放直接驱动风扇、继电器等硬件保护电路中断模式温度超过阈值FAULT引脚拉低并锁存主控读状态寄存器后清除需要主控软件介入处理的复杂逻辑比较器模式的优点是硬件自主性高。一旦主控程序跑飞只要传感器芯片还在正常工作它依然会把FAULT脚拉低去触发风扇控制电路这在做安全保护时是很有用的。缺点是没有“锁存”报警恢复后引脚自动释放如果你事后想追溯刚才是否发生过高温度从引脚状态看不出来必须由主控持续记录。中断模式则适合做软件层面的联动处理比如超温后不仅要开风扇还要关压缩机、给上位机发告警。锁存机制保证主控不会错过某次超温事件因为需要主控主动读寄存器才能清除报警。我在HVAC这个项目里用的是双保险报警引脚用比较器模式直接并联到一个风扇控制继电器同时引脚也接到PIC18F85J50的GPIO中断让主控知道报警发生了、记录下时间。硬件保护和软件记录两条路互不依赖。4.3 软件防抖策略虽然芯片硬件上有了滞回软件层面我还是加了第二道保险二次确认。具体做法是主控通过GPIO中断得知报警状态变化后不立即执行联动动作而是主动读一次PJ85718DM的状态寄存器确认报警标志真的置位了。如果只是引脚毛刺或电磁干扰导致的瞬间拉低状态寄存器的标志位大概率没有真的置位这时候直接忽略即可。另外在温度数据层面也可以做数字滤波。我常用的是滑动窗口取中值每次读到的温度样本放入一个长度为5的环形缓冲取中间值作为当前有效温度。这种方式相比简单平均能有效剔除因为电快速瞬变产生的尖峰读数而且不会像平均值那样把真实的温度上升趋势抹得太平。这里要提醒一下数字滤波的时间常数不要拉太长。我见过有人为了追求稳定把滤波窗口拉到几十个样本结果温度已经冲到70℃了系统显示还在65℃慢慢爬等报警触发时设备早就过热损伤了。温度滤波只要做到“剔除毛刺”这个程度就行不要把真实的热惯性也滤掉。5. I2C实测PIC18F85J50与PJ85718DM的通信调试5.1 主控侧I2C时钟设置PIC18F85J50的MSSP模块工作在I2C主机模式时时钟速率由波特率寄存器决定。公式是I2C时钟频率 Fosc / (4 × (I2CBRG 1))如果你用外部晶振8MHz再启用PLL到48MHz想要400kHz快速模式那就把I2CBRG设成这样的值I2CBRG 48MHz / (4 × 400kHz) - 1 30 - 1 29这个值是按内部总线时钟Fosc计算的。MSSP模块分频后的SCL频率不可能精确到每个位周期正好400kHz因为你还要加上总线上的上升沿时间、从机时钟扩展占用的时钟周期。实测下来I2CBRG设29SCL实际频率大约在390kHz上下完全能满足快速模式通信。我在调试时不会直接开400kHz去跑而是先用100kHz标准模式把通信打通确认传感器能正确响应然后再提到400kHz。这样做的好处是一旦高速下通信异常你可以快速排除“器件地址写错”这类低级问题专心查波形。5.2 调试中踩过的三个坑这一节都是真金白银换来的经验。第一个坑ACK丢失数据读出来全片是0xFF或者0x00。原因前面在上拉电阻那节提到了总线上升沿不够快。但我第二次碰到这个现象时上拉电阻并没有问题最后查出来是远程探头的屏蔽层在传感器端没有接地悬空屏蔽层变成了天线干扰串到了I2C总线边上。把屏蔽层接好地ACK就恢复了。所以排查ACK问题时先别急着改代码。拿示波器看SDA的上升沿如果是“慢慢爬上去”的弧线优先怀疑上拉。如果上升沿很陡但读不到正常数据优先查地线环路和信号干扰。第二个坑温度读数偶发跳变比如-40℃和80℃瞬间来回跳。这类问题十有八九出在读寄存器时序上。前面说过读取温度高字节和低字节之间如果转换结果恰好更新了就会出现高低字节来自两个不同转换周期的情况拼出来的数值完全是乱的。解决办法就是打开寄存器更新冻结功能或者连续读两遍、确认两遍结果一致再采用。第三个坑I2C通信完全无响应但代码看起来逻辑没问题。这种时候一定别只盯着一颗芯片。检查PIC18F85J50的MSSP模块到底是哪个。这芯片有两个MSSP模块和你初始化时用的模块号要一一对应。如果模块号写错主控发的I2C请求根本不会出现在PJ85718DM的引脚上表现出来就是总线一直忙、但外设毫无反应。用逻辑分析仪挨个量SCL/SDA引脚立刻就能看出来时钟到底打没打上去。5.3 用逻辑分析仪验证时的关键判据我调试这套I2C系统时从来都是挂着逻辑分析仪再跑固件的。验证通信是否正常看三个关键点第一SCL线在主机开始通信后必须有一段连续稳定的时钟脉冲。如果SCL拉低后一直不释放是被从机时钟扩展卡住了重点查从机的初始化序列有没有完成。第二SDA上的地址字节最低位读写位之后的第九个时钟周期SDA必须被从机拉低也就是ACK位。没有这一下拉低说明器件地址不对或者从机不在总线上。第三读温度寄存器时重复起始位之后主控发送的读命令后面跟随的字节数要和你的代码一致。多读一个字节可能导致从机提前进入空闲状态。有了这三个判据I2C调试基本可以在分钟内定位到问题层级。6. HVAC的工程化处理与实测误差校准6.1 嵌入式板级与HVAC探头安装的差异同样是双通道温度监测嵌入式板级场景和HVAC整机场景处理方式差别很大。嵌入式场景里本地通道和远程通道之间的距离一般就在一块板子上感温探头可以直接贴到被测对象表面。温度范围窄通常0到85℃对响应速度要求不高重点是长期稳定性和趋势跟踪。这种场景下你只需要注意探头和被测面的热接触质量。拿导热硅脂填充探头和被测表面之间的缝隙比单纯压紧效果要好得多。我实际测过同一颗传感器涂导热硅脂和不涂稳态读数差了接近1℃这个差距在判定过温时是致命的。HVAC场景则复杂不少。远程探头动不动要放到室外机格栅、风道深处或者压缩机管路附近。这些地方温度范围宽、环境恶劣、电磁干扰强线缆也长。这就要在前面提到的屏蔽双绞线基础上额外注意探头本身的封装防护。我建议把远程探头做成金属套管形式内部灌导热胶固定感温结金属管一端直接接触被测管壁线缆从另一端引出并加装防水接头。还有一个HVAC特有的点是探头安装位置的选择。很多人把温度探头直接绑在铜管表面觉得只要贴合就好其实不然。探头要装在能代表真实介质温度的位置比如管道的弯头下游一段距离而不是紧贴着冷媒入口处。冷媒入口存在明显的温度分层那里的读数波动大、代表性差用来做控制参考很容易出问题。6.2 误差来源与校准补偿把PJ85718DM的本地通道和远程通道实测跑起来之后你会发现读数多少和真实温度有些偏差。误差来源主要有这几个远程探头引线的串联电阻。线越长、线径越细串阻越大。远程通道某个测量原理下每1Ω串阻会引起大约0.5℃的读数偏移具体系数看芯片型号的数据手册所以长线应用一定要做串阻补偿或提前校准。远程探头脚上的寄生电容。电容过大会拖慢激励电流的建立时间导致测到的PN结压降偏低、温度读数偏低。这也是为什么前文建议滤波电容不要一味加大10nF已经算上限。本地通道的板上自热。传感器芯片自己发热、相邻功率器件发热都会让本地通道读到的温度高于真正“环境温度”。解决方法是尽量把传感器位置避开热源或者在软件里做静态修正项。整体校准我推荐做两点校准。流程很简单把远程探头和一个高精度参考温度计精度优于0.1℃绑在一起放到恒温槽里。在低温点比如10℃等稳定后记录系统显示温度与参考温度的差值。在高温点比如60℃重复一次。用这两组数据算出校准斜率和偏移量写入PIC18F85J50的Flash或EEPROM在温度换算后做线性修正。校准完成后再用第三个温度点验证如果三个点都控制在±0.5℃以内整套系统就可以放心交付生产了。最后再分享一个细节技巧量产的时候每块板子都会做一次温度回路自检。我会在软件里加一个自检模式由PIC18F85J50向PJ85718DM写入一个强制温度值再读回来比对。这样就能在不依赖外部恒温设备的情况下快速验证芯片和主控通信链路是否良好。这条自检路径在售后诊断时也保留下来现场工程师插上调试口就能判断是探头坏了还是芯片通道坏了不用拆机翻半天。这套本地加远程的温度监测方案我从打样到小批量产跑了一整年最深的体会是硬件连接要稳寄存器配置要细报警逻辑要和设备实际工况匹配。尤其是远程通道的滤波和屏蔽处理前期多花一点心思后面现场调试能省很多事。你照着这个思路去移植到自己的板卡上应该能少走不少弯路。