基于PIC18F87K22与PJ85718DM的本地/远程温度监测系统设计

发布时间:2026/10/22 12:16:05

基于PIC18F87K22与PJ85718DM的本地/远程温度监测系统设计 直接做项目的时候最常碰到的需求就是“把温度测准、传得远、看得见”。前阵子我基于PJ85718DM 温度变送模块和PIC18F87K22 单片机搭了一套同时支持本地和远程温度监测的嵌入式采集系统应用场景锁定在 HVAC暖通空调和控制柜环境监控上。这套方案不算花哨但胜在稳定、便宜、可复现而且把“本地就地显示 远程总线传输”两条路都打通了很适合做设备配套、机房检测或者小型控制器二次开发参考。先说结论如果你手头也有一颗 8 位单片机想接模拟量温度变送器、做多点采集、再通过 RS485 把数据送给触摸屏或上位机这套思路可以直接抄作业。下面把选型理由、硬件连接、固件代码、通信协议和踩坑记录全部展开尽量给到能落地的细节。1. 方案选型与整体设计思路1.1 为什么选 PIC18F87K22 这颗单片机PIC18F87K22 是 Microchip 8 位家族里资源比较“豪横”的型号80 引脚封装128 KB Flash、4 KB SRAM、1 KB EEPROM主频最高能跑到 64 MHz。在 8 位机里它给我最大的信心来自三个地方第一内置 12 位 ADC通道多、分辨率足够处理 0-5V 或 0-10V 的模拟温度变送器信号第二片上直接带两个增强型 EUSART一个接本地调试口一个走 RS485 远程通信不用软件模拟串口第三工作电压范围 1.8V 到 5.5V在工业控制柜里电源波动大一点的场合比 3.3V 专用芯片更抗造。实际项目里我没有选带浮点运算单元的 ARM 或者更高端的 MCU核心原因是这类 HVAC 网关/温控器设备不需要跑复杂算法Modbus RTU 轮询和 PID 控温都是轻量任务8 位机绰绰有余。而且这类芯片货源稳定、单价低、封装通用打样板和手焊都方便对中小批量产品非常友好。1.2 PJ85718DM 是什么信号如何接入PJ85718DM 是一个典型的导轨式或壁挂式温度变送模块内部把 NTC 热敏电阻或 PT100 的阻值变化转换成标准模拟电压输出输出范围常见为 0-5V 或 0-10V对应测量温度区间可配置为 0-100℃ 或 -20-80℃。选它的理由只有一个省去自己设计桥式电路和运放调理电路模块内部已经做了线性化和温度补偿我这边只需要用 ADC 采样电压再做软件标定就行。这类模块通常有三根线电源正、电源负、信号输出。供电一般用 DC 12V 或 24V信号输出是共地单端电压。接 PIC 的时候注意一点如果模块输出 0-10V而单片机 ADC 参考电压是 5V中间必须加分压电阻或运放跟随器转成 0-5V千万别直接怼到引脚上。我这次用的 0-5V 版本省掉了电平转换直接接入 ADC 通道硬件上干净利落。1.3 本地监测与远程监测的架构区别“本地”和“远程”在这套系统里分工明确。本地温度指设备安装点附近比如控制柜内部、风管回风处的温度由 PJ85718DM 直接测量单片机采样后一方面驱动本地的数码管或 LCD 显示另一方面参与逻辑判断比如超温报警、风机启停。远程温度指分布在其他位置的温度点比如多个楼层的机房、远端空调箱这些信号通过 RS485 总线汇集到主机或者把本机测得的数据上传给上位机组态软件。我做的这套设备本质上是一个“就地采集 总线从站”的小网关本地温度实时显示远程请求通过 Modbus RTU 读取寄存器时把本地温度连同从另一个串口读取的外部变送器温度一起返回。这样既满足了现场人员肉眼看温度的需求也满足了中控室集中监控的需求一举两得。2. 硬件连接与信号调理的实操细节2.1 电源设计与去耦布局PJ85718DM 模块标称工作电压 DC 12V但实际用 24V 供电也常见取决于模块规格。我建议在控制柜里统一用 24V 开关电源板上再加一颗 12V 稳压比如 7812给变送器供电PIC18F87K22 则用 5V 稳压AMS1117-5.0 或 7805。这样 24V - 12V - 5V 的链路有一个好处变送器和单片机之间电源隔离度好免受柜内大功率设备启停造成的电压跌落影响。这里有个重点PJ85718DM 的输出地必须要和单片机的模拟地共地否则信号无法采样。如果现场干扰严重建议信号地单点接入 PCB 模拟地不要和高频数字地混在一起。电源去耦上每个 IC 的 VDD 引脚旁边放 0.1uF 陶瓷电容靠近引脚放置单片机电源入口再放一个 10uF 电解电容。变送器供电入口也串一个磁珠能滤掉不少开关电源的高频噪声。2.2 ADC 参考电压的选择PIC18F87K22 的 12 位 ADC 有一个很关键的可选项参考电压可以使用内部固定参考或外部 VREF / VREF- 引脚。我的经验是既然要测“绝对温度”就不要省这颗基准芯片。用外部基准比如 REF3030 输出 3.0V或 TL431 搭 4.096V接到 VREF 引脚ADC 量化单位就稳定了。否则直接用 VDD5V 做参考而 7805 的 5V 会随负载和温度漂移直接反映到读数上温度波动一两摄氏度很常见。用 4.096V 基准还有个数学上的好处12 位 ADC 的是 4096 个码每个码正好对应 1mV软件里做电压-温度换算的时候特别顺手不用做浮点除法直接用整数移位就能算。这个细节在批量校准时能省很多事。2.3 输入滤波和防反接保护PJ85718DM 输出的模拟信号虽然模块内部做了滤波但连接线如果走得过长还是容易耦合工频干扰和电机噪声。我习惯在单片机的 ADC 引脚前加一个简单的 RC 低通滤波1kΩ 电阻串联 0.1uF 电容到地截止频率大概 1.6 kHz能有效抑制高频毛刺对温度这种慢变信号完全不影响响应速度。同时信号输入端两个二极管做钳位保护把电压限制在 GND-0.7V 到 VDD0.7V 之间。这个保护很必要因为现场维护人员有可能在设备带电时拔插探头瞬间的浪涌或反接会直接打坏 ADC 引脚。用两颗 BAT54 或 1N4148 就能解决成本两分钱能救一块板子。2.4 本地显示与远程通信的接口预留本地显示我这次选用的是 4 位数码管用两个 74HC595 移位寄存器驱动只占单片机 3 个 GPIO数据、时钟、锁存刷新率 50 Hz 无闪烁。如果你想显示更丰富的信息比如同时显示本地和远程两个温度用 1602 LCD 也行PIC18F87K22 的引脚资源完全够。远程通信则用一颗 MAX485 芯片把 UART 转成 RS485 半双工总线注意 A/B 输出端要加 120Ω 终端匹配电阻在总线两端各加一个不是每个节点都加并且 DE/RE 引脚由单片机一个 GPIO 控制收发方向。3. 固件实现采集、标定与滤波3.1 单片机初始化与 ADC 采样配置固件流程很简单上电延时 - 配置系统时钟16 MHz 晶振 4 倍 PLL 到 64 MHz- 配置 UART1 为调试口UART2 为 RS485 - 配置 ADC 引脚 AN0 接本地变送器AN1 接远程变送器 - 配置定时器 0 做 10ms 时基 - 主循环里轮询采样、滤波、刷新显示、处理 Modbus 请求。ADC 采样的关键参数是采样保持时间和转换时钟。PIC18F87K22 的 ADC 需要设置合适的 ADCON2 寄存器保证采样时间足够长。变送器输出阻抗加上 RC 滤波后等效内阻偏高如果采样时间太短内部采样电容充不满读数会偏低且不稳定。我实测 1kΩ 串联电阻下采样时间配置为 20 个 Tad 以上比较安全转换时钟选 2 分频或 4 分频都能满足 12 位转换精度。3.2 采样值到温度的换算两点标定法理论上 PJ85718DM 模块在 0-5V 输出、0-100℃ 量程下温度 电压 × 20也就是 250 mV / ℃。但模块本身存在零点和增益误差直接套公式会带来 ±1-2℃ 偏差。所以正规做法是两点标定用冰水混合浴0℃和沸水浴100℃需考虑当地大气压修正或者精密恒温槽做标定采集两个点的 ADC 码值然后按线性插值得到T T_low (ADC - ADC_low) × (T_high - T_low) / (ADC_high - ADC_low)这个公式用整数实现即可温度值乘 100 存储成定点数比如 25.43℃ 存成 2543避免浮点运算拖慢 8 位机。把标定好的斜率 K 和截距 B 存到 EEPROM掉电不丢失。以后每次采样温度 K × ADC B只做乘法和加法主循环里跑几十个点毫无压力。3.3 滤波算法移动平均和去毛刺温度信号变化缓慢但偶有尖峰干扰我在代码里做了两层处理。第一层是中值滤波取连续 5 次采样排序后取中间值能干掉电源开关或继电器动作引起的单点毛刺第二层是滑动平均把最近 20 个中间值做平均等价于一个 FIR 低通滤波器响应时间大约 1 秒对于 HVAC 这种时间常数很大的对象完全够用。注意滤波窗口不能太长否则温度报警响应会延迟我调试时发现 20 点平均在 10ms 采样周期下也就是 0.2 秒延迟实际体感很跟手。3.4 多点通道轮询的顺序问题采集两个温度点时存在一个隐蔽问题ADC 切换通道后内部采样电容还残留上一个通道的电压立刻采样会“串扰”。我在软件里做了两次采样的处理每次切换通道后先做一次“空采样”丢弃延时 100us 让电荷释放然后再连续采样 5 次进入滤波队列。这个细节对两个变送器输出相差很大时尤其重要。比如本地 10℃ 和远程 90℃如果通道串扰严重可能互相拉偏 0.5℃。3.5 核心代码片段参考下面给出一段简化的 ADC 采样和定点换算代码思路可以直接移植。// PIC18F87K22 ADC 采样示例AN0 为本地温度AN1 为远程温度 // 温度值用 int16 表示实际值 返回值 / 100 #define LOCAL_CH 0 #define REMOTE_CH 1 // 标定参数烧录前通过串口命令写入 EEPROM int16_t g_k_local 2000; // 每 ADC 码对应的温度 0.01℃ int16_t g_b_local 0; // 截距 0.01℃ uint16_t read_adc_average(uint8_t channel) { uint32_t sum 0; // 切换通道 ADCON0 (ADCON0 0xC3) | (channel 2); // 空采样释放残留电荷 ADCON0bits.GO 1; while (ADCON0bits.GO); // 正式采样 5 次 for (uint8_t i 0; i 5; i) { ADCON0bits.GO 1; while (ADCON0bits.GO); sum ADRES; } return (uint16_t)(sum / 5); } // 定点换算返回 0.01℃ int16_t calc_temperature(uint8_t channel, int16_t k, int16_t b) { uint16_t adc read_adc_average(channel); int32_t t (int32_t)adc * k / 10 b; // 简化运算实际按标定系数调整 return (int16_t)t; }注意ADC 结果的读取必须在 GO 位清零后立即读取 ADRESH 和 ADRESL不能延迟否则寄存器可能被下一次转换覆盖。PIC18 系列高字节结果寄存器需要先读 ADRESH再读 ADRESL顺序不要颠倒。4. 本地显示和远程 Modbus 通信的落地实现4.1 本地数码管动态扫描驱动数码管驱动我用了 3 个 IO 口加两片 74HC595在 10ms 定时中断里做动态扫描。显示内容设计为正常状态轮流显示本地温度和远程温度各显示 2 秒中间用一位小数点区分带小数点的表示远程不带小数点的表示本地。这样现场人员不用按键就能同时看到两个温度。如果有按键需求可以再留一个 GPIO 做模式切换在“本地/远程/两者交替”之间循环。给 74HC595 写数据用的是 SPI 主模式但不用硬件 SPI直接 GPIO 模拟时序更灵活。需要注意 595 的输出锁存引脚RCK要拉高至少几十纳秒才能稳定输出我把锁存操作放在最后三个数据位写完后再统一拉高 RCK避免中间状态闪烁。4.2 RS485 收发控制时序MAX485 的 DE 和 RE 通常接在一起由单片机一个引脚控制。发送数据前先把该引脚拉高使能发送然后等一小段时间至少一个字节的传输时间再往 UART 发送寄存器写数据。同样发送完成后不要立即把引脚拉低要等最后一个字节完全移位出去之后再拉低否则帧尾会截断。这个时序问题最常见很多初学者写 RS485 通信时出现“最后一字节丢失”就是这个原因。判断发送完成的稳妥办法是串口发送中断全部清空或者直接延时 1.5 个字节时间。我实测 9600 波特率下用 2ms 延时可靠。如果波特率是 115200这个延时可以缩短到 0.2ms但为了保险我通常留双倍余量。4.3 Modbus RTU 从站寄存器映射远程读取我用 Modbus RTU 协议设备地址可配置拨码开关或 EEPROM波特率 9600 8N1。寄存器映射规划如下寄存器地址功能数据类型0x0001本地温度值×100保持寄存器int160x0002远程温度值×100保持寄存器int160x0003温度报警状态bit0 本地超温bit1 远程超温保持寄存器uint160x0004设备运行状态bit0 传感器断线bit1 通信正常保持寄存器uint16Modbus RTU 从机核心任务就是收帧、校验 CRC、解析功能码03 读保持寄存器、组帧回复。在 8 位机上处理 CRC16 用查表法速度很快把 256 字节的表放 Flash 里每字节查表两次即可。中断收帧时把数据存入环形缓冲区主循环里解析避免在中断里做耗时运算。4.4 简化版 CRC16 计算代码Modbus CRC16 算起来不难但容易写错尤其是初始值和多项式。直接上代码// Modbus CRC16 查表法计算前将 crc 初始化为 0xFFFF uint16_t modbus_crc16(uint8_t *data, uint16_t len) { uint16_t crc 0xFFFF; for (uint16_t i 0; i len; i) { crc ^ data[i]; for (uint8_t j 0; j 8; j) { if (crc 0x0001) crc (crc 1) ^ 0xA001; else crc 1; } } return crc; }收到完整一帧后先校验 CRC低字节在前高字节在后。如果校验不过就不回复任何内容等待主站超时重发。这比回复异常码更符合 Modbus 惯例主站那边也好排查总线问题。4.5 看门狗与异常自恢复HVAC 现场设备常年通电最怕程序跑飞后无人复位。PIC18F87K22 内置看门狗定时器WDT我用它来做异常自恢复。正常主循环每轮喂狗一次如果死循环或外部晶振故障导致循环卡死WDT 超时复位系统把设备拉回正常状态。需要提醒一点WDT 的使用要配合“残骸复位检测”。复位后先读复位状态寄存器如果是看门狗复位就在报警寄存器里标记一次异常重启同时跳过至少 5 秒的初始化延时让变送器信号稳定后再开始采样。否则设备会出现在“复位-救急-再复位”的循环里看起来像电源不稳但其实是初始化时序问题。5. 常见问题与排查技巧实录5.1 温度读数漂移不定是硬件还是软件问题我调试时遇到过一次典型的“读数漂移”室内温度没变显示值从 25.3℃ 慢慢飘到 26.8℃。先怀疑滤波不够但把滤波窗口拉到 50 点还是飘。后来用万用表测 PJ85718DM 的输出电压发现电压本身就随供电电压在小幅波动。查下去找到原因变送器用的是柜内 24V 电源而那一路电源还带了一个电磁阀电磁阀动作瞬间 24V 被拉低模块内部稳压不足导致输出偏移。解决思路有两个一是给变送器单独一路稳压供电二是软件上做电源补偿。我选了前者因为更彻底。从那以后我把变送器和单片机电源彻底分开了24V 进来先给变送器经过 7812 再给 7805 供单片机模拟部分和数字部分电源回路不相交。这个改动之后读数稳得像钉子一样。5.2 RS485 通信偶尔丢帧单独测又正常单独接一台设备上位机读写都正常挂到现场总线上就 30 秒丢一帧。排查过程可以说一波三折。最终发现是终端电阻的问题总线上有三台设备我把每台设备的板上都加了 120Ω 电阻结果相当于三只电阻并联总线阻抗远低于特性阻抗信号反射反而更严重。正确的做法是只用最远端的两个设备加终端电阻中间设备不焊。另外还有一点A/B 线一定要用双绞屏蔽线屏蔽层单端接地。如果现场已经布了普通平行线短线10 米内还能凑合长线丢帧就没跑了。现在我做项目一律提前跟结构说清楚RS485 线必须是双绞屏蔽线这比换芯片、调波特率都管用。5.3 ADC 读到的值跳字像蒙了一层毛刺把变送器接上后ADC 数值在 ±20 个码左右跳折合温度大约 ±0.2℃对 HVAC 来说勉强能用但要显示 0.1℃ 分辨率就很尴尬。用示波器看变送器输出发现高频噪声有几十毫伏。加了 RC 滤波之后降到 ±3 个码。如果还想再稳可以把 ADC 采样结果每 100ms 做一次平均但要注意报警判定的延时。另外如果主板上有继电器或者晶闸管尽量让它们和模拟输入拉远一点或者在层间铺地隔离。5.4 上电瞬间数码管乱码、RS485 收乱码这种现象多是上电时序问题。单片机上电后 IO 默认是高阻输入74HC595 的输出锁存端如果被悬空输出就可能乱闪。我处理方式是板上加一个 RC 延时复位电路让单片机复位后再初始化 IO 状态。RS485 收乱码通常是 DE/RE 引脚在上电瞬间被外部干扰拉高导致 RS485 芯片处于发送状态或者收发切换没有初始化为接收模式。固件里第一步就把 DE/RE 拉低再配置 UART就能避免。5.5 温度显示不准标定流程怎么定才靠谱两点标定只适合线性度好的模块。PJ85718DM 这类变送器出厂前已经校准但如果安装位置、供电电压变化零点仍然会有偏差。我的标定流程是先让传感器和标准温度计在同一环境下静置 30 分钟记录 ADC 值和标准温度作为低点再用恒温槽或精密干井设定 80℃ 作为高点。两点拟合之后全量程误差可以控制在 ±0.3℃ 以内。如果现场没有恒温槽至少也要用冰水混合物做零点标定参考意义很大。5.6 常见问题速查表现象可能原因处理办法读数持续偏高变送器供电偏低或模块零点漂移单独供电重新两点标定读数持续偏低ADC 参考电压偏高或采样时间不足检查 VREF增大采样时间至 20 Tad刷新时数字跳动滤波窗口太短或显示扫描冲突增加平滑点数把显示刷新和采样错开远程读数为 0Modbus 地址映射错误或 CRC 校验失败检查寄存器地址串口监视收发帧总线无响应RS485 方向切换时序错误示波器看 DE 引脚增加发送完成延时设备反复重启WDT 超时或电源跌落读取复位原因寄存器改善供电走线最后分享点个人心得这套项目做完之后我自己有个很深的体会温度监测系统看起来简单真正考验人的不是单片机代码而是电源、地和信号调理这些“看不见的战场”。PIC18F87K22 是一颗很成熟的芯片在项目里给我很大自由度而 PJ85718DM 这种模块化的变送器则帮我省掉了模拟前端的设计调试时间两者搭在一起属于“8 位机也能干漂亮活”的典型组合。如果你正在规划类似的小型温控设备、HVAC 外援监测板或者 Modbus 从站顺着这条线往下做基本不会跑偏。后面我还会把这套代码整理成带注释的全量工程放到网上供大家直接参考。
延伸阅读

更多相关文章

2026/10/22 12:11:02

国庆AI动态深度解读:多模态、Agent与开源权重如何落地

开工第一天,我身边好几个做AI的朋友,见面第一句话几乎都不是问国庆去哪玩了,而是“你这几天刷了多少AI消息”。国庆七天,AI圈没一天消停——模型发布、开源权重、论文突破、产品更新,几乎每天都有几条值得细看的信息。…

2026/10/22 12:11:02

【SLAM】PCL:通过条件设置或者半径设置去除指定点云

/* 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 12:11:02

【SLAM】PCL:使用VoxelGrid filter对点云进行下采样

/* 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 17:08:59

C语言:指针的理解

/* 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 17:08:59

JAVA:基本数据类型详解

/* 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 17:03:55

PJ85718DM+PIC18LF45K40构建高可信温度传感链路

/* 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 11:29:28

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/22 0:01:49

电商智能运营体系从0到1:架构设计、落地步骤与避坑指南

前两年我们团队接了一个电商平台的运营中台项目,目标很直白:把过去靠运营拍脑袋做的选品、定价、发券、推活动这些事,逐步用数据算法和自动化流程代替。项目名字内部就叫“电商智能运营体系”。最近有不少朋友问我当时是怎么设计的、踩过哪些…

2026/10/22 0:01:49

若依框架AI代码生成不稳定?用Agent Skill三层结构+五步法搞定

最近一段时间,我一直想把后台管理系统里那些机械重复的增删改查代码交给AI去写。框架用的是若依,按理说这类业务代码模式非常固定,应该是AI最擅长的事情。可真试下来却不是那么回事——你让AI生成一个用户管理模块,它给出的Contro…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑