从做嵌入式温控的那天起温度采集就绕不开一个问题控制器自己待的环境温度和远端真正要控的风管温度到底怎么同时测准。我之前在做一款壁挂式HVAC控制器时试过MCU内置ADC加NTC的常规方案结果被精度、线性和走线干扰反复折腾。后来换成PJ85718DM这颗双通道数字温度传感器配合PIC18F96J94作为主控才把本地温度监测和远程温度监测两件事同时做得干净利落。这篇就把整个方案的原理、硬件、软件、标定和调试陷阱完整梳理一遍给同样在做暖通温控、嵌入式测温和板级温度管理的朋友做个参考。PJ85718DM的特点是一颗芯片同时输出两路温度一路是芯片所在位置的本地温度另一路是通过外接半导体二极管或三极管测量到的远程温度。PIC18F96J94则负责通过I2C总线读取数据、换算、滤波再配合报警窗口和环境控制逻辑。这套组合很适合HVAC里常见的风机盘管、新风机组、恒温恒湿控制箱也适合工业嵌入式设备里对板温和远端热源同时监控的场景。1. 为什么暖通控制器要同时盯两路温度1.1 HVAC应用中的“本地温度”到底是哪里很多刚入行的朋友会以为“本地温度”就是室内空气温度其实不然。在HVAC控制器里本地温度通常指的是控制板所在位置的温度也就是PJ85718DM芯片自己感受到的那片PCB附近的温度。这个温度经常比真实环境温度高出好几度因为控制板上有变压器、DC-DC、继电器驱动、通信模块等发热源如果控制器外壳不透风热量会在板内累积。本地温度监测的意义主要有三个。第一是保护控制板当板温超过比如85°C警戒值说明散热出了问题可能是风机停转、滤网堵塞或者安装在阳光直射位置这时候面板要给出报警并且适当降频运行。第二是参与补偿逻辑很多温控系统会依据板温推断外部环境趋势比如板温快速上升代表室外气温在升高可以提前调整压缩机运行策略。第三是冷凝预防在湿度高的地方板温如果接近露点PCB可能凝露这时候需要启动加热器或者关闭冷源。1.2 “远程温度”测的是什么、为什么要测远程温度才是HVAC控制系统的“真实目标”。比如风机盘管系统要把回风温度控制在设定值附近温度传感器就必须装在风管回风口或者盘管附近而不能装在主控板上。又比如冷库、新风系统需要在几十米外布点这时候远程温度的“远程”二字就名副其实了它指的是远离主控器的温度感知点。远程测温方案里PJ85718DM提供一个专门的外部传感器接口利用半导体PN结的物理特性来测量远端温度。测温点离主控板可以有几米甚至更远只要传感线处理得好精度依然能保持在标准范围内。更重要的是远程通道和本地通道共用同一套ADC和校准逻辑相当于一颗芯片干了两颗芯片的活还省掉了外置NTC的调理电路。1.3 为什么不用MCU ADC加NTC的走法说到这可能有人会问直接用MCU内置ADC测NTC分压不是更简单吗成本还低。确实很多低端温控器就是这么干的但它在HVAC场景里问题非常多。NTC的B值离散性很大即使是1%精度的NTC在-20°C到80°C范围内也能带来大约1-2°C的差异要做好必须逐台校准。ADC内部参考电压往往不够稳电源纹波和地弹会直接耦合进采样结果。NTC走线一长线阻和EMI干扰就会叠加进去想区分到底是线的问题还是温度变化都难。相比之下PJ85718DM把模拟测温、ADC转换、线性校正、报警比较全部集成在芯片内部直接通过I2C输出数字量精度稳定、一致性高省掉了大批校准工时长期可靠性也更好。所以如果设备需要精确控制、需要多路测温、需要抗干扰能力强数字温度传感器加MCU才是更稳的组合。PJ85718DM这类双通道芯片更是把“本地远程”的需求打包处理了。2. PJ85718DM的测温机制ΔVbe原理是关键2.1 本地通道片上带隙基准PJ85718DM本地温度测量用的是经典的半导体带隙测温结构简单说芯片内部有一个PN结和一个恒流源把PN结正向压降随温度变化的信号进行比例放大再经过ADC转换成数字量。这个原理和很多片上温度传感器相同优点是稳定、线性好缺点是它测的是芯片自身的结温和PCB环境温度之间会有热阻差。在HVAC应用中本地通道的读数会受走线铜箔、旁边功率器件、外壳材质影响。所以PCB布局时别把PJ85718DM放在发热源正旁边否则本地温度读数会有明显的系统偏高。这一点后面硬件章节会展开讲。2.2 远程通道测PN结的ΔVbe远程测温是PJ85718DM比较有含金量的部分它并不是直接测远端二极管的绝对压降而是测两个不同偏置电流下的Vbe差值也就是所谓的ΔVbe方法。PN结的正向电压Vbe本身会随温度变化大约是-2mV/°C但绝对值和二极管的饱和漏电流Is强相关而Is在不同二极管、不同批次之间离散很大所以直接测Vbe是做不准的。ΔVbe方法的巧妙之处在于让同一个二极管先后流过两个电流I1和I2两次Vbe之差满足公式ΔVbe (k × T / q) × ln(I2 / I1)其中k是玻尔兹曼常数q是电子电荷T就是绝对温度。这个公式里没有Is也就是说二极管个体差异基本被抵消了测出来的ΔVbe只和两路电流之比以及绝对温度有关。只要电流比例恒定读出ΔVbe就能反推温度。当然实际还有几个修正项需要处理。首先是晶体管的理想因子η也就是发射结电流-电压关系里的非理想系数不同型号的二极管和三极管η值可能从1.0到1.08不等如果芯片不支持N因子修正远程测温会整体偏移1°C以上。所以PJ85718DM会提供一个N因子校正寄存器让软件根据实际使用的二极管型号做补偿。其次是远程传感线本身的串联电阻和寄生电容串联电阻会造成Vbe测量偏高通常用低阻走线或者软件补偿来消除。2.3 寄存器与I2C基础PJ85718DM与MCU之间走I2C或SMBus协议器件地址低位由外部地址引脚决定芯片默认地址常见是0x38这类范围。内部寄存器布局大致分为温度寄存器、配置寄存器、上下限报警寄存器、N因子校正寄存器等几个区段。本地温度寄存器和远程温度寄存器都是16位宽的低四位是小数部分。I2C通信时要先发送寄存器指针再连续读取两个字节。PIC18F96J94的MSSP硬件模块可以直接承载I2C主机功能不需要用GPIO模拟省掉不少软件负担但要注意在读写多字节时处理好ACK和REPSTART时序。代码层面我习惯把温度读取封装成一个函数先通过I2C写寄存器地址0x01远程温度然后连续读两个字节再经坐标转换得到有符号的16位温度值最后乘以0.0625°C得到实际温度。只要这个函数稳定上层控制逻辑怎么调用都方便。3. 硬件接入设计布线、保护与抗干扰3.1 远程传感元件的选型与接法PJ85718DM的远程通道一般推荐使用分立二极管或者PNP三极管。用三极管时标准做法是把基极和集电极短接让发射结作为测温PN结这时Vbe的线性度最好。常用的型号有SOT-23封装的小信号三极管价格便宜热响应也快。选型时重点看封装热阻和额定电压别拿大功率管太大反而因为自身热容大而响应迟钝。传感器和芯片之间的连接方式如果是三线制可以提供更好的抗干扰能力但如果走线很短两根线也够用。我一般在传感器端加一个0.1μF旁的滤波电容在芯片端的D和D-引脚之间加一个低通RC比如100Ω串联电阻加1nF对地电容可以滤掉高频噪声对ΔVbe测量的干扰。注意电容不但是并联在D和D-之间有些设计是各引脚对地各接一个小电容加上差分结构实际效果也类似。3.2 走线长度、寄生电容和RC滤波远程通道最容易翻车的地方是走线寄生电容。PJ85718DM在测量ΔVbe时需要激励电流通过传感线给二极管充电如果线上电容太大电流建立的时间不够ADC采样会读到虚低的ΔVbe导致显示温度偏低。所以远程传感器走线不是越长越好。经验值上1米长度内用普通双绞线问题不大超过2米就要考虑屏蔽线并且要降低采样速率、增加转换时间。某些应用里把传感器放到了十几米外那就不能指望直接用这个接口了得在远端加调理电路或者改用总线式传感器。额外要留意的是PWM噪声、继电器电弧、变频器开关噪声。HVAC配电箱里同时存在220V接触器和可控硅这些干扰源离远程走线一近温度读数就会像心电图一样抖动。最佳的防护思路是远程线与强电走线分槽、远离继电器本体、在芯片输入端守住RC滤波同时在软件上做滤波和异常值丢弃。3.3 本地通道的PCB布局本地通道看着简单实际上坑也不少。PJ85718DM测的是芯片模具内的结温但芯片与周围环境之间的热阻决定了它测出来的温度和旁边空气温度有多大差别。如果芯片紧邻DC-DC电感、MOS管或者LED驱动电路那么本地温度读数会显著偏高严重时偏高十几度。正确做法是把PJ85718DM放置在独立于发热区的铜箔上避免和其他发热元件的铜皮大面积相连。在板子上开热隔离槽或者让芯片附近不铺大铜皮可以让读数更接近真实环境温度。另外PJ85718DM的两根I2C线上要加2.2kΩ左右的上拉电阻到VDD上拉电源建议和MCU供电同源避免电平不匹配。ALERT引脚通常作为报警输出外部需要上拉电阻。它的极性和触发条件可以通过寄存器配置。在硬件上我建议ALERT输出接一枚0Ω电阻方便调试时割线隔离也允许软件动态改接口方向。4. 基于PIC18F96J94的软件实现4.1 I2C主机时序与多字节读取PIC18F96J94的MSSP模块配置成I2C主机模式后写操作和读操作分别处理。写寄存器时先发送START再发器件地址写位然后发送目标寄存器指针再发送数据读温度时要先把指针写到目标寄存器再发START或者REPEAT START最后发送器件地址读位并读取数据。我贴一段在PIC18F96J94上用MSSP读取PJ85718DM远程温度寄存器的核心代码方便理解整个时序逻辑#define TEMP_REMOTE_REG 0x01 #define PJ85718_ADDR 0x70 // 实际地址按硬件接线调整 uint16_t read_remote_temp_raw(void) { uint8_t raw[2] {0}; uint16_t out 0; // 发送寄存器指针 i2c_start(); i2c_write(PJ85718_ADDR 1); // 器件地址 写位 i2c_write(TEMP_REMOTE_REG); // 指向远程温度寄存器 i2c_stop(); // 重新开始-读模式 i2c_restart(); i2c_write((PJ85718_ADDR 1) | 1); // 器件地址 读位 raw[0] i2c_read(1); // 读高字节主机回ACK raw[1] i2c_read(0); // 读低字节主机回NACK i2c_stop(); out ((uint16_t)raw[0] 8) | raw[1]; return out; }这里的细节有两点一是读最后一个字节时主机要回NACK告诉从机不用再发数据二是如果中间忘了发REPEAT START芯片会一直待在写状态读回来的全是乱码。另外PIC18F96J94的I2C时钟频率在标准模式下不要超过400kHzHVAC环境里我习惯用100kHz标准模式抗干扰能力明显更好。4.2 12位补码换算与符号处理PJ85718DM的温度寄存器高12位是有效数据低4位是小数部分。数值以二进制补码形式存放最高位是符号位。换算公式很简单将16位数据右移4位得到12位有符号整数小数部分等于寄存器低4位乘以0.0625°C这部分要注意的有符号数处理。比如寄存器值0x0FF0高12位是0x0FF对应31.875°C而0x0FF1是负数需要先按符号扩展成16位再计算。C语言里可以这样处理float raw_to_temp_c(uint16_t raw) { int16_t val (int16_t)(raw 4); // 逻辑右移得到12位整数再符号扩展 // 注意如果芯片定义是12位补码需要按下式还原符号 if (val 0x0800) { val val - 0x1000; // 12位符号扩展为16位 } float frac (float)(raw 0x000F) * 0.0625f; return (float)val frac; }不同芯片的寄存器定义可能略有差异有的芯片低四位对应0.625°C步进有的对应0.5°C一定要以手册为准。调试时最简单的验证方法是芯片放入冰水混合物读到的值应在0°C附近正负0.5°C如果偏差大多半是换算倍率或者符号处理有误。4.3 报警窗口配置HVAC控制里温度上下限报警比频繁轮询更省资源。PJ85718DM的报警寄存器允许分别设置本地温度上限、本地温度下限、远程温度上限、远程温度下限。超过设定窗口后ALERT引脚拉低MCU可以靠外部中断来响应而不必每个控制周期都轮询温度值。配置报警窗口时步骤是先关闭比较模式写入上限和下限寄存器确认无误后再使能报警并使能相关中断。不要在上限和下限设置完成之前就打开报警使能否则会出现中间状态的误触发。报警模式还分比较模式和中断模式比较模式下温度回到窗口内后ALERT会自动释放中断模式下需要MCU读状态寄存器清除报警标志ALERT才会释放。HVAC设备里我习惯用比较模式少一层处理面板上也够用。4.4 滤波与数据有效性判断温度本身变化慢但在HVAC配电箱里远程通道的读值经常伴随毛刺。软件滤波是不可少的。我常用一阶低通滤波公式就是y(n) y(n-1) alpha × (x(n) - y(n-1))alpha取值0.1到0.3左右采样周期1秒时既平滑又不迟滞。还要加一个异常值丢弃策略。如果当前采样值和上一次滤波结果差超过5°C就认为是毛刺本次采样不参与滤波连续出现三次异常时再报警防止传感器真的断路或者短路时被滤波掩盖掉。断路时远程通道读数往往接近最低值或者最高值短路时读数可能接近0°C这些情况要单独检测并报故障码。5. 标定与实测误差从哪来、怎么修正5.1 标定流程和工装PJ85718DM这类芯片在出厂时已经做过基准校准本地通道一般误差在±0.5°C以内远程通道的误差则和传感器本身、走线电阻、N因子设置强相关所以远程通道才是标定重点。标定时我用的工装包含一个恒温槽或者恒温箱一支经过计量校准的标准温度计若干固定在测温点上的远程传感器以及一块把PIC18F96J94和PJ85718DM连好的测试板。将远程传感器和标准温度计探头放进恒温槽在0°C、25°C、50°C、70°C几个点稳定后分别记录芯片输出值和标准温度计读数然后计算误差曲线。5.2 各类误差来源和修正手段不同误差源的表现和修正方法整理如下表误差来源典型表现修正手段远程二极管个体差异η全温区整体偏移设置N因子校正寄存器导线串联电阻高温区读数偏高越高温越明显缩短接线、增大电流比、软件串阻补偿走线寄生电容读数偏低且随频率变化加RC滤波、降低采样速率电源纹波等于扰信号耦合读数跳动大、不稳定加强滤波、远离干扰源、用屏蔽线本地热源耦合引起布局温差本地通道恒定偏高物理隔离、调整PCB布局有趣的是串联电阻误差在高温段容易被忽略。远程通道本质上测的是ΔVbe串联电阻上会产生一个额外的差分电压整体叠加进测量值温度越高这个相对误差越大所以修正时要看曲线斜率不能只做零偏修正。5.3 实测数据记录我在某次样机测试中的记录如下。使用一支SOT-23三极管作为远程传感器恒温槽稳定后读取的数据为标准温度(°C)远程读数(°C)本地读数(°C)修正后远程(°C)0.20.825.10.325.025.440.625.050.351.062.750.270.171.380.970.0可以看到本地通道因为板内发热源影响读数一直比恒温槽高很多这是正常现象本地通道是用来做板温保护的不需要等于环境温度。远程通道修正后误差控制在±0.3°C以内对HVAC控制来说已经很够用。修正量在常温段和高温段基本一致说明主要误差来自N因子而非线性问题。如果在多个温度点修正偏移后曲线还是不平比如低温偏差小、高温偏差大就要重点检查串联电阻和寄生电容了。6. 调试复盘三个真实踩坑与排查链路6.1 远程读数乱跳走线耦合了PWM噪声第一块样机上电后远程温度读数在室温下乱跳波动幅度有0.3-0.5°C明显超出正常范围。用示波器测远程通道D和D-之间的波形看到上面叠加了周期性的尖峰频率和板上风机PWM调速信号一致。排查链路线是先确认PJ85718DM的供电电容没问题再检查传感器走线最终定位到远程线在PCB上刚好平行走了一段旁边就是流过PWM信号的排线。噪声通过寄生电容耦合进了高阻抗的D/D-线。解决办法是调整走线位置让远程线远离PWM走线并在D/D-之间增加1nF差分电容。改完后跳动降到0.05°C以内问题解决。这个坑提醒我硬件评审阶段看远程走线时不只是看长度和阻抗更重要是看它周围还有什么信号在跑。高阻抗测温线在EMC面前非常脆弱预防胜于补救。6.2 本地温度系统性偏高贴太近电感另一个问题是本地通道读数始终比实际室温高8°C左右一开始我怀疑是芯片寄存器换算问题还专门做了恒温箱测试但恒温箱里读数是准的说明芯片没问题。回到整机状态才明白样机把PJ85718DM放在了板子靠近DC-DC电感的区域电感发热把板温拉高了芯片测的是板温而非空气温度。这个场景说明一个本质问题本地通道永远是芯片附近的物理温度它不等于“机壳外空气温度”。如果产品需要本地温度代表环境温度就必须在结构上做热隔离芯片远离发热器件、通过导热材料与机壳接触、或者将测温点做成外置探头。后来我在同一块板上把PJ85718DM挪到靠接插件的位置并在两者间铜皮上开了热隔离槽本地读数降到了只比环境温度高1-2°C的程度可以接受。6.3 I2C总线偶发挂死超时恢复与总线释放这个坑最隐蔽。系统连续跑十几个小时后面板温度突然不再刷新看门狗没有触发但程序卡在I2C读流程里。用逻辑分析仪抓总线发现SCL长期被拉低说明从机PJ85718DM进入了一种异常状态而MSSP主机一直在等待时钟释放。排查链路从硬件开始先检查上拉电阻是否太小导致驱动能力不足实测2.2kΩ没问题再检查是否有人为把ALERT引脚拉出低电平导致地址冲突也没有。最终把可疑点聚焦到I2C规范里的总线超时机制上。PJ85718DM作为SMBus兼容设备总线空闲超时后可能进入复位状态但PIC18F96J94的MSSP模块如果不做超时处理就会一直等下去。修复办法分两层。硬件上ALERT引脚通过一个二极管与SCL做总线复用保留了兼容性但主控端改用GPIO轮询软件上给I2C主机加了超时判断通过定时器在50ms内未收到ACK就强制复位MSSP模块然后发9个额外时钟脉冲释放SDA和SCL。这之后连续跑了一周没有再复现。最终的软件保护措施我建议每个项目都保留任何I2C操作都设置超时、任何读取失败都走错误恢复流程、连续错误计数达到阈值就重启总线。不要依赖看门狗把整个MCU从异常状态拉回来I2C层面的恢复要快得多。这几个坑走完对PJ85718DM和PIC18F96J94这套组合的脾气摸得比较透了。核心体会是远程测温精度高不高一半靠芯片原理另一半靠你的布线和软件容错。芯片本身已经把模拟前端做得很省心但如果走线随意、滤波缺失照样会翻车。希望这篇整理能帮做嵌入式温控和HVAC控制的朋友少走几段弯路。