☰
基于PIC24F与1-Wire的多点温度采集远程监测方案
2026/10/22 1:03:48 网站建设 项目流程

最近同时推进的两个需求,最后落在了同一套方案上:一边是机房动环的小项目,要在一块主板上同时监测电源模块、处理器散热器和机箱进风口的温度,数据还要定时报给后台;另一边是某楼宇的 HVAC 改造,需要在回风管、送风管和室外墙上各放一个温度探头,把温度统一送到控制柜。两边看起来八竿子打不着,我反而在同一个组合上找到了共同解:用 PJ85718DM 做温度采集,用 PIC24FJ256GA110 做主控和通信。这篇文章就把这套方案的硬件接线、驱动代码、远程通信以及现场踩过的坑完整梳理一遍,适合正在做嵌入式测温、HVAC 控制器,或者想了解 1-Wire 总线多点部署的开发者参考。

先说结论:这套方案解决的核心问题,是"本地多路采集、远端可靠上传"。PJ85718DM 是一颗遵循 1-Wire 协议的数字温度传感器,一条数据线上能挂几十个,每个器件有唯一 ID;PIC24FJ256GA110 是某老牌 MCU 厂商的 16 位 PIC24F 系列芯片,Flash 256KB、RAM 16KB,外围接口多,用来跑传感器管理、通信协议和报警逻辑非常舒服。两个器件凑在一起,既能做板级嵌入式测温,也能扛住 HVAC 现场几十米长线的远程部署。

1. 从应用需求反推选型:为什么是 1-Wire,为什么是 PIC24F

1.1 两类场景对温度监测的真实要求

嵌入式场景里,温度监测的对象往往是功率器件、电池电芯、电源模块这类"热敏感点",要求通常是:精度 ±1°C 以内,采集周期从几百毫秒到几秒,传感器数量几个到十几个,数据线尽量少,抗干扰能力要好。因为板上往往同时有开关电源、电机驱动这类强干扰源,测温电路如果太脆弱,读出来的数据会自己跳。

HVAC 场景则完全不一样:回风温度、送风温度、室外温度这几个点,传感器离主控的距离可能从几十厘米到几十米;现场有压缩机启停、风机变频这类大干扰;数据周期 1 秒到 30 秒都能接受;精度 ±0.5°C 到 ±1°C 足够;但断线、错读必须能被系统识别,否则空调控制逻辑会被一个假温度带偏。

对比下来,两个场景真正的共同需求是"多点、能容忍一定距离、可靠性优先"。传统的 NTC 热敏电阻加 ADC 方案,每个传感器都得单独拉一根线到主控,一个分压电阻、一条走线、一个 ADC 通道,线一多就乱;而且 NTC 的非线性要靠查表或者公式拟合,分压电阻的精度直接影响读数。I2C 温度传感器虽然接线简单,但传输距离短,地址有限,在几十米线缆上基本没法用。

1-Wire 总线天然就是为"单总线挂多点、线少、可远程"设计的:每个传感器只有一根数据线,挂在同一根总线上,靠唯一 64 位 ROM 码区分,非常适合"一根双绞线穿到底"的部署方式。我在 HVAC 改造里特别看重这一点——原来用 NTC 的地方,如果换成 1-Wire,往往可以利用原有的弱电管道,只穿一根双绞线,改造工作量小很多。

1.2 PJ85718DM 和 PIC24F 的选型逻辑

PJ85718DM 这颗传感器,按规格来说是这样的:工作电压 3.0V 到 5.5V,HVAC 现场 5V 电源到处都是,直接能用;测量范围 -55°C 到 +125°C,-10°C 到 +85°C 范围内典型精度 ±0.5°C;分辨率可配置为 9/10/11/12 位,对应转换时间 93.75ms / 187.5ms / 375ms / 750ms;温度值是数字量,直接读寄存器,不需要做任何线性化标定。

方案传输距离多点能力精度影响因素系统复杂度
NTC + ADC长,但每路一根线线多就乱分压电阻、ADC 参考中等
I2C 传感器几米内地址有限低低
1-Wire 传感器几十米可用一根线挂几十个时序、上拉中等

主控为什么选 PIC24FJ256GA110?首先,16 位内核跑 1-Wire 时序和 Modbus 协议足够,比 8 位机在乘除运算和内存管理上舒服。其次,外设丰富:它有多个 UART、I2C、SPI、定时器、DMA,而且很多外设引脚可以通过 PPS 重映射。这个特性在画 PCB 时非常实用,比如可以把 UART2 的收发脚映射到任意普通 IO,RS485 方向控制脚也能随意安排,布线自由度极大。

另外一个现实原因是长期维护。这类测温网关类产品,生命周期往往很长,选一颗工业级温度范围、供货稳定、编译器免费、资料公开的 16 位 MCU,比追新追快要省心得多。XC16 编译器是免费的,开发门槛不高,小批量系统后期维护成本也低。

1.3 方案的整体分工

这套方案的分工非常清晰:PJ85718DM 负责把物理温度变成数字量,挂在 1-Wire 总线上;PIC24F 负责总线的时序驱动、传感器 ID 管理、温度数据缓存,再通过 UART 转 RS485、串口转以太网或者 4G 透传模块,把数据送到上位机或云平台。

"本地"和"远程"这个词在标题里其实有两层含义:一层是传感器离主控的物理距离,本地就是板级或柜内,远程就是几十米外的风道、室外;另一层是数据的去向,本地显示在 LCD 或指示灯,远程则通过协议上报。后面我会把这两层分别展开讲。

2. 硬件连接与部署:一颗传感器怎么变出一整条总线

2.1 引脚与外部供电/寄生供电的选择

PJ85718DM 只有三个引脚:VDD、DQ(数据)、GND。外部供电接法很简单:VDD 接电源,GND 接地,DQ 通过一只上拉电阻接 VDD,所有传感器的 DQ 并在一起,接到 MCU 的一个 GPIO 上,默认上拉电阻选 4.7kΩ。

它还有寄生供电模式:VDD 和 GND 都接地,能量全部从 DQ 线上取。好处是省一根线,两根线就能工作;坏处是温度转换期间 DQ 必须被持续拉高提供电流,长线上压降一大就容易失败,传感器挂多了还可能互相抢电流。我在自己的系统里一律用外部供电,尤其远程传感器——理由很简单:供电稳定,转换时的电流尖峰不会影响 MCU 和传感器自身的电平判定,调试时少一个变数。

供电方式线数可靠性适用场景
外部供电3 根高本地、远程、多点
寄生供电2 根受长线影响短距离、传感器数量少

2.2 本地部署:板级传感器的接线要点

板级测温的场景,传感器要贴在电源模块、MOSFET 散热器或者处理器附近。安装时尽量让传感器外壳和测点之间用导热硅脂过渡,再机械固定,避免只靠空气导热,那测出来的不是器件温度而是环境温度。数据线不要和开关电源的开关节点走在一起,高频干扰会在 1-Wire 时序上形成毛刺,导致偶发 CRC 错误。

如果用在电池包这类 ESD 风险高的环境,DQ 线上最好加一个 100pF 左右的小电容到地,或者并联一个 TVS 管。这个不是可选项——现场静电打坏传感器引脚的情况我见过好几次,返修成本远大于那几毛钱的器件成本。

2.3 远程部署:几十米线缆的处理方式

HVAC 风道和室外温度探头是远程传感器的典型场景。传感器离主控十几米、几十米很正常,这时候接线就是一门学问。

线缆选屏蔽双绞线,屏蔽层单端接地,通常在主控端接地,避免两端都接地形成地环路。上拉电阻不能再死守 4.7kΩ:线长了、分布电容大了,4.7kΩ 上拉太弱,数据线上升沿会变得很缓,MCU 可能在采样窗口读到一个模糊电平。实际经验是,10 米以内 4.7kΩ 基本没问题,20 米以上建议换 2.2kΩ 甚至 1kΩ,但要注意 MCU 引脚在总线被外部拉低时的灌电流是否在安全范围内。

拓扑上优先"菊花链",也就是手拉手逐级串下去,避免星型分支。星型分支会在分支点产生信号反射,波形出现台阶,这是实验室里很难复现、现场却经常遇到的问题。多条支路如果实在避免不了,每条支路要尽量短,或者干脆每个分支点用独立的驱动级。

如果总线从控制柜拉到室外,强烈建议加数字隔离器或光耦,把总线和 MCU 的地分开。地电位差是 HVAC 现场最常见的隐性故障,地环路打坏 MCU 引脚的事情,碰到一次就长记性了。

2.4 传感器数量规划和 ID 管理

一条总线能挂多少个 PJ85718DM?取决于上拉驱动能力和 ROM 搜索时间。总线长、上拉弱,挂多了信号质量会恶化;实际项目中一条总线挂 20 到 30 个是常见水平。更多的话建议分多条总线,PIC24FJ256GA110 的 GPIO 数量完全够用,每条总线独立一个 IO,这样做还有一个额外好处:故障隔离。某一路总线短路,不至于把整个温度采集系统拖垮。

批量部署前,先把所有传感器的 ROM 码读出来,按安装位置建表,烧写到 MCU 的 EEPROM 里。这样现场换传感器时,系统能自动识别"这个位置的传感器换了",而不是等到上位机报警才发现数据错位。这个小习惯能省掉大量现场排查时间。

3. 驱动代码骨架:把 1-Wire 时序吃透

3.1 时序的本质:复位、写时隙、读时隙

1-Wire 是半双工、开漏、低速总线。MCU 通过一根 DQ 线,用严格的时隙区分 0 和 1。核心就三个动作:

复位时序:MCU 把 DQ 拉低至少 480µs,然后释放;传感器在释放后 15µs 到 60µs 内把总线拉低,产生存在脉冲。MCU 如果能读到这个低电平,就说明总线上有传感器。

写时隙:一个写周期 60µs。写 1 时,MCU 拉低 6µs 到 15µs 后释放,剩下的时间由外部上拉把总线拉高;写 0 时,MCU 拉低整个 60µs。

读时隙:MCU 拉低约 6µs 后释放,然后在 15µs 内采样总线电平。读到低电平是 0,高电平是 1。

这个时序不是"差不多就行",而是"边界要清楚"。写 1 时隙释放太早或太晚,传感器就可能把 1 判成 0;读时隙采样太晚,可能读到下一位的电平。我在调试时用逻辑分析仪看过很多次,最容易翻车的不是读写逻辑本身,而是中断穿插导致时隙长度抖动。

3.2 PIC24F 上模拟 1-Wire 的代码

PIC24F 没有专用的 1-Wire 外设,但这反而是好事——用 GPIO 模拟,时序完全透明可控。核心做法是用开漏输出加外部上拉,通过 TRIS 寄存器控制引脚方向。

#define DQ_TRIS TRISAbits.TRISA0 #define DQ_LAT LATAbits.LATA0 #define DQ_READ PORTAbits.RA0 #define DQ_LOW DQ_TRIS = 0; DQ_LAT = 0; #define DQ_RELEASE DQ_TRIS = 1; uint8_t ow_reset(void) { uint8_t presence; DQ_LOW; __delay_us(500); DQ_RELEASE; __delay_us(40); presence = (DQ_READ == 0) ? 1 : 0; __delay_us(240); return presence; } void ow_write_bit(uint8_t bit) { if (bit) { DQ_LOW; __delay_us(8); DQ_RELEASE; __delay_us(60); } else { DQ_LOW; __delay_us(60); DQ_RELEASE; __delay_us(8); } } uint8_t ow_read_bit(void) { uint8_t bit; DQ_LOW; __delay_us(6); DQ_RELEASE; __delay_us(9); bit = DQ_READ; __delay_us(50); return bit; }

这段代码里有个细节:拉低用 TRIS 而不是 LAT。因为 DQ 工作在开漏模式,TRIS=1 就是高阻释放,由外部上拉拉高总线;TRIS=0 输出低电平。这样即使代码逻辑出错,也不会把电源和地短路,排查问题的时候会少很多麻烦。

延时用 XC16 的__delay_us,需要在代码里定义 FCY 并包含相应的头文件:

#define FCY 32000000UL #include <libpic30.h>

如果系统时钟配置不同,FCY 一定要改对,否则整个时序全偏。写时序函数时建议临时关闭中断,或者至少把 60µs 的时隙放在临界区里保护——一个高频定时器中断如果正好插在写 1 时隙中间,释放点会被推迟十几微秒,传感器读到的就很可能是 0 而不是 1。

3.3 多点采集:从跳过 ROM 到匹配 ROM

总线上只有一个传感器时,可以用跳过 ROM 命令 0xCC,不用知道它的 ID 就能操作。多点就不行了,必须用匹配 ROM 命令 0x55,后面跟上 8 字节的 ROM 码,传感器 ID 匹配上了才会响应。

ROM 码的获取有两个办法:一是一次性把所有传感器逐个挂在总线上,读出来记下来;二是用搜索 ROM 命令 0xF0,通过位搜索算法在总线上自动枚举所有传感器。我的项目里直接用后者,因为部署时不可能一个个挂线。

温度采集流程分两步:

第一步,触发转换:向所有传感器广播跳过 ROM + 转换命令 0x44。这一步用跳过 ROM 是安全的,因为所有传感器收到命令后都会开始转换,不存在数据冲突。12 位分辨率下等待 750ms。

第二步,分别读取:逐个匹配 ROM + 读暂存器命令 0xBE,读取 9 个字节。这一步绝不能再用跳过 ROM,否则多个传感器同时把数据放到总线上,数据就全乱了。

转换完读出的温度,低字节是 byte0,高字节是 byte1,带符号补码:

int16_t raw = (byte1 << 8) | byte0; float temp = raw * 0.0625f;

12 位分辨率下 raw 的低 4 位是小数部分,乘以 0.0625 就是摄氏度。负温度在补码下直接按 int16_t 处理即可。

读暂存器的第 9 个字节是 CRC 校验值。这个校验必须做,尤其 HVAC 场合——一个被干扰读错的温度如果直接送进控制逻辑,风机、阀门全都会跟着错。校验算法是多项式 X^8+X^5+X^4+1,初始值 0,逐位计算,网上到处都有现成实现,直接拿过来用就行。

3.4 从阻塞等待改成状态机

如果总线上有 16 个传感器,每轮都串行等 750ms,几轮下来系统其他事情全卡死了。我的做法是做一个简单的采集状态机,主循环里维护当前状态:

  • 触发状态:广播转换命令,记录当前时间戳,进入等待;
  • 等待状态:不阻塞主循环,继续处理 Modbus 查询、LCD 刷新、LED 指示等任务,系统时间走够 750ms 后才进入读取;
  • 读取状态:逐个匹配 ROM 读暂存器,做 CRC 校验,更新温度缓存。

这样,一次 16 路温度轮询,对其他任务的干扰降到了最低。用定时器做一个软件时间基准,比在等待循环里数 NOP 可靠得多。

长期运行还需要几个安防措施:每次读取都做 CRC,失败记错误计数,连续 3 次失败判定传感器掉线;掉线后自动重新搜索 ROM,支持现场换传感器;所有总线操作加超时保护,任何一步超时就释放总线,防止总线被锁死。

4. "远程"的第二层:数据如何离开 PIC24F

4.1 三种上报通道

远程温度监测的第二层含义,是数据要能到上位机或者云平台。按现场条件我通常分三档:

第一档,控制柜内有上位机或 PLC,走 RS485 + Modbus RTU。这是最稳、最常见的方式。PIC24FJ256GA110 一个 UART 加一颗 RS485 收发器就搞定,收发器 A/B 端要注意 120Ω 终端电阻的匹配,总线两端各并一个。

第二档,现场有以太网,接串口转以太网模块,模块内置 Modbus TCP 或 MQTT,PIC24F 只需要把温度整理成模块能识别的格式。

第三档,现场没有有线网络,接 4G DTU 或 Wi-Fi 透传模块,串口发 JSON 或者自定义帧,云端解析入库。

我自己的动环小项目用的是 RS485 + Modbus RTU,简单可靠,调试工具多;HVAC 那个项目走了串口转以太网,直接对接楼宇自控系统。

4.2 Modbus 寄存器映射设计

寄存器映射合不合理,直接决定上位机对接顺不顺。我的习惯是温度值全部按 0.01°C 存成有符号整数,避免浮点解析;每组传感器分配固定数量的寄存器,并且预留扩展位。

寄存器地址内容说明
40001状态字bit0-7 对应各路传感器在位标志
40002有符号整数本地温度 × 100
40003有符号整数远程温度1 × 100
40004有符号整数远程温度2 × 100
40005有符号整数室外温度 × 100
40006无符号整数CRC 错误计数

上位机只要按这个表读寄存器,就能拿到所有温度值。状态字和错误计数也要暴露出去,否则现场传感器掉了,上位机还以为温度是正常的。

4.3 预警逻辑

温度监测的最终目的是报警,不是读数。我的预警逻辑一般分四层:

  • 每路温度设上限和下限,可配置;
  • 差值报警:回风和送风温度差超过范围,说明风道传感器位置不对或者换热器出问题;
  • 掉线报警:CRC 连续失败或读到异常值,上位机界面直接标红;
  • 报警带死区:比如上限 40°C,到 40.5°C 才触发,低于 39.5°C 才恢复,避免临界点抖动导致报警反复开关。

嵌入式设备里的温度监测也一样,处理器温度到 85°C 报警,到了 90°C 还要触发降频,这些阈值逻辑放在 PIC24F 里做,上位机只负责显示和记录。

5. 实测数据、校准方法和现场踩坑记录

5.1 精度实测与校准

我在模拟项目 X 里做了 16 路传感器对比测试:探头放进恒温槽,在 25°C 和 55°C 两个点,和一个参考温度计比对。12 位分辨率、外部供电、总线长度 5 米。结果大多数通道偏差在 ±0.3°C 以内,个别通道偏差到 -0.6°C。这说明两件事:传感器本身一致性不错,但系统级校准仍然有必要。

校准方法:每路建一个软件偏移表,用恒温槽或至少冰水混合物和沸水两个点测出偏移量,烧写到 PIC24F 的 Flash 里。上位机最终显示值就是"原始读数 + 该路偏移量"。现场更换传感器后,对该路重新校准即可。

有两点要提醒:不建议把校准值写进传感器的 TH/TL 寄存器。那两个字节虽然可写、非易失,但语义是报警阈值,拿它存校准值容易埋雷,以后有人设报警阈值时会把校准信息覆盖掉。另外,批量校准前先确认传感器已经稳定在目标温度,不能把刚放进恒温槽的探头立刻读数,热平衡没建立,测出来的偏移没有意义。

5.2 现场踩坑:五个典型的坑

这些坑是我实际遇到过的,按出现频率排序:

上拉不足导致 CRC 频繁失败。症状是短距离一切正常,接上 30 米线就开始丢包。根因是线缆分布电容太大,4.7kΩ 上拉充不动,上升沿太缓。把上拉换成 2.2kΩ,屏蔽层单端接地,问题立刻消失。

星型拓扑导致偶发字节错误。症状是某一路传感器读数几分钟错一次。根因是三条支路在汇接点反射叠加,波形出现台阶。改成菊花链拓扑后,错误消失。

寄生供电在低温时转换失败。症状是室外传感器冬天偶尔读不到。根因是-20°C 环境下传感器转换电流变大,寄生供电的 DQ 电流不够。室外探头全部改外部供电,问题根治。

HVAC 现场地环路损坏引脚。症状是控制柜和室外传感器之间有电压差,MCU 引脚偶尔损坏。解决方法是总线上加数字隔离器,或者至少 DQ 串一个 1kΩ 电阻限流。

Modbus 读取时 1-Wire 等待造成超时。症状是 PLC 轮询温度寄存器时偶尔超时。根因是 PIC24F 在 750ms 转换等待期间没及时响应 Modbus 报文。把转换等待改成状态机,通信优先级提前,问题解决。

5.3 现场排查链路

现场温度数据异常,我一般按这个顺序查:

第一步,看存在脉冲。用逻辑分析仪抓复位和存在脉冲,先确认传感器有没有响应。

第二步,看时隙波形。重点看写 1 时隙的上升沿,如果上升沿超过 1µs,多半是上拉弱或线太长。

第三步,看 CRC。暂时只挂一路传感器,排除总线上多点冲突。

第四步,量供电。看传感器 VDD 引脚在转换瞬间的电压会不会跌落。

第五步,才怀疑代码时序。代码时序一旦在实验室验证过,现场基本不会自己变,问题通常出在硬件和部署上。

这个顺序很关键。很多工程师一出问题就怀疑代码,结果花了两天查固件,最后发现是线缆接反或者上拉电阻掉了,耽误时间。

6. 实际操作后的几点体会

写到这里,如果让我提炼最想说的话,大概是这几点。

第一,1-Wire 这套方案最大的优势不是精度,而是省线和可扩展。一条双绞线挂几十个传感器,在 HVAC 改造里省下的穿线成本,比传感器本身贵得多。这和嵌入式板级场景是两个逻辑,但省线和可扩展这两个特性在那里同样成立。

第二,PIC24FJ256GA110 这种 16 位 MCU 做温度网关其实有点"大材小用",但恰恰因为资源富余,才能把通信协议、传感器管理、报警逻辑都放在一个芯片里,后期维护只动固件,不用换硬件。对一个要长期运行的产品来说,这是最省心的状态。

第三,关于"本地"和"远程"的区分,我踩过几次坑之后的体会是:本地部署要关注 PCB 布局和电源噪声,远程部署要关注线缆电容、地环路和拓扑结构。前者是设计问题,靠原理图阶段就能规避;后者是工程问题,必须到现场才能暴露。把这两类问题分开思考,调试起来会清晰很多。

最后再分享一个小技巧:批量部署前,先把所有传感器的 ROM 码读出来,按安装位置建表存进 EEPROM。这样现场换传感器时,系统能自动提示"这个位置传感器型号不对",而不是等到上位机报警才发现温度数据错位。这个习惯我后来所有项目都在用,省下的现场排查时间非常可观。

这套方案后续扩展的方向其实也清楚:PJ85718DM 的总线条数扩到三四条,配合 PIC24F 的多个 UART 和 DMA,就能同时服务"本地板级温度"和"远程多点温度"两类采集,再往上走就是一个标准的嵌入式环境监测网关。手头有类似项目的,按这个思路试一遍,应该能少走不少弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询