news 2026/10/22 1:11:00

双通道数字温度传感器与PIC18F45K80的暖通测温实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
双通道数字温度传感器与PIC18F45K80的暖通测温实战

最近做暖通控制板的项目时,碰到一个很典型的测温需求:单片机既要知道自己这块控制板附近的温度,用于过热保护,又要知道两三米外风道深处的送风温度,用来参与调节和报警。如果用两根 NTC 热敏电阻拉过去,引线电阻和现场干扰会让人很头疼。最后定下的方案是 PJ85718DM 加 PIC18F45K80:一颗双通道数字温度传感器负责本地和远程两路温度,一颗带 CAN 接口的 8 位单片机负责读取、联动和上报。调完以后整体非常稳,今天把方案逻辑、硬件接线、固件流程和调试中踩过的坑完整复盘一遍。

先说明白这颗 PJ85718DM 是什么定位。它是一颗"本地测温 + 远程二极管测温"二合一的数字温度传感器:本地通道测芯片自身结温,远程通道通过 DXP/DXN 两个引脚外接一枚普通的三极管,利用三极管 PN 结导通压降随温度变化的特性,反推远端温度。真正放到被测现场的是一枚几毛钱的小三极管,而不是体积不小的热敏电阻探头,导线影响小、抗干扰能力强,比传统阻性测温方式更适合长线传输。PIC18F45K80 则是很经典的工业级 8 位单片机,内部集成 ECAN 控制器,正好适合后面接楼宇自控总线。这篇东西适合正在做嵌入式温度采集的工程师,也适合暖通设备选型阶段的技术人员参考,下面进入正题。

1. 方案整体设计:为什么本地和远程温度要分开测

1.1 HVAC 场景里的温度测点,从来不只是“一个”

做过暖通的人都知道,一套风柜或风机盘管系统里,参与控制的温度测点少则两三个,多则七八个。回风温度、送风温度、盘管进出口水温、新风温度、混合温度,每个测点服务的控制目标都不一样。送风温度参与风机转速和冷热水阀开度计算,回风温度反映房间实际负荷,盘管温度还关系到防冻保护。这些测点分散在不同的物理位置,不可能全部挤在控制板上,所以“传感器在被测现场、主控在控制盒里”是常态。

测点和控制器之间只要有距离,就必然有导线。导线短的时候什么传感器都好用,一长就露馅。这个项目里送风温度测点离控制盒大约两米五,中间还要在桥架上绕一段。如果用 NTC,常见的 10kΩ 热敏电阻,引线电阻哪怕只有 2Ω,温度误差就能到 0.2°C 左右,再加上附近变频器感应进来的噪声,ADC 采样结果会非常乱。PJ85718DM 的远程通道恰恰绕开了这两个问题:它传输的不是一个随温度变化的电阻值,而是恒流源驱动二极管产生的电压。这个电压信号的抗干扰能力比阻性测量强很多,而且传感器内部做了 β 补偿和串联电阻抵消,线缆电阻带来的误差可以被算法补掉一部分。实测下来,在不算干净的工业现场,远程温度读数也能稳定在 ±1°C 以内。

1.2 嵌入式控制器自身的本地温度,也有大用

本地温度很多人容易忽略,觉得“不就是芯片自己的温度嘛”。实际上,控制板上有功率 MOS、继电器、开关电源这些发热源,板温往往比环境温度高出不少。如果板温持续越过阈值,一般意味着散热通道堵了,或者输出负载异常,应该提前报警甚至降额运行。PJ85718DM 的本地通道正好承担这个板级过热保护任务。

本地温度还有第二个用途,就是给远程温度提供参考点。虽然远程测温芯片内部会做自动补偿,但在极端温差场景下,比如现场环境 -20°C、控制盒里却因为功率器件发热到了 80°C,多一个本地温度信息做校验总是更放心。上位机看到“环境 30°C、盘管水温 11°C”这样一组数据,也更容易判断整个温度链路是否正常。所以这颗传感器“双通道”的意义就在这里:一颗芯片同时覆盖控制器自身状态监控和外部测点监控,比用两颗传感器省事,布线也更干净。

1.3 选型时为什么排除了 NTC、PT100 和红外测温

有人在选型时问过我,测温方式这么多,为什么偏偏用一颗数字双通道传感器。我逐个对比过一遍:

  • NTC:价格便宜,但要 ADC 采样、查表、线性化,长线传输需要恒流源或三线制配置才能稳住精度,工程调试成本不低。
  • PT100:精度确实高,但需要恒流源激励和仪放电路,外围元件一圈,成本一下子就上去了,小批量产品上不划算。
  • 红外测温:非接触是优点,但发射率参数要设置,而且没办法测管道内部或者风道深处的空气温度。
  • 数字传感器:直接输出数字量,单片机 I2C 读回来就是温度,而且 PJ85718DM 这种双通道型号把远端和本地需求一次包圆了。

单片机这一侧选择 PIC18F45K80,理由也很直接。第一是 HVAC 设备现在普遍要挂楼宇自控总线,CAN 在工业现场很常见,这颗芯片内置 ECAN 控制器,不用外挂 CAN 控制器芯片,硬件和驱动工作都省了。第二是它的工作电压范围 2.0~5.5V,对控制盒这种电源波动比较大的场合很友好。第三是 Flash 和 RAM 余量足,以后想加风阀控制逻辑或者水泵联锁,不用换主控。

2. 硬件设计要点:接线、去耦和安装细节

2.1 主控的资源分配与引脚预留

做硬件分配的时候,我的原则是“先把扩展空间留出来”。PIC18F45K80 的资源分配思路如下:

功能模块使用的外设说明
温度传感器接口MSSP/I2C Master接 PJ85718DM,100kHz
报警输入外部中断引脚接传感器 ALERT 引脚
远程通信ECAN 模块对接楼宇自控总线
调试输出UART接 USB 转串口,看日志
本地状态2 个 GPIO报警灯、运行指示灯

这样把外设分开规划,后续如果再扩展第二路温度传感器,I2C 地址可以用 A0/A1 引脚切换,同一棵总线上最多挂四颗。做多测点控制器的时候,这个余量非常重要。

这里有个经验:I2C 的 SCL 和 SDA 一定要选支持开漏输出的引脚,并加上拉电阻。上拉电阻值我是根据传感器工作电压选的,3.3V 供电时用 4.7kΩ,总线如果比较长,绞合线电容会让沿变缓,就换成 2.2kΩ。太高的上拉电阻会让总线上升沿不够快,特别是在现场线缆长了以后容易出偶发通信错误。

2.2 传感器的供电与 I2C 接线

PJ85718DM 本次按 3.3V 供电设计,SCL、SDA 各接一颗上拉电阻到 3.3V。因为单片机也工作在 3.3V,省掉了电平转换那一步。如果控制板整体用 5V 电源,需要确认传感器型号是否支持 5V 供电,否则要在 I2C 线上加电平移位,别硬接。

传感器 VDD 和 GND 之间,我放了 0.1μF 陶瓷电容和 10μF 钽电容并联。很多工程师习惯只放一颗 0.1μF,但在温度传感器附近,尤其是远程测温通道对电源毛刺很敏感的场合,加大电容有实际效果。曾经碰到过一次本地温度读数偶尔跳 3~4°C 的情况,排查到最后就是电源纹波问题,补了钽电容以后就正常了。

ALERT 引脚直接连到单片机的外部中断引脚。这颗传感器也有 SMBus 超时功能,但实际项目中用硬件中断比轮询状态寄存器更及时。ALERT 是开漏输出,也要加上拉,我用的也是 4.7kΩ。

2.3 远程三极管的接法和安装

远程测温的本质是把一个二极管放在远端。工程上最稳妥的做法是用普通三极管,我选的是 2N3906 这类 PNP 管。接法很固定:PNP 三极管的发射极接 DXP,基极和集电极短接后接 DXN。这里最容易犯的错误是方向接反,接反以后读数通常会指向一个明显不合理的极端值,比如 -50°C 或者 150°C。

安装方式直接决定测量质量:

  • 测风道温度,把三极管扁平外壳贴在翅片或者铜块上,涂导热硅脂,再用高温胶带固定。
  • 测水管温度,用抱箍把三极管压在管壁上,外面包保温棉,防止环境温度干扰。
  • 绝对不能直接把三极管悬在空中测空气,那样测到的是周围环境混合温度,而不是被测对象的温度。

远程通道走线超过一米,我强烈建议用屏蔽双绞线。DXP 和 DXN 作为差分对走双绞线,屏蔽层单端接控制器的 GND。另外在传感器端,DXP 和 DXN 之间并联一颗 1nF 陶瓷电容,DXP、DXN 各串联一颗 100Ω 电阻,这个 RC 结构能明显衰减空间耦合噪声。我第一次调试没加滤波,读数在变频器动作时会跳,加了以后干净很多。

2.4 长线测温的抗干扰布局

提到抗干扰,布局不是只考虑传感器那一段。控制板上的开关电源、继电器线圈如果离传感器太近,干扰也会耦合进去。我在布板的时候把 PJ85718DM 放在离电源模块尽量远的位置,传感器接口区域不走功率线,模拟地和控制地单点连接。

还有一个容易被忽略的点:CAN 总线本身是差分结构,抗干扰能力不错,但 CAN 收发器和微控制器之间也要注意隔离。如果现场有变频器或大功率接触器,建议用光耦隔离或者集成隔离式收发器,否则温度数据偶尔会被干扰成错误帧。说实话,温度监测项目里的 CAN 功率不强求隔离,但为了后期省心,能隔就隔。

3. 固件实现:从初始化到双路温度稳定读取

3.1 系统初始化:先把时钟和通信口理清楚

固件用标准 C 语言编写,基于寄存器操作,方便之后移植。第一步是配置时钟。PIC18F45K80 内部振荡器经 PLL 后跑到 32MHz,不需要外部晶振,省了两个引脚。然后把 I2C 配置成主模式,目标速率 100kHz。

void system_init(void) { // 配置内部振荡器,开 PLL,等待时钟稳定 OSCCON = 0x72; // 内部 8MHz 振荡器 while (!OSCCONbits.PLLRDY); // 等待 PLL 锁定 // I2C 主模式,100kHz SSPCON1 = 0x28; // I2C 使能,主模式 SSPCON2 = 0x00; SSPADD = (unsigned char)((32000000UL / 4 / 100000UL) - 1); // 外部中断引脚配置,用于响应传感器 ALERT TRISBbits.TRISB0 = 1; // RD0 设为输入 INT0CON = 0x90; // 下降沿触发,使能外部中断 // 调试串口 uart_init(9600); // CAN 初始化 can_init(500); }

SSPADD 的计算公式是 Fosc / (4 × 目标频率) - 1。32MHz 下 100kHz 算出来是 79,代码里直接算出写进去。如果想跑 400kHz,就拿 64MHz 或者更高的输入时钟重新算,但我的建议是温度采集应用别追求高速,100kHz 足够。

有一点要特别说明:PJ85718DM 的实际寄存器地址和配置位,请一定以你手上的数据手册为准。我在这里用的寄存器宏定义是这个项目里整理出来的,不同批次或型号后缀可能有差异。

3.2 I2C 读取函数和温度换算

I2C 读温度的流程是:启动 → 写器件地址和写方向 → 写寄存器地址 → 重启 → 写器件地址和读方向 → 连续读两个字节 → 停止。器件地址按 0x48 左移一位,写方向是 0x90,读方向是 0x91。

unsigned int read_temp_register(unsigned char reg_addr) { unsigned int value = 0; i2c_start(); i2c_write_byte(0x90); // 地址 0x48,写 i2c_write_byte(reg_addr); // 寄存器指针 i2c_restart(); i2c_write_byte(0x91); // 地址 0x48,读 value = i2c_read_byte(1); // 高字节,回 ACK value = (value << 8); value |= i2c_read_byte(0); // 低字节,回 NACK i2c_stop(); return value; }

温度寄存器的数据格式是 16 位,有效精度 12 位,最低位代表 0.0625°C。换算函数要小心负数温度,不能直接当成无符号数算。

float raw_to_celsius(unsigned int raw) { unsigned int sign = raw & 0x8000; if (sign) { raw |= 0xF000; // 扩展符号位 } signed int val = (signed int)raw; val >>= 4; // 去掉低 4 位扩展位 return val * 0.0625f; }

这里的坑在于:如果直接把 raw 当成有符号数右移,在部分编译器上可能是逻辑右移而非算术右移,负温度就会算成很大的正数。我刚开始用了一句(signed short)raw >> 4,结果 -5°C 读出来成了 600 多度,排查了老半天。后来老老实实做符号扩展再移位,问题才解决。

3.3 报警中断和主循环逻辑

报警处理我用了中断加轮询双重保险。PJ85718DM 的 ALERT 引脚会在温度越限时拉低,接在单片机外部中断引脚上,中断服务程序里读状态寄存器,判断是哪一路报警,然后置标志位,主循环根据标志位执行降额或者发送故障帧。

void __interrupt() isr(void) { if (INT0IF) { INT0IF = 0; unsigned char status = read_temp_register(REG_STATUS); if (status & 0x02) // 远程温度越限 alarm_flags |= ALARM_REMOTE_HIGH; if (status & 0x04) // 本地温度越限 alarm_flags |= ALARM_LOCAL_HIGH; } }

主循环的节奏控制在 500ms 周期。对暖通场景来说,这个采样周期足够支持风机启停和阀门的调节。不要贪快让周期低于传感器的转换时间,否则读到的可能还是上一次的数据,而且白白增加总线和单片机的负载。

void main_loop(void) { while (1) { float t_local = read_local_temp(); float t_remote = read_remote_temp(); if (t_remote > 80.0f) { alarm_flags |= ALARM_REMOTE_HIGH; } if (t_local > 85.0f) { alarm_flags |= ALARM_LOCAL_HIGH; } can_send_temp_report(t_local, t_remote); __delay_ms(500); } }

报警阈值可以做成配置项写在 EEPROM 里,这样现场不需要烧程序就能调整风机的保护温度。我这个项目里默认远程送风温度 80°C 报警、本地板温 85°C 降额,都是根据设备长期运行数据定的,不同机型会略有差异。

3.4 通过 CAN 上报温度帧

PIC18F45K80 内置的 ECAN 模块带多个报文缓冲器,发送逻辑比早期 CAN 模块好用。我把两路温度、一个状态字节打包成 5 字节数据帧,标准标识符 0x1A0 上传。温度值乘以 16 后取整,用整型传输,分辨率 0.0625°C,既不丢精度又方便上位机解析。

void can_send_temp_report(float t_local, float t_remote) { unsigned char msg[8]; signed short tl = (signed short)(t_local * 16.0f); signed short tr = (signed short)(t_remote * 16.0f); msg[0] = (unsigned char)(tl >> 8); msg[1] = (unsigned char)(tl & 0xFF); msg[2] = (unsigned char)(tr >> 8); msg[3] = (unsigned char)(tr & 0xFF); msg[4] = 0; can_send_standard_frame(0x1A0, msg, 5); }

上位机拿到数据后除以 16,转成十进制显示,和传感器端的分辨率完全对应。如果需要数据带时间戳,可以扩展成 8 字节,多放一个毫秒级时间戳,方便排查历史记录。

4. 现场实测与问题排查实录

4.1 现象一:远程温度读数跳变,像心电图

这是长线远程测温最典型的故障。症状是远程温度在正常值附近快速大幅跳变,有时候还能跳成负值。排查顺序我建议从硬件到软件:

  1. 先看 DXP/DXN 有没有接反。
  2. 再看线缆是否双绞,这个项目最开始用的普通平行线,干扰明显。
  3. 检查线路长度,超过三米建议加 RC 滤波,DXP/DXN 之间并 1nF 电容。
  4. 用示波器看 DXP/DXN 波形,如果叠了明显的高频噪声,基本锁定干扰源。

我这边的最终原因是变频器启停瞬间的空间电磁干扰。换成屏蔽双绞线、屏蔽层单端接地后,读数立刻稳定。软件里我又加了一层一阶低通滤波,取 16 次平均,波动幅度从之前的 ±3°C 压缩到 ±0.3°C 以内。

4.2 现象二:温度整体偏高,怀疑传感器坏了

有一路远程温度读出来总是比实测环境高 1.5°C 左右。先做恒温槽校准,把远程三极管和标准温度计同时放进 25°C 恒温槽里对比,发现确实偏高,但偏移值稳定。排查下来是线缆的串联电阻问题。这根远程线比较细,来回两米五,等效串联电阻大约 3Ω,相当于给二极管叠了一个不小的串联电阻,导致测量结果偏高。

解决办法有两个:一是换更粗的导线,把串联电阻压到 1Ω 以下;二是看传感器是否支持串联电阻抵消功能,如果支持,在配置寄存器里打开,能从算法层面消掉这部分误差。实际产品里两个手段我都用了,效果最好的是开内部抵消功能,粗线反而成了冗余保险。

4.3 现象三:本地温度正常,远程读数为零

远程通道读数一直是 0°C 附近,甚至报错,但本地温度完全正常。这类问题大概率出在 DXP/DXN 短路或者三极管接反。用万用表二极管档直接在传感器引脚处测量,室温下 DXP-DXN 之间应该有 0.5V 左右的结压降。如果量到 0V,说明远端短路;如果量到反向不通,说明三极管方向不对。

我遇到过一次是现场工人把传感器线缆的两个端子压接到同一个接线端子上,相当于直接把 DXP 和 DXN 短了。拆开重做端子以后恢复正常。这个问题的排查速度很快,但很多人会先怀疑程序,代码查半天,其实万用表一量就知道。

4.4 现象四:I2C 偶发通信失败,调速率后消失

设备在实验室跑得好好的,现场偶尔报找不到传感器。用逻辑分析仪看波形,发现总线电平上升沿比较缓,偶发出现一个不完整的应答位。原因有两层:一是 I2C 上拉电阻太大,总线电容导致沿太缓;二是我最初为赶进度把速率设在 400kHz,现场线缆稍长一点,边缘时间就超规格了。

最后把速率降到 100kHz,上拉电阻从 10kΩ 换成 4.7kΩ,问题彻底消失。对于暖通这种实时性要求并不极端的应用,I2C 通信速率追求的是稳定而不是速度,温度数据每 500ms 上报一次,100kHz 的总线毫无压力。

4.5 常见问题速查表

故障现象可能原因处理办法
远程温度跳变干扰、线缆过长、DXP/DXN 接反改屏蔽双绞线、加 RC 滤波、检查方向
远程读数偏高线缆串联电阻过大换粗线、开串联电阻抵消
远程读数为零远端短路、三极管接反万用表测二极管压降
本地温度异常电源去耦不足、纹波过大补 0.1μF + 10μF 电容
I2C 读不到设备地址错误、上拉过大、速率过高检查 A0/A1 地址线、换 2.2~4.7kΩ 上拉、降到 100kHz
温度数据偶发错误帧干扰串入 CAN 总线CAN 收发器隔离、屏蔽层单端接地

排查问题的时候有个习惯:先量再猜。硬件上的坑,万用表、示波器一量就知道,别急着怀疑固件。固件出问题的比例远没有想象中那么高。

最后再说一个实际体会。做这种本地和远程温度监测项目,很多人把工夫全花在选高精度传感器上,可真正决定成败的往往是布线和后端逻辑。PJ85718DM 用一枚外接三极管解决远程测点,思路很巧妙,但对于远程线缆的抗干扰设计、电源去耦、报警逻辑,每一个环节都不能偷懒。如果你现在也在做类似控制器,建议在样板阶段就把传感器线和动力线分开敷设,远程线用双绞线做好屏蔽,I2C 速率定在 100kHz,后面调试能省下大量时间。这个方案后续还可以扩展成多路远程测温,换一颗支持多通道的传感器型号,或者用一颗 PJ85718DM 加模拟开关轮流切入,配合 PIC18F45K80 的 Flash 余量,代码结构基本不用大改。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 1:09:18

PJ85718DM与STM32F401RB温控系统设计实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 1:08:14

PJ85718DM+STM32F107双通道温度监测方案解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 1:08:08

基于STM32与PJ85718DM的嵌入式双通道温度监测方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 1:07:58

PIC18F57K42与PJ85718DM的HVAC温度采集与抗干扰设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 1:06:22

嵌入式HVAC温度监测:STM32F746ZG与PJ85718DM的本地显示与远程上报

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 1:06:21

PJ85718DM+TM4C129XKCZAD实现嵌入式与HVAC本地远程双通道温度监测方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华