1. 先拆标题:这其实是两套测温需求
做嵌入式测温和暖通空调(HVAC)控温,大家习惯性方案是“NTC热敏电阻 + ADC采样”。这个套路本身没毛病,但如果你现在遇到的问题是:既要测控制板自己所在环境的温度,又要测设备内部另一个位置的温度,并且还想把数据挂到总线上给主控统一处理,那NTC方案就会变得很啰嗦——两路NTC要两路ADC,还要做分压网络、查表、线性化,每一路都得标定。这个时候,PJ85718DM配合STM32F446ZE的做法就值得认真看看。
PJ85718DM本质上是一颗带I2C接口的数字温度传感器,内部同时支持本地测温通道和一路远程测温通道。本地通道测的是芯片自身环境温度,远程通道则是通过外接一个三极管(或二极管)来测“放在远处的那个点”。STM32F446ZE在这套系统里负责挂I2C总线、读寄存器、做温度换算、跑控制逻辑,顺便处理报警中断。两颗芯片一组合,就解决了“本地温度 + 远端温度 + 数字化传输 + 可校准”这一整条链路。
这篇内容适合谁?正在做恒温控制器、风机盘管温控、设备内部温度监控或者嵌入式电控板测温模块的开发者。也适合那些已经用NTC方案被标定问题折腾过、想换数字化测温方案的人。看完之后你至少能知道:硬件上怎么接,软件上怎么读,HVAC场景里远程测温怎么标定才靠谱,以及一些纯靠看数据手册根本发现不了的坑。
2. 硬件连接与PCB布局容易忽视的3个细节
2.1 引脚逻辑与I2C总线的搭法
PJ85718DM的引脚逻辑和常见的I2C温度传感器差不多,关键引脚基本是:本地测温通道(就集成在芯片内部)、远程D+和D-引脚、I2C的SCL和SDA、以及地址选择引脚和报警输出引脚。第一版设计里,我最担心的不是芯片本身,而是把远程三极管的极性接反。远程通道的D+和D-,接到的是外部三极管的发射结,通常用基极和集电极短接的形式当作正极接到D+,发射极接到D-。也就是说,使用PNP三极管时方向会反,很多第一次用的人在这里就栽了跟头。
I2C总线这块,STM32F446ZE默认要用开漏模式,然后外部加上拉电阻。上拉阻值的选法有个讲究,总线电容小时用4.7kΩ,走线长、节点多时降到2.2kΩ。我这边两根线各接了2.2kΩ上拉到3.3V,实测总线波形干净,没有振铃。速度方面,这颗芯片标准模式100kHz和快速模式400kHz都支持,但HVAC设备里一般控制板和工作噪声源比较多,我建议先用100kHz跑通功能,再考虑提速度,别一上来就追求400kHz,后面排查电磁干扰时会多很多麻烦。
PJ85718DM的从机地址取决于A0、A1两个引脚的高低电平组合,出厂默认状态上电后常用地址是0x48。如果你板子上同时挂了多颗同类传感器,或者和某些eeprom地址冲突,就靠这两个引脚错开地址。我第一次调试时犯过一个低级错误:把A0和A1都悬空了,结果某些批次芯片读地址不稳定,时好时坏。后来给两个引脚都拉了固定电平,才彻底稳定。
2.2 远程二极管选型和走线规则
远程通道本质上测的是外接二极管PN结的压降随温度变化的关系,所以选型很简单,一颗小信号三极管就够用。常见做法是拿2N3904或者2N2222,把基极和集电极短接,等效成一个二极管,接到D+和D-之间。很多人问,我直接用普通二极管行不行?能用,但三极管的BC短接结构在宽温度范围内线性度更稳,而且三极管的一致性比二极管好,批量生产时换货也容易。HVAC应用里,这个“远程温度点”一般就是回风温度、送风温度、或者水管表面温度,探头可以用金属壳的三极管封装贴到测量目标上,再用导热硅胶固定,响应速度不错。
走线规则是最容易被低估的。D+和D-是非常敏感的小信号差分对,PCB上这两根线要平行等长走,尽量短,不要跨越电源和继电器等强干扰源正下方。线间距控制在0.2mm以上,别太近。如果工艺允许,在D+和D-之间放一个10pF到100pF的滤波电容,可以滤掉高频噪声,但容值不能贪大,太大会导致远程温度响应变慢甚至读数偏低。信号线远离继电器、变压器这类感性干扰源,这点在HVAC设备里尤其重要,因为继电器通断瞬间的干扰能让你远程温度读数凭空跳好几度。如果远程探头离主板比较远,比如超过30cm,最好用屏蔽双绞线,屏蔽层单端接地,而不是普通排线。
2.3 模拟侧电源和地去耦的实操
PJ85718DM的电源脚VDD和地脚GND之间必须放去耦电容,这个不用说。但我实测下来,0.1uF陶瓷电容是标配,如果电源纹波偏大,再加一个1uF到10uF的钽电容或电解电容。重点是这两个电容要靠近芯片的电源引脚,不是随便放在板子任何位置。STM32F446ZE本身工作在180MHz主频,高频数字电路的地弹噪声对温度传感器的模拟测量会有影响,所以尽可能把温度传感器的模拟地和MCU的数字地在单点汇合。如果PCB面积允许,我建议在PJ85718DM的电源入口加一个磁珠,阻断高频噪声串入。
还有一点,报警引脚ALERT是开漏输出,使用时要接上拉电阻。这个引脚在HVAC系统里建议不要直接驱动继电器,只能进MCU的GPIO或者中断控制器。原因很简单,继电器的吸合电流会拉低电压,干扰报警信号的电平判断。我有一块板子偷懒没注意,直接把ALERT连到了三极管驱动电路上,继电器动作时MCU频繁误触发温度报警中断,排查了整整半天才找到原因。
提示:远程测温的精度很大程度取决于外部三极管的布局和走线质量,硬件完成后先做一次连线检查,比上电后再测量调试省时间得多。
3. 软件实现:从寄存器映射到可用驱动
3.1 寄存器布局和上电默认值
PJ85718DM这类I2C温度传感器的寄存器结构和行业内常见的兼容方案高度相似,基本是一个“配置寄存器 + 两个温度数据寄存器 + 两个阈值寄存器 + 一个迟滞寄存器”的结构。这里我基于自己调过的同类型芯片列出通用映射,实际使用请以官方数据手册的寄存器表为准。
| 寄存器功能 | 常见地址 | 说明 |
|---|---|---|
| 本地温度寄存器 | 0x00 | 16位,高字节为整数部分,低字节为小数部分 |
| 远程温度寄存器 | 0x01 | 16位,远程通道测量值 |
| 配置寄存器 | 0x03 | 控制分辨率、转换模式、报警极性等 |
| 远程上限报警阈值 | 0x05 | 超过该值触发报警 |
| 远程下限报警阈值 | 0x06 | 低于该值触发报警 |
| 本地上限报警阈值 | 0x07 | 本地通道报警上限 |
| 本地下限报警阈值 | 0x08 | 本地通道报警下限 |
上电默认状态一般是连续转换模式、11位分辨率。如果你不做任何配置,直接读温度寄存器也能读到数据,但11位分辨率只有0.125°C,对HVAC的0.5°C控温精度要求勉强够用,想做得稳一点,我会把它配置成更高分辨率模式。配置寄存器里还有一个关键位是“屏蔽报警”或者“比较器/中断模式选择”,这在风机盘管这类设备上很重要,后面报警处理章节会详细展开。
3.2 初始化与单次/连续读取流程
软件流程其实很简单,全流程就是:初始化I2C外设,配置传感器寄存器,然后循环读温度。这里给出我实际用的初始化代码,基于STM32的HAL库,逻辑比较清晰。
#define PJ85718DM_ADDR (0x48 << 1) #define REG_LOCAL_TEMP 0x00 #define REG_REMOTE_TEMP 0x01 #define REG_CONFIG 0x03 void PJ85718DM_Init(I2C_HandleTypeDef *hi2c) { uint8_t cfg = 0x00; // 建议高分辨率模式,连续转换 cfg |= 0x0C; // 根据具体数据手册设置,这里示意 HAL_I2C_Mem_Write(hi2c, PJ85718DM_ADDR, REG_CONFIG, I2C_MEMADD_SIZE_8BIT, &cfg, 1, 100); }连续读取模式下的主循环读取函数要注意一点:温度寄存器是16位数据,读取时先读高字节再读低字节。某些多字节读操作如果总线时序没有处理好,中途被中断打断,高字节和低字节会错位,温度会出现突然跳到几百度的奇观。我习惯的做法是连续读两个字节,一次性拿回高字节和低字节,而不是分两次单独读。
float PJ85718DM_ReadRemoteTemp(I2C_HandleTypeDef *hi2c) { uint8_t buf[2] = {0}; int16_t raw = 0; HAL_I2C_Mem_Read(hi2c, PJ85718DM_ADDR, REG_REMOTE_TEMP, I2C_MEMADD_SIZE_8BIT, buf, 2, 100); raw = ((int16_t)buf[0] << 8) | buf[1]; // 14位分辨率下,量化为0.0625°C/LSB return (float)raw * 0.0625f; }温度转换里有个小细节,raw直接转成int16_t是为了保持负数也能正确换算。比如零下的温度寄存器读出来是二进制补码,如果不做符号扩展,一个-5°C的读数会被算成251°C。这个错误在HVAC冬季工况里最容易撞上,因为回风温度低于零度很常见。所以我的建议是,这里千万别用无符号整型去算。
3.3 偏移校准与报警阈值写入
很多人拿到传感器读出一个温度就急着用,但我踩过几次坑之后明确告诉你:每颗芯片、每个远程探头装在具体结构里的实测温度,和寄存器原始值之间总是有偏差的。偏差来源主要是传感器自身误差、探头安装位置误差、以及探头热阻抗导致的响应滞后。解决办法就是做两点校准,把“读到的值”映射到“真实温度”,这个后面一章详细展开。
报警阈值寄存器也需要通过I2C写入。写入流程和读温度寄存器类似,都是先写寄存器地址,再写两个字节的阈值数据。唯一要注意的是,阈值数据格式和温度寄存器分辨率是一一对应的,你在配置寄存器里选了什么分辨率,阈值寄存器就用什么分辨率,否则报警点的实际触发温度会和你预期的不一致。HVAC场景里,比如回风温度报警点设置为55°C,如果分辨率配错,可能实际60°C才报警,这问题不致命但很烦。
4. 远程测温的标定方法与HVAC场景结合
4.1 为什么HVAC要标定而不直接采信
HVAC设备的工作环境比实验室恶劣得多。恒温控制器装在风机盘管旁边,探头贴在水管表面,夏天管路里是7到12°C冷冻水,冬天则可能是60°C热水,期间还有冷凝水、电磁阀开关的干扰。这种情况下,远程探头测到的温度和设备真实工况温度差个1到2°C非常正常。如果不标定,控制器就会按照一个偏高的温度去调节,导致压缩机或者电加热器频繁启停,能效下降甚至影响设备寿命。我第一次做风机盘管控制器的时候,就是因为没做标定,直接采信远程原始值,导致水温控制曲线整体偏移,冷量输出总是差一口气。
标定的本质,是修正系统性偏差。远程通道的二极管测温原理决定了它的曲线是相对线性的,所以两点标定就够用。一个点在低温区,一个点在高温区,把测量值和参考值对齐,然后整条直线的斜率和截距就确定了。
4.2 NTC方案与二极管方案的取舍
在HVAC行业里,NTC还在大面积使用,但当你同时需要本地和远程两路温度时,差别就出现了。这里用个表来对比一下:
| 对比项 | NTC + ADC方案 | PJ85718DM本地+远程方案 |
|---|---|---|
| 本地温度测量 | 需要额外NTC和分压电阻 | 芯片自带,零外围 |
| 远程温度测量 | 需要第二个NTC,走线长还要做导线电阻补偿 | 三极管可以做远端探头,走线相对不敏感 |
| 线性度 | NTC指数曲线,需要查表或多项式 | 近乎线性,直接乘系数 |
| 标定成本 | 两路都要逐点标定 | 本地基本免标,远程两点标定 |
| 总线集成 | 需要MCU的ADC资源 | I2C一条总线挂多颗 |
如果你只是在板内测个温度,NTC完全够用,成本还低。但一旦牵扯到远程测量,NTC的长引线误差和自热误差会变得很难受。PJ85718DM这种方案的好处是远程探头走的D+和D-是高阻抗差分信号,对线电阻不像NTC那么敏感,设备生产时省很多人工校准的成本。
4.3 实测步骤:两点标定怎么做
标定流程不需要精密温箱,一个可靠的参考温度计加点耐心就行。我的做法是:先在板卡通电、探头处于自然室温状态下,记录传感器读数和你认为的可信参考值;再把探头放到一个稳定的高温点,比如60°C的水浴里,等待读数稳定后记录第二组数据。
然后套用线性校准公式:
斜率 = (T2参考 - T1参考) / (T2原始 - T1原始) 修正后的温度 = (原始温度 + 截距) / 斜率说一个真实的计算例子。比如探头放在25°C环境里,传感器读到26.5°C;放60°C水浴里,传感器读到61.8°C。那斜率就是(60 - 25) / (61.8 - 26.5) = 35 / 35.3 ≈ 0.9915。修正后的温度就是原始读数乘以0.9915,再减去一个偏移量。为什么减偏移量?因为使用斜率修正后,还需要用任何一个已知点回代求出偏移,确保修正后的值和参考值对齐。这套逻辑在代码里就是两个float参数,存到EEPROM里,量产时每台设备写入一次即可。
注意:标定过程中探头必须和测量对象充分热接触,否则标定数据本身就是漂移的,后边怎么修正都是错上加错。
5. 常见问题与排查技巧实测集锦
5.1 读数为零或满量程
远程温度读数在任何温度下都稳定在负值极限(比如-64°C或者-128°C),或者固定读数完全不变化,大概率是远程二极管没接好。D+和D-之间如果没有形成有效导通,传感器的远程测量通道就会给一个满量程异常值。排查方法是先测量二极管两端是否确实有约0.6V左右的正向压降,再用示波器看D+/D-波形是否正常。我遇到过最隐蔽的一次,是三极管封装引脚折弯后和PCB焊盘虚焊,外观完全正常,但温度读数一直飘,后来拿放大镜检查才发现是锡裂。还有次是设备组装时把探头线接反,整个批次的温度全部读成乱码,所以装配图纸上一定要把探头极性画清楚。
本地温度读数正常,远程温度显示为满量程,还有可能是使用了PNP三极管而不是NPN。PNP接法的偏置方向相反,理论上有极性翻转功能,但很多兼容芯片不一定支持,稳妥做法还是选NPN,BC短接后发射极朝下接到D-。
5.2 I2C总线异常与地址冲突
STM32F446ZE在180MHz主频下运行,I2C总线出问题大多是时序问题而非CPU问题。表现为系统上电后第一次读温度能读到数据,运行一段时间后再读就挂死。这种我建议优先检查I2C的时钟配置,确认在标准模式或快速模式对应的CCR值是否正确,开漏输出有没有配置到位。另外一个常见坑是上拉电阻只接了SDA没接SCL,或者两边阻值不对称,导致总线高电平驱动能力不足,出现偶发性应答丢失。
地址冲突的问题集中在多设备共用总线时。PJ85718DM的地址引脚如果全部接高或全部接低,地址可选范围就有限。我在某块板上同时挂了三颗温度传感器和一颗EEPROM,结果地址全挤在一起,总线上有两颗芯片同时应答,数据直接乱掉。解决方式是给每颗芯片分配不同地址,并且绘制原理图时就把地址表列出来,别等PCB打样回来再想办法。
5.3 报警误触发与迟滞处理
HVAC设备里温度报警误触发的最常见原因是继电器吸合瞬间的电磁干扰,而不是真实温度超限。现象是:报警引脚偶尔拉低,MCU读取报警标志有值,但你紧接着去读温度寄存器,温度却又在正常范围。这是瞬时干扰耦合到了D+和D-线上,导致远程通道测到毛刺信号。物理层面可以在D+/D-加滤波电容,软件层面则是在报警中断服务函数里加一个延时确认,再读取两次温度做确认,只有连续确认才认定为真报警。
配置寄存器里的迟滞位值得好好利用。默认情况下,温度传感器是高于上限值立刻报警,且必须回落到上限值以下一定数值才解除报警。这个特性其实很有用,当我们检测回风温度时,冬天刚开机,回风温度还没上来,持续报警会让人误解设备故障。我通常会把迟滞配置成2°C甚至3°C,让报警行为更贴近实际业务,避免反复跳变。迟滞值过大也会导致温度已经恢复正常,报警还一直挂着,所以要根据设备类型权衡。
6. 写在最后的个人体会
这套方案让我最满意的地方,是把远程测温这件原本很“模拟”的事,简化成了“I2C读两个寄存器”这么简单。说实话,第一次把远程三极管探头接到PJ85718DM上,看到温度数据在串口里稳定刷新的时候,我的第一反应是“怎么这么轻松”,对比以前调NTC还要对着电阻分压表和温度表一个个算,体验确实不一样。
不过也要泼盆冷水,任何温度传感器方案都不存在“焊上去就能用”的童话。PJ85718DM + STM32F446ZE这个组合,核心优势是把问题集中到了少数几个点上:远程探头选型、PCB走线、两点标定、报警迟滞。这四个点处理好,整个系统的温度测量稳定性就能超过大部分NTC方案。如果后续你想再扩展,可以考虑把这个温度数据和PID控制结合,做风机盘管的三速调节;也可以通过本地和远程的温度差值判断设备风道是否堵塞。我自己的下一步是打算把远程探头换成一个封装更大的三极管,看看热响应能不能再快一些,毕竟暖通里面最讨厌的就是传感器响应慢半拍。