做HVAC控制器这些年温度采集这块我一直不太愿意用传统的NTC热敏电阻方案。原因很简单NTC换一个电阻封装就要重新标定一次ADC通道还要单独校准而且在现场强电干扰下引线稍微拉长一点读数就飘。后来在一个项目里把PJ85718DM和MK51DN512CLQ10搭在一起用才算把“本地温度”和“远程温度”两路监测一次搞定。这篇文章就围绕这套组合把硬件连接、寄存器操作、固件读取、现场排障和校准经验完整梳理一遍给正在做嵌入式环境监控或者HVAC控制板的朋友一个可参考的落地思路。1. 为什么用“本地远程”双通道HVAC 温度监测的真实需求1.1 HVAC 场景里“本地”和“远程”分别指什么HVAC 系统里温度监测从来不是一个点的事。控制器主板本身要防过热芯片、功率器件、电源模块的温度得盯着这是“本地温度”同时风管、回风、送风、压缩机表面、冷凝器盘管这些位置也要测这是“远程温度”。传统做法是本地一路 NTC 加远程一路 NTC每路都占一个 ADC 引脚还要在电路上做分压电阻、滤波电容批量生产的时候每块板子都要校准。用 PJ85718DM 这类带本地和远程双通道的数字温度传感器情况就简单很多。本地通道测芯片自身或 PCB 附近的温度远程通道通过一对 D/D- 引脚外接一个二极管探头就能测几米外的目标点温度。它的远程通道走的是二极管正向压降随温度变化的原理和 NTC 完全不同抗干扰能力和线缆长度容忍度都高不少。我实际用下来的体会是这种结构特别适合 HVAC 控制器板子内部温度一片外部关键点温度一片两个数据都通过同一个 I2C/SMBus 总线读到主控里不需要额外的信号调理电路校准工作量也大幅下降。1.2 为什么选择 PJ85718DM 而不是普通热敏电阻NTC 方案在 HVAC 里很常见但它有几个绕不开的痛点。首先 NTC 是非线性的温度越高阻值变化越平缓需要查表或者用 Steinhart-Hart 方程做拟合其次 NTC 的标称阻值和 B 值存在离散性批量生产时一致性要靠选档或软件标定来兜底再者 NTC 导线一旦靠近继电器、接触器这些强电器件采样值很容易被干扰。PJ85718DM 属于数字输出型温度传感器温度数据直接通过总线以数字形式传输MCU 不需要做 ADC 采样也就不存在基准电压误差和采样时序抖动的问题。远程通道虽然外接的是二极管通常是 2N3904/2N3906 这类三极管的 BE 结或者专用的二极管探头但传感器内部通过在不同电流下测量二极管压降差来计算温度抵消了二极管绝对压降离散性的影响。这个原理让它对探头本身的个体差异不敏感换一个探头基本不需要重新校准。要说明的是我没有拿它去做超低温或者超高精度的计量级应用那种场景还是得靠 PT100/PT1000 加高精度 ADC。但在 HVAC 这种 -20°C 到 125°C 的范围内±1°C 左右的精度完全够用而且它是数字接口系统集成成本低很多。1.3 MK51DN512CLQ10 在这套方案里扮演什么角色MK51DN512CLQ10 是 Kinetis K51 系列里带 512KB Flash 的 Cortex-M4 主控用来做 HVAC 控制器比用 8 位单片机从容不少。它的 I2C 模块支持标准模式和快速模式用来和 PJ85718DM 通信非常合适同时它还跑着 Modbus 通信、风扇 PWM 控制、继电器逻辑、LCD 显示这些任务温度读取只是其中一个任务模块。在这个方案里MK51DN512CLQ10 负责三件事初始化 I2C 总线并配置 PJ85718DM 的工作模式周期性读取本地和远程温度寄存器换算成真实温度值根据温度阈值做报警判断把结果分发给控制逻辑或者上传给上位机。K51 系列另一个实用点是它的 GPIO 带上拉使能配置可以减少外部上拉电阻的依赖。不过我在实际项目中还是外挂了 4.7kΩ 上拉后面会专门说原因。总的来说这颗 MCU 的性能余量很大温度采集只占用它很少的资源剩下的算力都留给控制策略。2. 硬件连接从传感器引脚到 MCU 引脚的完整链路2.1 PJ85718DM 典型引脚定义与接线拿我这块测试板来说PJ85718DM 的引脚功能大致分四组电源、I2C 总线、地址选择、远程二极管接口。电源引脚接 3.3VVCC 和 GND 之间放一个 0.1uF 去耦电容位置尽量靠近芯片。SDA、SCL 是总线引脚分别接 MK51DN512CLQ10 的 I2C0 对应引脚并配上拉电阻。地址选择脚一般有两个A0 和 A1通过高低电平组合可以让传感器在 I2C 总线上占用不同地址。这在我这个项目里很有用因为控制板可能同时挂两个温度传感器一个测控制器内部温度另一个测风管温度靠不同的地址区分总线只要一组。OS/ALERT 引脚是开漏输出的比较器输出可以配置成中断输出。我把这个引脚接到了 MK51DN512CLQ10 的一个 GPIO 上并使能了上升沿中断用于温度越限时的快速响应。平时主控不需要轮询温度状态等报警触发再说这样 CPU 占用率更低。实际接线时要注意SDA、SCL、ALERT 都是开漏结构必须接上拉电阻否则总线拉不高通信直接失败。我习惯用 4.7kΩ总线速度在 100kHz 到 400kHz 之间都很稳。如果总线上挂的设备多可以适当降到 2.2kΩ但注意不要低于 1kΩ否则驱动电流偏大对传感器和 MCU 都不友好。2.2 远程二极管探头怎么接D 和 D- 的布线要点PJ85718DM 的远程通道有两根线D 和 D-。远程探头最常见的做法是拿一颗小信号三极管比如 2N3904把基极和集电极短接当作二极管用。基极-集电极短接的那一端接 D发射极接 D-这样就能形成传感器需要的二极管结构。布线方面高铁军规有一条D/D- 必须走双绞线或者紧贴在一起的平行线并且周围用地线包住。我踩过坑一开始图省事用普通的杜邦线飞了两根线出来长度大概 80 厘米结果读数在 25°C 附近反复横跳波动超过 3°C。后来换成双绞线读数立刻稳定下来。原因很简单远程通道的测温原理基于毫伏级的二极管压降测量线上的噪声和寄生电容都会直接影响测量结果。双绞线可以抑制共模干扰同时要避免 D/D- 在 PCB 上长距离并行走线防止两条线之间形成寄生电容耦合。还有一点经验远程探头线尽量不要和继电器控制线、220V 动力线走同一个线槽尤其是距离超过半米的时候。HVAC 设备里继电器动作瞬间会产生很强的感性尖峰如果温度线贴得太近轻则读数跳变重则把传感器内部电路打坏。我在测试中发现即便用了双绞线只要和动力线平行走线超过 1 米远程温度在继电器动作前后还是会有 0.5°C 左右的波动这在要求严格的场合是不可接受的。2.3 HVAC 现场环境下的信号完整性与防护措施HVAC 控制柜里是典型的电磁干扰环境接触器吸合、断开、变频器开关、风机启停这些都会在电源和信号线上制造噪声。这套方案里I2C 总线本身是低速总线抗干扰能力还行但远程二极管线属于高阻抗模拟前端必须重点保护。我的做法是在 D/D- 靠近传感器入口的位置各串联一个 1kΩ 到 2.2kΩ 的电阻然后对地并联一个 1nF 到 10nF 的滤波电容。这个串联电阻并不会破坏测温因为传感器测的是电流切换下的压降差而串联电阻上的压降是固定的只要两个测量点的激励电流不变电阻的影响就可以忽略。这个细节其实很多参考设计里都有但实际布板时容易被省略。I2C 总线这边也要考虑防护。传感器和主控如果不在同一块板上或者中间通过连接器走线建议在总线引脚上并联 TVS 管。我用的是一颗双向 TVS 阵列能同时保护 SDA、SCL 和 ALERT。另外HVAC 控制板经常工作在温度变化大的环境中PCB 上要注意避免传感器周围有大电流走线否则本地温度读数会被 PCB 上的热点干扰测出来的不是空气温度而是铜箔温度。3. 寄存器与协议SMBus 交互的底层逻辑3.1 温度数据寄存器与读取格式PJ85718DM 这类 SMBus 温度传感器内部寄存器布局基本遵循一个约定通过写入命令寄存器地址来选择要读的数据然后用重复起始条件repeat start读回数据。我这边用的寄存器布局是这样的0x00 是本地温度数据0x01 是远程温度数据高字节0x10 是远程温度数据低字节0x02 是状态寄存器0x03 是配置寄存器0x04 是转换速率寄存器0x05 到 0x08 是本地和远程的高/低温度报警阈值。本地温度一般是一个字节分辨率为 0.5°C/LSB以二进制补码表示。远程温度则是两个字节高字节是整数部分低字节的高几位是小数部分合起来能达到 0.125°C 的分辨率。读取的时候必须把高低字节都读出来并且注意高低字节之间要连续读防止传感器在两次读取之间更新了数据导致高低字节不是同一时刻的快照。虽然在实际使用中这个问题影响很小但严谨的做法是连续读完再合并。3.2 状态寄存器与报警阈值寄存器的使用状态寄存器里通常有几个标志位远程温度高于上限、远程温度低于下限、本地温度高于上限、本地温度低于下限还有远程二极管开路/短路检测标志。我在固件里每次读取温度后都会顺便读一下状态寄存器把报警标志保存下来但不立即处理而是在任务循环里统一判断。报警阈值寄存器的用处是让传感器自己在超限时拉低 ALERT 引脚这样 MCU 可以用中断方式知道温度异常而不是一遍遍轮询。阈值是 8 位有符号数分辨率同样是 0.5°C/LSB写入时需要先把目标温度乘以 2 转成整数再写入。比如想设置远程温度 85°C 报警就要写入 0xAA因为 85 * 2 170 0xAA。关于阈值的设置我想多说一句在高温度波动频繁的 HVAC 环境里不要把上阈值设得和正常工作温度太近否则 ALERT 引脚会频繁触发主控的中断处理会被淹没。我通常把远程温度上阈值设成正常工作最高温度加 10°C 到 15°C比如正常 65°C 的工况报警阈值设到 80°C。3.3 MCU 侧 I2C 外设与传感器的交互关系MK51DN512CLQ10 的 I2C 外设支持主模式收发使用上和大多数 Cortex-M 平台的 I2C 模块类似。关键在于它需要先把引脚复用配置成 I2C 功能这一步很多人容易漏。我在初始化时把 SCL 和 SDA 引脚复用为 ALT2 功能并开启内部上拉然后配置 I2C 分频系数。SMBus 和 I2C 在电气层面基本兼容逻辑上略有区别。PJ85718DM 支持 SMBus 的快速命令协议比如写一个字节、读一个字节、读两个字节。对 MCU 来说实现这些操作不需要太复杂的协议栈只需要按部就班地做启动、发地址写、发寄存器地址、重复启动、发地址读、连续收字节、停止。有一点要注意SMBus 的 SCL 低电平超时特性在某些传感器里存在但大多数此类传感器并不强制要求主控支持超时复位。我这边没有实现 SMBus 超时检测只依赖 I2C 通信失败后的软件重试机制实测运行很稳定。4. 固件实现从 I2C 驱动到温度计算的完整代码4.1 I2C 初始化与单次温度读取流程MK51DN512CLQ10 的固件我用的是寄存器级配置没有依赖特定 SDK 版本方便后续移植。初始化部分把 I2C0 模块时钟打开配置引脚复用设置波特率。以外部 16MHz 晶振、总线时钟 48MHz 为例I2C 分频寄存器配置成的 100kHz 总线频率足够用了。下面是 I2C 初始化的核心代码void I2C0_Init(void) { SIM-SCGC4 | SIM_SCGC4_I2C0_MASK; // 打开 I2C0 模块时钟 SIM-SCGC5 | SIM_SCGC5_PORTB_MASK; // 打开 PORTB 时钟 PORTB-PCR[2] PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; // SCL下拉 PORTB-PCR[3] PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; // SDA下拉 I2C0-C1 0; // 关闭 I2C I2C0-F 0x17; // 配置分频约 100 kHz I2C0-C1 I2C_C1_IICEN_MASK | I2C_C1_MST_MASK; // 使能 I2C主机模式 }启动位和停止位的处理我做成两个小函数发送地址和收发数据的过程都在一个状态机里跑。实际项目中我没有用阻塞等待的方式而是在中断里维护一个简单的队列但因为代码比较长这里先用阻塞方式说明核心逻辑。4.2 远程温度和本地温度的换算公式读取远程温度的完整 I2C 序列是这样的先发设备地址加写位再写寄存器地址 0x01然后发重复起始再发设备地址加读位连续读两个字节高字节和低字节最后发停止位。远程温度的高字节是 8 位有符号数单位是 1°C低字节的高 3 位是小数部分每一位代表 0.125°C。所以合并后的温度值可以这样算int16_t remote_raw_to_temp(uint8_t hi, uint8_t lo) { int16_t temp (int8_t)hi; temp * 8; temp (lo 5); // 取低字节的 bit7~bit5各代表 0.125°C return temp; // 单位0.125°C } float remote_temp_c remote_raw_to_temp(hi, lo) * 0.125f;用这个公式比如高字节读回 0x41十进制 65低字节读回 0x20bit5 置位那么温度就是 65 * 1 1 * 0.125 65.125°C。这个分辨率放在 HVAC 场景里完全够用。本地温度更简单它就是高字节的一个字节1 LSB 代表 0.5°C直接用有符号转换float local_temp_c (int8_t)local_byte * 0.5f;我在代码里把两个温度值都转成了浮点型方便后续直接在 Modbus 寄存器里上报避免在业务逻辑里反复做定点换算。4.3 报警配置与故障恢复逻辑报警配置需要在初始化时把四个阈值寄存器都写一遍。这些阈值寄存器都是 8 位有符号数以 0.5°C 为步进。例如本地温度上阈值设为 70°C就写入 0x8C70 * 2 140。写阈值寄存器的代码逻辑和写任何配置寄存器一样先发写命令指定寄存器地址然后写入数据字节。我在配置完成后会再读回来验证一次防止 I2C 干扰导致写入失败。这一点在批量生产中比较重要因为如果报警阈值没写进去设备可能在超温时没有任何反应。故障恢复方面我加了三个处理通信失败重试、报警状态轮询、远程二极管异常检测。如果连续三次 I2C 读操作都返回错误我在固件里会重启 I2C 模块并重新初始化传感器同时把故障记录到错误日志。远程二极管如果开路或者短路状态寄存器里的对应标志会置位这时远程温度读数没有意义我直接把远程通道标记为故障而不是把错误的温度数据送进控制逻辑。5. HVAC 落地场景与现场实测排障5.1 风管送风温度监测长线远程探头的实用调整风管送风温度是 HVAC 控制里最常用的参数之一。我在这套系统里把远程二极管探头固定在风管内部导线从风管引到控制板实际走线距离接近 1 米。初期测试时遇到的问题是读数比风管内的参考温度计低了大约 0.8°C而且波动偏大。排查下来发现主要原因有两个。其一是远程探头没有做导热封装只是裸二极管放在风管里和空气的换热不充分响应速度慢其二是 D/D- 在控制柜内部那段走线贴近了一块开关电源的散热片引入了热量影响。解决办法是把探头装进一个铜制的小套管里套管再伸进风管既增加了导热面积又屏蔽了辐射干扰。另外一个实用经验如果风管内部有凝露风险探头要做好密封处理否则水汽凝结在 D/D- 之间会改变漏电流温度读数会慢慢偏移。我后来在探头外面套了热缩管只露出感温部分这个问题就解决了。5.2 压缩机壳体温度监测继电器动作时的抗干扰处理压缩机壳体温度通常用于判断压缩机是否过载运行。这个测量点距离控制箱往往有 2 到 3 米而且中间要经过压缩机本身的电源线、接触器控制线干扰非常严重。我在这套系统上实测过一次接触器闭合的瞬间远程温度读数偶尔会跳变 2°C 到 3°C持续几十毫秒后恢复。虽然这个短暂的跳变不足以触发误报警但如果阈值设置得比较紧可能导致误动作。处理方案分为三层第一层在传感器端 D/D- 上增加 1nF 差分电容吸收高频干扰第二层在 MCU 固件里做软件滤波连续采样三次取中值第三层是遇到温度跳变超过 5°C/100ms 的情况直接丢弃该次采样等待下一轮。三层叠加后继电器动作对读数的影响彻底消失了。如果你也在类似的场景里做温度采集我建议别急着改硬件滤波参数先把示波器探头接到 D/D- 上看清楚干扰波形是共模还是差模再对症下药。盲目加电容会把传感器的响应速度拖慢反而影响实时性。5.3 空调控制器本地过热保护本地通道的独特价值本地通道的典型用途是做控制器自身过热保护。MX51DN512CLQ10 这类 MCU 虽然运行温度范围宽但 HVAC 控制柜夏天在阳光直射下内部温度可能达到 70°C 以上功率器件就更热了。PJ85718DM 的本地温度感应来自芯片内部或 PCB 上的热通路读到的数据能真实反映主控芯片附近的温度状况。我在这套系统里做了一件事把本地温度作为降频策略的输入。当本地温度高于 65°C 时控制逻辑会降低风扇 PWM 最低转速加强散热高于 85°C 时直接进入保护模式关闭部分输出。这个逻辑在连续高温天的运行中确实触发过几次保护动作准确。值得提醒的是本地温度测的是传感器芯片自身的结温或封装温度不是空气温度。如果 PCB 上有一块发热严重的功率器件本地温度会被它拉高这时候要判断是应该做整机散热还是局部隔热处理不要一味降低控制器的输出能力。6. 调试校准与批量生产的最后一步6.1 总线时序的验证方法新板子第一次上电我最先做的事不是看温度读数而是用示波器抓 I2C 波形。SDA 和 SCL 的时序是否正确、是否存在毛刺或低电平毛刺这些用万用表根本看不出问题。示波器抓取起始条件、停止条件和数据位电平确认地址字节正确之后才会跑固件里的读取逻辑。如果波形看起来不对第一排查方向是上拉电阻值。总线上升沿太缓说明上拉电阻偏大或者总线电容过大如果出现台阶可能是总线上的设备有冲突或者地址冲突。这里有一个经验MCU 内部上拉和外部上拉同时使能时波形可能因为上下拉驱动能力差异出现小台阶所以我在最终量产版本里故意禁用了内部上拉只保留外部 4.7kΩ 上拉波形干净很多。远程温度读数的验证则要靠示波器的 D/D- 波形。正常工作时D/D- 上能观察到传感器内部切换电流产生的微小电压跳变大约几毫伏到十几毫伏。如果看不到这个跳变多半是探头断线或者 D/D- 接反了。6.2 远程探头校准用冰点做基准的实操流程远程通道的校准流程我的习惯是先把 D/D- 短接看传感器返回的错误状态确认开路检测正常然后用一个已知特性的二极管探头在恒温槽里和基准温度计对比记录误差曲线。在条件有限的情况下冰水混合物是一个很容易获得的 0°C 基准。做法是把探头密封好后放进冰水混合物中等读数稳定后记录误差值。需要注意的是探头要完全浸没且不接触冰块本身避免局部温度不均。0°C 校准做完以后再用手握着探头调到人体温度附近做第二个点基本能保证 0°C 到 50°C 这个常用区间足够准确。另一个实际经验是如果传感器的远程通道支持多个偏置电流档位校准前要把电流档位固定下来因为不同档位下测到的二极管压降差略有不同切换档位会导致读数偏移。我在这套系统里固定在一个档位不动省去了很多麻烦。6.3 批量生产的统一性注意事项批量生产时温度传感器方案比 NTC 省心的地方在于无需逐板标定但也不是完全不需要注意。我的建议是每块板子在出厂测试时做一次总线通信自检读一次传感器 ID 和温度确认焊接和贴片没有问题。地址冲突是批量生产中比较容易出现的问题。如果一块板上多路传感器共用同一组 I2C 总线贴片机必须保证 A0/A1 引脚焊接正确否则两片传感器的地址会重复导致总线上设备互相干扰。我在设计 PCB 时给 A0/A1 预留了 0Ω 电阻切换位方便生产不同型号时调整地址避免重新改板。固件升级也要考虑寄存器兼容性。不同批次的同型号传感器寄存器定义可能会有细微差异。稳妥的做法是固件启动时读取传感器 ID 寄存器校验型号不匹配就进入错误日志并停止温度采集而不是在未知状态下运行控制逻辑。我把这套方案在空调控制器和空气处理机组上都跑过连续运行几个月的稳定性比之前 NTC 方案好很多。如果你也在做类似的东西建议第一步就用示波器把总线时序和远程二极管波形抓清楚这一步省不了后面所有调试都会顺利得多。