PJ85718DM与STM32F334R8实现HVAC双通道温度监测方案
做 HVAC 控制板的工程师多半在某个项目需求里见过这句话本地温度和远程温度都要监测数据还要进主控参与控制逻辑。本地温度通常指电路板附近或者机柜内部的温度远程温度则可能来自几十厘米到几米外的盘管、风道、功率器件表面两路都属于刚需却又没有人愿意为了这两路单独搭一套模拟采集链路。我的常规做法是用一颗双通道数字温度传感器直接搞定PJ85718DM 配 STM32F334R8 就是一套已经跑过多个模拟项目的组合。PJ85718DM 属于本地/远程双通道数字温度传感器本地通道把芯片自身所在位置的温度直接数字化远程通道通过一对差分引脚外接测温二极管两个读数都走 I2C 输出STM32F334R8 只负责取数、滤波、报警和联动控制。相比用 NTC 加 ADC 的方案省掉了分压电阻、查表、线性化和逐批校准这些脏活。这篇文章就按我实际做过的方式把这套方案的硬件布线、寄存器操作、温度换算、校准方法以及 HVAC 现场常见的坑完整过一遍给准备在嵌入式或者暖通项目里做双温度监测的朋友一个能直接抄作业的参考。这个方案适合两类人一类是在 HVAC 变频电控或者工业控制板上做主控软件开发想快速给现有系统加温度监测的另一类是刚开始选型正在纠结用模拟 NTC 还是数字传感器的新手。后面我会把为什么这么选、每一步怎么连、代码怎么写拆开讲清楚。1. 方案拆解PJ85718DM 与 STM32F334R8 搭配的价值在哪1.1 本地与远程双通道到底在测什么PJ85718DM 这类芯片的思路说穿了一文不值把两个不同位置的温度测量集成到一颗芯片里。本地通道测的是传感器自己封装附近的温度也就是电路板局部环境温度远程通道通过 D/D- 两个引脚外接一个二极管结通常是三极管的 BE 结测那个二极管所在位置的温度。两颗测温点一颗芯片出数字结果这就是整套方案的立足点。HVAC 场景里这个需求非常高频。以风机盘管控制板为例本地通道紧贴控制板测回风温度或机箱空气温度远程通道用铠装探头贴在盘管出水铜管上测水温两个温度一起参与防冻保护、风机转速补偿和能效计算。冷凝机组更直接本地测控制柜环境温度远程测压缩机排气管表面温度过温时立刻切压缩机。嵌入式场景则是本地通道测板上功率器件附近的温升远程通道测电机绕组、散热器或者电池包外壳两个数据合成一条温升曲线。这类应用有个共同特点两个测温点之间的距离大概在 0.1 到几米范围要求精度在 ±0.5℃ 到 ±1℃ 之间并且希望主控能直接拿到数字量做逻辑判断。PJ85718DM 正好卡在这个需求区间本地通道常规精度在 ±1℃ 以内远程通道经过校准也能做到类似水平。1.2 为什么选 STM32F334R8 而不是普通单片机严格说读一个 I2C 温度传感器8 位单片机都绰绰有余所以选 STM32F334R8 的决定因素不在温度采集本身而在整个系统的定位。F334R8 是一颗面向电机控制和数字电源的 MCUCortex-M4F 内核72MHz 主频带硬件除法器和 DSP 指令最有特点的是 HRTIM 高分辨率定时器和多个 12 位 ADC、比较器、运放。在 HVAC 变频系统里这套外设决定了它可以同时承担压缩机/风机的驱动算法、电流采样、PFC 控制温度监测只是它顺手要做的事情之一。你不需要为了温度再挂一颗逻辑 MCU也不需要为了电机控制选一颗比你实际需求贵得多的芯片。64KB Flash 和 16KB SRAM 对完整的变频控制工程来说够用对温度采集代码来说更是毫无压力。如果只做纯温度采集节点选一颗更小的低功耗 MCU 当然更合适但那就变成另一个方案了。在这篇文章的场景里F334R8 是现成的主控PJ85718DM 是插上去的温度前端两者是“系统主控制单元加外设”的关系不是“大马拉小车”的关系。这个定位清楚了后面所有设计都不会跑偏。1.3 数字传感器与 NTC/ADC 方案的真实差距不少习惯用 NTC 的工程师会问一颗 NTC 加一个分压电阻再用 MCU 内部 ADC 采样成本不是更低吗理论上是的但把批量问题算进去就不一定。NTC 方案要面对三个麻烦第一NTC 的 B 值和阻值离散性很大换一颗料就要重新校准或者至少做温度点抽检第二ADC 参考电压、分压电阻精度、PCB 漏电流都会引入误差想做到 ±0.5℃ 需要投入不少调试时间第三NTC 天生是非线性元件必须做查表或者用 Steinhart-Hart 公式换算代码量不大但维护起来很烦。PJ85718DM 这类数字传感器把温度到数字量的转换放在芯片内部线性化、补偿都由厂家在生产时完成。你拿到的是标准 I2C 寄存器读出来就是温度误差范围写在手册里。这相当于把“模拟前端调校”这件事从你的开发清单里划掉了。对 HVAC 这种往往需要现场维护、后期批量生产的场景少一个模拟环节就少一个潜在故障点。2. 硬件接线要点把本地、远程和 I2C 都接靠谱2.1 PJ85718DM 引脚与接线速览我用的这颗 PJ85718DM 功能引脚不算多典型的双通道温度传感器封装也就八个左右的脚VCC、GND、SDA、SCL、ALERT、D、D-然后是地址配置脚常见是 A0/A1/A2有些型号标成 ADD0/ADD1。具体封装的脚位排布以你手里的手册为准但功能模型基本通用。引脚方向连接到说明VCC电源输入3.3V并联 100nF 去耦电容传感器供电GND地主控地平面单点接地远端勿跨强电地SDA双向STM32F334 I2C 数据线外部上拉漏极开路必须上拉SCL输入STM32F334 I2C 时钟线外部上拉同上ALERT输出MCU EXTI 引脚或悬空报警中断建议接上D模拟输入远程二极管正极外接测温二极管或热敏探头D-模拟输入远程二极管负极与 D 成对差分走线第一次打板时最容易犯的错是把 D、D- 画反。虽然有些芯片支持极性反转但多数情况下接反会导致远程通道始终报错或者读到明显错误的温度。原理图阶段就要在网络上标注清楚PCB 出来后先测二极管两端电压再上电别等代码跑半天才发现是硬件接反。2.2 I2C 上拉、电平与地址冲突I2C 总线是漏极开路结构上拉电阻必须自己加。工作频率 100kHz 标准模式时上拉电阻用 4.7kΩ 到 10kΩ 都行跑 400kHz 快速模式我习惯用 2.2kΩ 到 4.7kΩ具体值看总线上挂了多少设备、走线有多长。总线节点多、寄生电容大就把上拉调小否则 SCL/SDA 的上升沿变缓高速时容易出错。只有一颗传感器且紧挨 MCU 的情况下4.7kΩ 是稳妥的起步值。电平方面STM32F334R8 的 I/O 是 3.3V直接把传感器 SDA/SCL 上拉到 3.3V 即可。如果系统里还有其他 5V I2C 器件需要做电平转换或者确认传感器是否支持 5V 耐压。I2C 是双向协议光靠换一个上拉电源解决不了电平匹配除非所有器件都兼容同一个高电平范围。地址冲突是我在 BSP 阶段翻车最多的地方。PJ85718DM 的 7 位 I2C 地址由 A0/A1/A2 引脚的电平决定全部接地时常见地址是 0x48。板载 I2C 上经常还会有 EEPROM、RTC、PMIC这些器件的地址可能与之一致。画原理图时把地址排列列一张表确认唯一再定稿。2.3 远程温度探头选型与长线抗干扰远程通道的测温元件最常用的是把普通小信号三极管接成二极管使用基极和集电极短接BE 结作为测温结D 接短接端D- 接发射极。2N3904、2N3906 这类管子都很常见选型时关注封装热阻、结电容、工作温度范围。封装越小热阻越低对温度变化的响应越灵敏但小封装也意味着更怕 ESD外接探针时要注意防护。布线是远程通道真正的考验。D/D- 是模拟差分输入最好成对走线长度相等、两侧尽量对称不要跨越 PCB 分割区域更不要贴着开关电源、继电器驱动这类强干扰信号走。板内距离几十厘米内普通双绞就能工作如果探头要拉到几米外建议用屏蔽双绞线屏蔽层单端接地同时在线端加滤波。比较实用的做法是在 D/D- 引脚上各串一颗 100Ω 电阻再在进芯片前加一个 1nF 到 10nF 的差模电容组成一阶低通滤波。这个电路能有效抑制变频器 IGBT 开关耦合过来的共模干扰。经验上线电阻会直接影响远程读数量级大约是每 1Ω 线阻可能引入接近 0.5℃ 的偏差所以探头引线越长越要重视线阻补偿或者选择带线阻补偿功能的模式。2.4 电源去耦与强电干扰隔离PJ85718DM 的 VCC 引脚不要直接简单搭在数字电源上要就近放一颗 100nF 的瓷片电容离电源脚 3mm 以内为佳。传感器离电源入口超过几个厘米时再加一颗 1μF 电容。HVAC 控制板有个特点主控弱电和 220V 强电往往在同一个板子上继电器、接触器、变频驱动回路就在旁边。温度采集属于模拟量最容易受地电位差干扰。解决办法是地线区域明确划分温度传感器和探头的接地回到主控地平面不要借强电回路的地I2C 走线也不要跨越继电器下方区域。如果信号必须穿过强电区宁可绕一圈走板边也比被切地导致地电流抬高基准好。ALERT 信号若接到 MCU 中断也属于易受干扰的输入建议加一个 100Ω 串联电阻和 1nF 对地电容防止误触发。3. 软件实现从 I2C 初始化到温度上报的完整套路3.1 寄存器模型与温度换算公式PJ85718DM 这类双通道传感器的寄存器布局大同小异我这里按通用模型来写具体地址以你手里的数据手册为准。典型的寄存器结构如下寄存器地址名称作用0x00配置寄存器分辨率设置、连续/单次转换、报警极性0x01状态寄存器转换忙、远程开路/短路、报警标志0x02本地温度寄存器16 位温度数据0x03远程温度寄存器16 位温度数据0x04 / 0x05本地报警阈值本地通道 TH/TL0x06 / 0x07远程报警阈值远程通道 TH/TL温度寄存器的高 12 位是有效数据低 4 位为 0。读回来是 16 位补码格式符号位在最高位。换算公式用 C 语言表达非常直接先转成 int16_t右移 4 位后乘以 0.0625。因为 12 位分辨率下每个 LSB 代表 0.0625℃这也是这个分辨率组合下最常用的计算方式。如果配置寄存器把分辨率改成 9 位、10 位或 11 位对应的 LSB 值分别是 0.5℃、0.25℃、0.125℃右移量分别是 7、6、5。代码里最好做一个分辨率到移位量和缩放系数的映射表不要写死一个 12 位公式不然换了配置就出莫名其妙的大误差。3.2 STM32F334R8 的 I2C 初始化用 STM32 HAL 库做 I2C 初始化并不复杂核心是把外设配置成 400kHz、7 位地址模式。下面这段是 I2C1 的基础初始化我用的引脚是 PB6 为 SCL、PB7 为 SDA实际引脚以你的原理图为准。I2C_HandleTypeDef hi2c1; void MX_I2C1_Init(void) { hi2c1.Instance I2C1; hi2c1.Init.ClockSpeed 400000; /* 400kHz 快速模式 */ hi2c1.Init.DutyCycle I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 0; hi2c1.Init.AddressingMode I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 0; hi2c1.Init.GeneralCallMode I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode I2C_NOSTRETCH_DISABLE; HAL_I2C_Init(hi2c1); }GPIO 那边要把 PB6/PB7 配置为开漏复用功能并外接上拉电阻。开漏配置这一步很容易漏如果配成推挽输出I2C 通信可能会用不了或者损坏总线。初始化 GPIO 时注意使能 GPIOB 的时钟同时把 AF 设为 I2C1 的复用编号。3.3 读取温度与滤波任务怎么写读取温度最直接的方法是 HAL 的 Mem_Read 函数一次读取两个字节然后按前面的公式换算。7 位设备地址 0x48 传给 HAL 时要左移一位也就是写成(0x48 1)或者直接用宏0x48 1。static float read_temperature(uint8_t reg_addr) { uint8_t buf[2] {0, 0}; if (HAL_I2C_Mem_Read(hi2c1, (0x48 1), reg_addr, I2C_MEMADD_SIZE_8BIT, buf, 2, 50) ! HAL_OK) { return 0.0f; /* 让上层根据返回值判断异常 */ } int16_t raw (int16_t)((uint16_t)(buf[0] 8) | buf[1]); return (float)(raw 4) * 0.0625f; } float read_local_temp(void) { return read_temperature(0x02); } float read_remote_temp(void) { return read_temperature(0x03); }读取周期在 HVAC 应用里一般不需要很快200ms 到 1s 读取一次足够。温度变化本身就是慢变量过快的采样除了增加总线负载和主控负担没有实际意义。但读取慢不代表不滤波。现场设备只要有压缩机、继电器这类负载温度读数就可能在短时间内出现毛刺。最简单的做法是滑动平均滤波窗口取 8 个点既能平滑干扰又不至于让温度响应滞后到让人察觉。核心代码就是维护一个环形缓冲区每次采样替换最旧的数据返回值取均值。这样实现起来只有十几行效果却很实在。3.4 报警阈值与超温保护怎么接合理的设计不应该让主控一直轮询比较温度而要让传感器自己判断、主动报警。做法是把 TH/TL 阈值写入对应寄存器使能 ALERT 输出把 ALERT 引脚接到 STM32F334R8 的 EXTI 外部中断引脚。温度超过上限或低于下限时传感器把 ALERT 拉低MCU 进入中断服务函数置一个报警标志主循环再决定是降低输出功率、停机还是只上报警告。阈值一定要设置迟滞。比如高温报警阈值设 85℃那么恢复阈值就设 80℃不然温度在 84.5℃ 到 85.5℃ 之间抖动时ALERT 会反复触发中断频率可能高到主控什么都干不了。这类芯片一般都支持 TH/TL 两个阈值天然就是迟滞结构关键是你得把上下限写进去而不是只写一个上限。报警响应之后F334R8 这边可以联动 HRTIM 或者外部驱动直接切断压缩机输出。整个链路是温度传感器发现异常→ALERT 中断→主控确认→硬件级保护动作。这比单纯靠软件周期轮询再停机要可靠得多。4. 校准确认把误差压到 ±0.5℃ 以内的实操4.1 先搞清楚误差从哪里来哪怕是数字传感器误差也不是零。这个方案里主要的误差来源包括量化误差、远程二极管的非理想因素、线电阻、芯片自热和 PCB 温度梯度。误差来源典型影响说明量化误差12bit 时 LSB 为 0.0625℃不可避免但影响很小远程二极管非理想因素0.5℃~1.5℃不同二极管厂家的 Vbe 特性有差异线电阻每 1Ω 约 0.5℃主要体现在长引线场景芯片自热0.5℃~2℃传感器功耗越大、通风越差偏差越大PCB 温度梯度0.2℃~0.5℃本地通道测的是板温不是环境空气温度本地通道最常见的争议是“传感器明明在板子上却说自己在测环境温度”。其实它测的本来就包含 PCB 传导的热量这是物理限制解决办法是把传感器放在气流通道上、远离功率器件并保证传感器自身功耗尽量低。4.2 本地通道与远程通道的分步校准做单点校准时冰水混合物是最容易复现的 0℃ 基准。不需要特制设备保温杯里装满碎冰和少量水搅匀后静置十几分钟把探头放进去等读数稳定后记录偏差。再拿一个恒温水浴或者精度足够的标准温度计记录第二个点的偏差。有了两组数据就能做两点线性修正。软件里预留一个校准结构体typedef struct { float gain; /* 增益修正默认 1.0 */ float offset; /* 偏移修正默认 0.0 */ } temp_cal_t; static temp_cal_t local_cal {1.0f, 0.0f}; static temp_cal_t remote_cal {1.0f, 0.0f}; float apply_calibration(float reading, const temp_cal_t *cal) { return reading * cal-gain cal-offset; }两点校准的计算方法很简单实际温度分别记为 T1、T2对应读数为 R1、R2那么 gain (T2 - T1) / (R2 - R1)offset T1 - R1 * gain。把结果写进 Flash上电时加载到全局变量即可。对出厂精度已经不错的传感器实际生产中往往会发现 gain 接近 1.0主要修正的是 offset。远程通道校准时要注意探头必须和标准温度源充分接触最好用导热硅脂或者夹具压紧避免接触热阻造成的假偏差。风速、光照都会影响表面测温夹具稳定后再记录数据。4.3 批量产测怎么做才快又不翻车量产阶段不可能每台设备都做两点校准时间和成本都扛不住。我的做法是样机阶段认真做好两点校准确定固定修正参数产线阶段只做常温单点检查把测试块的温度作为一个基准设备上电读取温度误差在 ±1℃ 以内就放行偏差偏大的返回维修。产测程序第一步做 I2C 扫描确认设备地址 0x48 在线这一步能抓出漏焊、虚焊和贴错料的问题。第二步读取本地温度和远程温度分别与测试块已知温度对照。第三步把报警阈值写入芯片并读回校验防止出厂配置没烧进去。整个过程控制在几十秒内对产线节拍比较友好。比较踩坑的经验是测试块本身也有温度梯度测试前需要先等它稳定否则会把测试设备的误差当成产品误差造成误判。稳定的判断标准是连续三次读数差值小于 0.1℃再进行判定。5. 踩坑记录HVAC 现场最容易出的几类问题与排查5.1 读数异常0xFFFF、0x8000、狂跳读数出现 0xFFFF 或者 0x8000第一反应不是去改代码而是先查硬件链路。这两个值通常表示 I2C 通信失败或者传感器在转换中。排查顺序是先用万用表量传感器 VCC 和 GND确认供电在规格范围内再用逻辑分析仪抓 I2C 波形看是否有 ACK如果波形正常再读状态寄存器查看转换忙标志或者远程开路/短路标志。远程通道最容易出现的问题就是 D/D- 开路或短路。HVAC 现场探头经常是接插件连接插针氧化、端子松动、线缆折断都会导致读数突然跳到异常值。软件里要专门处理这类状态不要简单把异常值当成真实温度参与控制否则可能引发误保护或者漏保护。5.2 远程温度整体偏移好几度远程读数比实际值稳定地高或者低几度最常见原因是远程二极管选型和芯片的电流系数不匹配。很多测温二极管特性在 datasheet 里给出的典型值是针对特定偏置电流的换了一个品牌的二极管系数就会有偏差。短期的解决办法是软件校准在远程通道上加偏移量。根本的解决办法是确认二极管选型是否在传感器手册推荐的范围内尽量使用推荐型号。现场如果必须用延长线把线电阻实测出来加进 offset 里。5.3 继电器或者压缩机动作时读数跳变这个现象几乎可以确定是电磁干扰。继电器线圈吸合的瞬间会在 PCB 地线上产生尖峰电流D/D- 或者其他模拟走线受到耦合读数就会跳一跳。排查时先断开远程探头把 D/D- 对地短路看本地通道是否也会跳变。如果本地通道稳定而远程通道跳变那就重点整改远程走线和滤波如果本地也跳问题在整板层面可能是地线布局不合理或者去耦不足。整改方向有几个D/D- 加 100Ω 串联电阻和差模电容继电器线圈要加续流吸收传感器供电和主控数字电源之间加 π 型滤波强电驱动走线远离温度采样区。实测下来前两个方案对大多数情况都有明显改善。5.4 I2C 偶发卡死程序死等I2C 偶发卡死是嵌入式里很折磨人的问题。从机没有响应、总线被拉死、超时时间设太短都会导致程序卡在 HAL_I2C_Mem_Read 里。第一原则是读取函数必须带超时并且超时后做错误处理不能干等。复位从机的通用办法是让 SCL 连续翻转 9 个时钟把从机内部状态机复位。在 STM32 上如果软件控制 GPIO 模拟时序比较麻烦可以直接调用 HAL_I2C 的复位函数并重新初始化外设。如果频繁卡死则更可能是硬件问题检查上拉电阻是否过大导致上升沿不达标总线电容是否过大或者总线长度是否过长。5.5 报警误触发报警误触发多半不是阈值没写对就是 ALERT 信号受到干扰。先说阈值要确认写入 TH/TL 时用的是同一套分辨率数据格式别把 12 位数据按 9 位格式写进去那样上下限的换算完全不对。再说抗干扰ALERT 如果走线太长建议加 100Ω 电阻和 1nF 电容如果 MCU 的 EXTI 配置成了低电平触发而非边沿触发现场噪声很容易让中断连续进来改成边沿触发并在中断里加防抖判断。软件上比较稳妥的做法是中断里只置标志不立即执行停机主循环连续确认几次报警状态后再动作。迟滞阈值也一定要设尤其 HVAC 压缩机频繁启停的环境没有迟滞的报警必然被现场干扰打爆。6. 工程落地顺带要做的三件事6.1 低功耗休眠模式下的读取思路如果这个方案用在电池供电的嵌入式无线传感器上低功耗就是刚需。PJ85718DM 支持单次转换模式的话MCU 可以进入 STOP 模式定时唤醒后发起一次转换读取结果然后再睡回去。本地和远程两路如果都能在一次转换中完成整机平均功耗可以压得很低。注意从 STOP 模式唤醒后I2C 外设需要重新初始化HAL 库在低功耗模式下不会自动帮你维护总线状态。6.2 多通道扩展一路不够时怎么办一颗芯片只能测一个本地加一个远程点如果需要测三路、四路可以考虑挂多颗传感器在同一 I2C 总线上前提是地址不同。一颗把地址配置为 0x48另一颗把 A0 拉高配置成 0x49这样用同一组 SDA/SCL 就能读多路。I2C 总线地址数量就那么几个且上拉电阻和总线电容会随着节点增加而压力变大挂到三四颗以后要重新算上拉必要时把频率降回 100kHz。6.3 数据上报与联动逻辑温度读出来之后HVAC 主控往往还要把数据送给人机界面、RS-485 总线或者云端。比较省力的方式是在主控里维护一份最新温度结构体任何外设需要数据时直接访问结构体而不是临时再去发起 I2C 读取。这份数据还可以加时间戳和故障状态一旦远程通道出现断路上报的数据要带上故障标志而不是扔一个离谱的数值出去。这个“脏数据不外传”的原则在现场维护的时候能省下大量排查时间。我个人在这套方案上体会最深的一点是PJ85718DM 和 STM32F334R8 的组合真正省时间的地方并不在“把温度读出来”这一步而是把校准模块、报警中断、滤波策略这些周边机制一并想清楚之后整个系统变得非常省心。温度监测看着是配角可一旦它在运行现场不稳定故障定位的成本远高于它本身的价值。如果你正在做类似的控制板第一版就建议把滤波电容位置、校准偏移量和独立的报警中断口预留出来后面改需求和现场调试都会舒服很多。