从实际项目出发。我去年给一款商用新风机组控制器做升级,原方案用两颗热敏电阻分别测回风温度和板卡环境温度,结果每台设备都要做点校准,温度漂移还大。后来换成了标题里这套组合:PJ85718DM 做温度采集,STM32F100ZE 做主控,一本地通道加一路远程通道,一次就把问题解决了。
这篇文章把整个方案掰开揉碎讲清楚:PJ85718DM 是什么、凭什么能用一颗二极管测远程温度、STM32F100ZE 那边怎么初始化 I2C、怎么读寄存器、如何换算成实际温度,以及 HVAC 联动控制里那些容易踩的坑。想搞温度监测的嵌入式开发、做暖通控制器的新手,或者想把老产品从热敏电阻升级到数字传感器方案的工程师,都可以直接参考。
1. 方案选型:为什么是 PJ85718DM + STM32F100ZE
1.1 先拆解项目需求:本地测温 + 远程测温的区别
很多做嵌入式测温的朋友,上来就选 DS18B20 或者 NTC 热敏电阻,但是在本项目里有个特殊需求:既要测板卡附近的空气温度,又要测几十厘米外设备内部的温度,同时还希望传感器尽量少接线、抗干扰强。
“本地温度”和“远程温度”的定位完全不同:
- 本地温度,指传感器芯片本身附近的环境温度,常用来监测板级热环境、外壳温升,给系统做过热保护和风扇调速;
- 远程温度,指通过一根双绞线连接外部测温元件(通常是三极管或二极管)测到的远端温度,比如进出风口、压缩机表面、风道内温度。
为什么不用两根 NTC?因为 NTC 的一致性差、需要逐点标定,而且长线传输时线阻会直接引入误差,差个十几欧姆温度就偏好几度。PJ85718DM 这类芯片直接内置了本地测温通道和远程测温通道,远程通道利用半导体 PN 结正向压降与温度的对应关系来测温,信号以电流形式激励,长线压降不影响精度,这是它最大的价值。
1.2 PJ85718DM 的拓扑优势
PJ85718DM 从功能结构上看,是一颗支持双通道温度监测的数字温度传感器:
- 本地通道:内置一颗精度较高的温度传感器,位于芯片内部;
- 远程通道:外接一颗二极管连接的三极管(常见 2N3904/2N3906 或直接接二极管),通过测量 PN 结正向压降变化反推温度;
- 通信接口:I2C/SMBus 兼容,支持标准模式到高速模式,还带 SMBus 超时功能,这在 HVAC 控制板上特别实用,因为 SMBus 的时序更严格、能避免总线死锁。
选它还有一个现实原因:STM32F100ZE 是 Cortex-M3 内核、72 MHz 主频的低成本 MCU,外设丰富但不堆料。它本身就带硬件 I2C 控制器和丰富的 GPIO,用起来很顺手。这种 MCU 在空调外机板、新风机控制器、热泵控制器里有大量存量,升级方案时不必换主控芯片,只改外围传感器电路就能完成产品迭代。
1.3 对比其他测温方案
| 方案 | 本地测温 | 远程测温 | 抗干扰能力 | 标定难度 | 成本 |
|---|---|---|---|---|---|
| NTC 热敏电阻 | 需自搭电路 | 需两根长线,线阻影响大 | 一般 | 麻烦 | 低 |
| DS18B20 单总线 | 单点 | 无法直接外接远程探头 | 一般,时序要求严格 | 免标定 | 低 |
| PJ85718DM | 内置 | 支持,PN结测温 | 强,电流激励抗线阻 | 免标定 | 中 |
| 其他多通道 ADC + 恒流源 | 需外置传感器 | 需外置传感器 | 中等 | 麻烦 | 高 |
PJ85718DM 的优势非常明显:免标定、两端都覆盖、I2C 接口跟大部分 MCU 直接对接。如果产品还要做多路监测,比如同时测冷凝器进出口温度,替换成四通道版本的同类芯片也是同一套驱动逻辑,迁移成本很低。
2. 硬件设计:JTAG 一样严谨地接好每一根线
硬件设计是这类项目的根基。传感器电路看似简单,但 HVAC 环境里电机启停的浪涌、继电器火花、压缩机大电流干扰,随便一个都能让测温数据变成噪声。我在这个项目里踩过一次远程温度跳变 ±10℃ 的坑,最后查到是远程走线离继电器太近。
2.1 STM32F100ZE 的外设分配
STM32F100ZE 是 LQFP144 封装,资源非常宽裕,温度传感器占用的资源很少。建议按以下分配:
- I2C1:连接 PJ85718DM,SCL 用 PB6、SDA 用 PB7,各加 4.7kΩ 上拉电阻到 VCC;
- GPIO 输入:ALERT 报警引脚接到 PB5 并配置为外部中断输入,温度越限时触发中断;
- 供电:PJ85718DM 的 VCC 用 3.3V,与 STM32 同电源域,I2C 电平匹配,不需要电平转换。
注意:I2C 上拉电阻的取值不是随便选的。总线电容越大,上拉电阻就要越小,否则上升沿太慢。标准 400 kHz 快速模式配 4.7kΩ 通常没问题,但如果线长超过 20cm,建议降到 2.2kΩ 并实测波形。
2.2 PJ85718DM 远程测温的接法
PJ85718DM 的远程测温原理,本质上是在测量晶体管的 VBE 压降。官方推荐接法是:NPN 三极管(2N3904)基极接 D-,集电极接 D+;或者 PNP 三极管(2N3906)发射极接 D+,基极接 D-。两种接法测出来的温度方向是一致的,但注意绝对不能把三极管当成共射放大电路来用,它就是纯二极管连接形式。
我之前做样品时图省事,直接拿一个 1N4148 二极管接上去,也能读出温度,但远程通道会做 beta 补偿校准——即消除三极管电流增益带来的误差。用二极管代替三极管会失去这个补偿,低温段误差稍大。批量生产时建议严格按照 2N3904/2N3906 来设计,尤其是制冷设备工作在 -20℃ 环境下,二极管方案的误差会被放大。
远程走线推荐双绞线或屏蔽线,D+/D- 走差分形式,测试点附近的滤波电容不要超过 100pF,否则会拖慢传感器内部的 ADC 采样,导致温度更新率下降。我实测过,1nF 电容会让远程温度读取速度从 4Hz 掉到不足 1Hz,而且会出现明显滞后。
2.3 电源和 PCB 布局
HVAC 控制板通常有 220V 强电和弱电共存区域,PJ85718DM 的供电如果直接取自开关电源而滤波不佳,测温结果会在 0.5℃ 左右的范围内抖动。
- 电源入口加 100nF + 10μF 电容去耦,且尽量靠近 VCC 引脚;
- 远程 D+/D- 走线要远离继电器、压缩机驱动、PWM 强电走线,如果实在避不开,中间铺地屏蔽;
- ALERT 引脚空闲时必须上拉到 VCC,否则悬空状态下可能因为噪声误触发中断;
- PJ85718DM 的地址选择引脚 A0/A1(如果封装提供)要明确接到 GND 或 VCC,选默认 0x48 地址即可,避免上电时浮空导致地址不确定。
PCB 打样回来后,第一步不要急着接远程探头,先把本地通道读出来,与精密温度计对比。这样能快速确定焊接到位,再把远程部分单独排查。
3. 固件实现:从 I2C 初始化到温度换算全流程
固件设计不复杂,核心就三件事:初始化 I2C、读写寄存器、把寄存器值换算成温度。但每一件都有细节,尤其是远程温度数值的移位处理,做错过一次就知道坑在哪。
3.1 I2C 底层驱动
STM32F100ZE 用标准外设库或者 HAL 都行,我习惯用 HAL,因为后续换芯片平台时移植成本低。以 I2C1 为例:
I2C_HandleTypeDef hi2c1; void I2C1_Init(void) { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; // 100kHz 标准模式,传输距离可放宽 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); }注意:SMBus 设备通常建议用 100kHz 比较稳妥。实测在 400kHz 下也可以工作,但受制于远程走线的电容和 PCB 质量,400kHz 时偶发 NACK,导致温度回读失败。生产固件里我特意固定成 100kHz,牺牲一点速度,换来长期可靠性。对于 HVAC 这种一年不重启的设备,稳定压倒一切。
3.2 寄存器映射与配置
PJ85718DM 的寄存器结构基本兼容常见的多通道温度传感器,关键寄存器如下:
| 寄存器名 | 地址 | 说明 |
|---|---|---|
| 本地温度高字节 | 0x00 | 整数部分 |
| 本地温度低字节 | 0x01 | 小数部分(高 4 位有效) |
| 远程温度高字节 | 0x02 | 整数部分 |
| 远程温度低字节 | 0x03 | 小数部分(高 4 位有效) |
| 配置寄存器 | 0x09 | 决定转换模式、分辨率、警报极性 |
| 状态寄存器 | 0x0A | 读取远程温度开路/短路状态 |
继续沿用常见寄存器地址约定,驱动里首先要确认芯片能正常应答,然后写配置寄存器。配置内容建议:
- 开启连续转换模式;
- 选择 11 位或 12 位分辨率,远程通道用 12 位;
- 报警/ALERT 引脚配置成比较模式或中断模式。
如果是 HVAC 控制器,我推荐用比较模式:温度超限就锁存报警,直到温度回落且读状态寄存器清除,这样外部的硬件风扇调速/控制电路可以直接利用报警信号,即使 MCU 死机也能保护系统。
3.3 温度读取与换算
读温度时按“两字节一组”来处理。本地和远程格式一致:
uint8_t buf[2]; int16_t raw; float temp; HAL_I2C_Mem_Read(&hi2c1, 0x48 << 1, 0x02, 1, buf, 2, 100); raw = (int16_t)((buf[0] << 8) | buf[1]); temp = (float)raw / 256.0f;为什么右移 8 位、除以 256?因为 PJ85718DM 这类传感器温度寄存器的高字节是整数的二进制补码,低字节的高 4 位表示 0.0625℃ 的步进。用一个 12 位 ADC 测量,数据格式是 16 位寄存器里高 12 位有效,所以除以 256 正好把 12 位映射到完整温度范围。
举两个具体例子:
- 本地温度 25.0625℃,读出原始寄存器值 0x1901,右移 8 位得到 0x19(25),低字节高 4 位得到 1(0.0625),合在一起就是 25.0625℃;
- 远程温度 -10.25℃,寄存器读出 0xF640,右移 8 位是 0xF6,转成 int16_t 即为 -10,小数位 4×0.0625=0.25,合起来 -10.25℃。
补码处理是最容易错的点,务必在测试时给远程探头放冰水混合物(0℃)和沸水(100℃),验证一下负数温度换算是否与预计一致。
3.4 读取完整代码片段
下面是循环读两个通道温度的完整函数,加了一个简单的数据有效性检查:
float read_temp(uint8_t reg_high) { uint8_t data[2] = {0}; int16_t raw; float temp; if (HAL_I2C_Mem_Read(&hi2c1, 0x48 << 1, reg_high, 1, data, 2, 100) != HAL_OK) { return -100.0f; // 读取失败,返回非法值,由上层处理 } raw = (int16_t)((data[0] << 8) | data[1]); temp = (float)raw / 256.0f; if (temp < -55.0f || temp > 150.0f) // 超出器件标称范围视为异常 { return -100.0f; } return temp; } float local_temp = read_temp(0x00); float remote_temp = read_temp(0x02);如果读到的温度反复是 -100.0f,优先用示波器抓 I2C 波形,确认是否有应答位。我遇到过一次某公司生产的 PJ85718DM 地址不是默认的 0x48,而是 0x49,排查了半天才发现是 A0 引脚被 PCB 上游走去拉了高电平。
4. HVAC 联动:本地与远程温度的控制逻辑设计
嵌入式测温从来不是测完就完事,真正的大头如果要用到控制闭环里,就需要考虑数据融合、滤波、迟滞策略和失效保护。
4.1 双通道温度在 HVAC 系统中的角色分配
在暖通空调/新风系统里,我是这样分配两个通道的:
- 远程通道(外部探头):测回风温度或盘管出风温度,参与 PID 温控调节。风道里的温度变化相对缓慢,对实时性要求不高,但对稳定性要求高;
- 本地通道(板级):测主控板附近温度,用于散热风扇调速、过热保护。板级温度变化快,如果 MCU 周围温度超过 70℃,应当强制通风或者限功率运行。
这套分工的逻辑在于:把“环境控制”和“设备自保护”两个目标分开,避免用一个传感器同时做两件事时,因为安装位置、探头时间常数不同导致控制行为互相干扰。
4.2 数据滤波与去抖
HVAC 现场最常见的干扰来自压缩机和风机启停瞬间的强电磁干扰。即便 PJ85718DM 抗干扰能力不错,远程探头距离稍长时,读数阵列里偶尔也会冒出一个明显离谱的尖峰值。控制逻辑不能直接拿这种尖峰值去参与调节。
我的做法是在驱动层做中值+滑动平均的复合滤波:
- 连续采集 5 次,去掉一个最大值、去掉一个最小值,剩下 3 个取平均;
- 每 500ms 更新一次滤波后温度;
- 如果连续 3 次滤波后温度变化速率超过 0.4℃/s,判定为数据异常,保持上一次有效值。
实际调试中,这种简单组合远比单纯均值滤波有效。均值滤波会被大的毛刺拉偏,中值滤波则能完全剔掉尖峰。代价是内存和 CPU 开销都很小,在 STM32F100ZE 上多开几十字节缓冲区毫无压力。
4.3 滞后控制与报警阈值设计
HVAC 控制最忌讳的是温度在设定点附近来回抖动,导致继电器频繁通断,烧触点。
以新风机组为例,目标回风温度 22℃,如果用远程温度做开关量控制,不能到了 22℃ 就停、低于 22℃ 就开启。要设置双层迟滞:
- 制冷模式:回风温度 > 23.5℃ 启动压缩机,回落至 < 21.5℃ 时停机;
- 制热模式:回风温度 < 19.5℃ 开启加热,回升至 > 21.5℃ 时关闭。
PJ85718DM 本身有 ALERT 引脚和上限/下限寄存器,可以把阈值直接写进去,当远程温度越过阈值时 ALERT 拉低,STM32 接收外部中断后执行启停逻辑。这样即使主程序因其他任务阻塞,温度越限事件也不会丢。
4.4 失效安全策略
HVAC 设备一旦误判温度,后果可轻可重。我在项目中额外做了以下保护:
- 当远程探头开路或短路时,状态寄存器会给出指示。固件必须识别到这些状态,不能直接把 0xFFFF 之类的值当温度用;
- 当读取失败或温度超过物理意义范围(比如低于 -50℃),立即按“传感器故障”处理,停机并闪故障码,而不是继续运行;
- 若远程温度不参与控制,则至少要让系统进入安全模式——比如不让压缩机启动,防止管路冻结或过热。
这里有个容易被忽略的点:远程温度探头的开路状态不一定稳定,可能一下好一下坏。固件里要加持续确认逻辑,比如连续 10 个周期都检测到开路,才判定为真故障,避免探针接触不良时系统来回切换。
5. 常见问题与排查实录
最后把我在调试过程中遇到的典型问题整理成速查表,每一类都踩过真实的坑,希望能帮你省掉几天排障时间。
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| I2C 读不到设备 | 地址写错 | 先扫描总线,确认器件应答地址,再核对 A0/A1 电平 |
| 温度固定在 0℃ 附近 | 远程探头接线短路 | 用万用表测 D+ D- 间阻值,正常应为数百欧姆量级 |
| 温度跳变 ±10℃ | 远程走线离继电器/电源太近 | 检查布线,D+/D- 加屏蔽或双向对地滤波电容 |
| 本地温度偏高但板子正常 | 芯片散热风道受阻 | 用热成像仪确认,重新规划器件布局 |
| 远程温度读数比实测低 1-2℃ | 三极管型号不对/beta 补偿失效 | 换成 2N3904/2N3906 标准三极管;检查集电极/基极焊接方向 |
| ALERT 频繁误报 | 阈值设置过于贴近工作点 / 未设迟滞 | 扩大阈值窗口,读取状态寄存器确认是哪种报警 |
| 上电后长时间无温度更新 | I2C 总线被 SMBus 超时锁死 | 检查 SCL 是否有持续低电平情况,必要时复位从机 |
5.1 远程探头开路问题
这个数据必须写进代码里。当 PJ85718DM 检测到远程 D+ 与 D- 之间断路,状态寄存器会置位。但如果固件不读状态寄存器,拿 0x02/0x03 寄存器原始值换算,会得到一个远超正常范围的数值。我看到过有人把开路值当成超高温触发停机,结果设备环境正常却被强制保护,这种故障最坑。
正确做法是在进入控制逻辑前先读状态寄存器:
uint8_t status = 0; HAL_I2C_Mem_Read(&hi2c1, 0x48 << 1, 0x0A, 1, &status, 1, 100); if (status & 0x40) // 远程温度传感器开路标志位 { // 进入探头故障处理流程,保留上次有效温度并告警 }5.2 AM 传感器误差与校正
PJ85718DM 本身的精度足以满足 HVAC 需求,但远程走线较长时,线缆的热电偶效应可能引入微小误差。一个实用补偿技巧是:在设备安装完成后,用精密温度计实测风道温度,与远程读数对比,然后把差值作为偏移量保存在 EEPROM 中。
如果是批量设备,固定走线长度和线径,偏移量是相对一致的。批量校准时可以抽测几台设备,用平均偏移量作为统一补偿值写入生产固件,省去每台设备的单独标定时间。这个操作在产品量产阶段尤其重要,能明显降低生产工时。
5.3 两通道数据融合复现
本地通道和远程通道还可以做交叉验证。比如新风机运行时,如果板级环境温度与风道温度相差超过 20℃,大概率是设备风道设计或安装位置出了问题。我在固件里加了一组诊断日志,当出现这种“异常温差”时,记录远程探头的连续温度曲线,方便售后人员快速定位。
这种做法对嵌入式产品意义很大:不是单纯增加传感器数量,而是让双通道数据产生“1+1>2”的价值。
6. 量产阶段额外要留意的几件事
前面讲的主要是实验室和小批量调试逻辑,如果这个项目要走向量产,还有几个工程化的问题要提前规划。
6.1 寄存器初始化时序
PJ85718DM 上电后可能需要几十毫秒才能稳定响应 I2C 访问。固件里不要开机后立刻读温度,建议等至少 50ms 再初始化。多次上电测试时,曾遇到一次读取失败就重试二十多次的情况,加延时后完全消失。
6.2 报警引脚的硬件去抖
ALERT 引脚是开漏输出,外部要加上拉电阻。如果 PCB 上同时存在继电器动作,ALERT 线上可能耦合噪声,导致 STM32 外部中断频繁触发。硬件上建议加一个 10kΩ 上拉和一个 100pF 电容,软件上在中断服务程序里加一个 10ms 的去抖判断,双保险。
6.3 远程探头的位置设计
远程测温三极管没接电流方向就完事?还早。它应该尽量贴在待测表面上,用导热胶或夹具固定。我见过不负责任的做法,直接把三极管悬空绑在风道里,测出来的其实是空气温度,风道进风速度变大时,读数就跟随空气温度变化,控制效果很差。
推荐的做法是:三极管用紫铜片夹持后固定在被测铜管表面,再覆盖保温棉,这样测的是温差影响下的真实壁温,控制滞后明显减小。
6.4 现场更换探头的兼容性
HVAC 售后经常需要更换远程探头。不同批次的三极管 beta 值可能略有差异,如果探头更换后温度偏差变大,最简单的方法是重新做一次偏移校正。固件要支持通过串口或调试工装写入补偿偏移量,避免为了 0.5℃ 的偏差把整机拆下来返厂。
7. 个人操作体会
最后说点实在的。这套方案我已经跑过两个冬天,期间经历过室外 -25℃ 的低温和机房 60℃ 的高温,远程测温从没掉过链子。相比之下,之前用 NTC 方案时每到季节交替就要去现场校准,现在只要安装时做一次偏移补偿即可。STM32F100ZE 的 I2C 驱动非常成熟,PJ85718DM 的寄存器操作跟多数温度芯片高度相似,整个软件框架以后想换更高精度的器件,改动成本也就是改改初始化和换算函数。如果你也在做类似的暖通控制器或者嵌入式测温模块,直接从这套框架起步,能少走不少弯路。