基于PJ85718DM与STM32F334R8的分布式温度监测系统设计与实现

发布时间:2026/10/22 6:42:20
基于PJ85718DM与STM32F334R8的分布式温度监测系统设计与实现 我做过不少温度采集的项目从简单的单点测温到多节点组网都碰过。但说实话用 PJ85718DM 这颗芯片来做温度监测的方案市面上讨论得不太多。正好最近在某跨平台系统项目里我用它配合 STM32F334R8 搭了一套同时覆盖本地和远程温度监测的系统顺带也适配了 HVAC 场景的需求。整个过程踩了不少坑也积累了一些可以直接拿去用的经验整理出来分享给想走同样路线的开发者。这套方案的核心价值在于PJ85718DM 负责温度采集STM32F334R8 负责数据处理和通信调度通过 RS485 总线把本地节点的温度数据汇聚到上位机同时利用单片机的 DAC 和比较器资源做温度越限预警。也就是说一套硬件同时解决了“现场看数据”和“远程盯温度”两个需求。对于做嵌入式温控、HVAC 系统、机房环境监测这类项目的开发者来说这套架构有比较强的参考意义。1. 整体设计与思路拆解为什么选 PJ85718DM 和 STM32F334R8做温度监测方案芯片选型往往决定了整个项目的开发难度和后期维护成本。很多人一上来就选数字温度传感器比如常见的 DS18B20 或者 SHT30。但在这个项目里我选 PJ85718DM 不是偶然而是因为它有几个特性恰好贴合了嵌入式和 HVAC 场景的需求。PJ85718DM 是一颗模拟输出的温度传感器典型输出是电压信号电压与温度呈线性关系。这意味着它不需要复杂的通信时序直接接 ADC 通道就能读。对于 STM32F334R8 来说内置的 12 位 ADC 足够应付这种模拟信号的采集而且精度完全够用。为什么不用数字传感器数字传感器虽然接口简单但在长线传输和强干扰环境下通信时序容易受电磁干扰影响。HVAC 系统里压缩机启停会产生比较大的浪涌和噪声数字传感器在这种环境下偶尔会出现通信错误排查起来很头疼。模拟传感器就不一样输出的是连续电压信号即使受到干扰最多是读数波动不会出现通信中断这类硬故障。STM32F334R8 的选择也有讲究。它是 M4 内核带 FPU 的芯片主频 72MHz虽然不是特别强但跑温度采集和协议处理绰绰有余。更重要的是这颗芯片自带高精度定时器、DAC 和比较器。我在项目里用 DAC 产生一个阈值电压再用比较器把 PJ85718DM 的输出电压和阈值做硬件比较一旦温度越限直接触发中断信号。这种硬件联动方案比纯软件轮询要可靠得多响应速度是微秒级的。从架构上看这套系统分三层感知层、控制层、应用层。感知层就是 PJ85718DM负责把温度转换成电压控制层是 STM32F334R8负责采集、换算、协议组包和预警输出应用层是上位机或者触摸屏通过 RS485 或者 Modbus 协议读取数据实现远程监测。2. 核心参数与硬件设计PJ85718DM 的温度-电压特性分析PJ85718DM 的典型工作电压是 3.3V 或者 5V我在项目里用了 3.3V 供电。这里要特别注意供电电压直接影响输出电压范围而输出电压范围又决定了 ADC 采样的分辨率利用率。这颗芯片的温度-电压关系基本是线性的典型灵敏度大概在 10mV/°C 左右。以 0°C 为参考点0°C 时输出电压大约是 500mV温度每升高 1°C输出电压增加 10mV。那么室温 25°C 时输出电压就是 500 25×10 750mV。这个电压范围对 STM32F334R8 的 ADC 来说非常友好因为参考电压设置为 3.3V 时750mV 对应的 ADC 数值大概是 750/3300×4095 ≈ 931。这里有一个关键点如果直接用线性公式换算温度需要注意零点偏移。不同批次的 PJ85718DM 可能会有微小的零点差异。我建议在项目初期做一次校准方法很简单用一颗已知精度的参考温度计在当前环境下测出实际温度 T_ref同时读取 PJ85718DM 的输出电压 V_measured然后计算实际零点偏移 V_offset V_measured - (T_ref × 0.01)把这个偏移量存到 Flash 里以后每次换算都扣掉这个偏移。硬件连接上PJ85718DM 的输出脚直接连 STM32F334R8 的 ADC 输入引脚比如 PA0。注意在 ADC 引脚和地之间加一个 0.1μF 的滤波电容这对抑制高频干扰有明显效果。我一个朋友刚开始没加这个电容读数波动达到 ±1.5°C加了电容之后稳定到 ±0.2°C 以内差距非常大。如果需要采集多个位置的温度可以在 PA0 到 PA3 上接多个 PJ85718DMSTM32F334R8 的 ADC 支持扫描模式可以依次采集。但要注意ADC 引脚输入阻抗有限如果传感器距离超过 1 米建议在传感器输出端加一个电压跟随器否则采样值会偏低。3. STM32F334R8 的软件架构与实现ADC 采集、滤波与数据处理软件这块我采用了分层结构驱动层、协议层、应用层。驱动层负责 ADC 初始化和数据读取协议层处理 Modbus 组包解析应用层负责温度换算、越限判断和逻辑控制。这样的好处是后续如果要换更高级的芯片或者加功能模块只需要改驱动层应用层基本不用动。ADC 初始化关键代码如下void ADC_Init(void) { ADC_ChannelConfTypeDef sConfig {0}; hadc1.Instance ADC1; hadc1.Init.ClockPrescaler ADC_CLOCK_SYNC_PCLK_DIV4; hadc1.Init.Resolution ADC_RESOLUTION_12B; hadc1.Init.DataAlign ADC_DATAALIGN_RIGHT; hadc1.Init.ScanConvMode DISABLE; hadc1.Init.EOCSelection ADC_EOC_SINGLE_CONV; hadc1.Init.LowPowerAutoWait DISABLE; hadc1.Init.ContinuousConvMode DISABLE; hadc1.Init.NbrOfConversion 1; hadc1.Init.DiscontinuousConvMode DISABLE; hadc1.Init.ExternalTrigConv ADC_SOFTWARE_START; hadc1.Init.DMAContinuousRequests DISABLE; HAL_ADC_Init(hadc1); sConfig.Channel ADC_CHANNEL_0; sConfig.Rank 1; sConfig.SamplingTime ADC_SAMPLETIME_239CYCLES_5; HAL_ADC_ConfigChannel(hadc1, sConfig); }采样时间这里我选了 239.5 个周期也就是约 3.3μs。对于模拟温度传感器来说采样时间越长内部采样电容充电越充分精度越高。如果你发现读数跳变比较厉害优先把采样时间调大而不是盲目加滤波算法。温度采集不是读一次就完事的我做了多次采样取平均的处理。具体方法是每次读取 10 个采样值去掉最大值和最小值然后对剩下的 8 个值求平均。这个操作能有效滤除偶发性的尖峰干扰同时又不会像滑动平均滤波那样引入明显的滞后。uint16_t ADC_ReadFiltered(ADC_HandleTypeDef *hadc) { uint16_t samples[10]; uint16_t min_val 0xFFFF, max_val 0; uint32_t sum 0; for (int i 0; i 10; i) { HAL_ADC_Start(hadc); HAL_ADC_PollForConversion(hadc, 10); samples[i] HAL_ADC_GetValue(hadc); } for (int i 0; i 10; i) { if (samples[i] min_val) min_val samples[i]; if (samples[i] max_val) max_val samples[i]; } for (int i 0; i 10; i) { if (samples[i] ! min_val samples[i] ! max_val) { sum samples[i]; } } return sum / 8; }温度换算公式为float ADC_To_Temperature(uint16_t adc_value) { float voltage (float)adc_value * 3.3f / 4095.0f; float temperature (voltage - 0.5f - calibration_offset) / 0.01f; return temperature; }这个公式里的 0.5 就是 0°C 时对应的输出电压。如果你的 PJ85718DM 零点偏移较大需要把 calibration_offset 考虑进去否则所有温度都会整体偏差。实际运行下来这套软件配合外部滤波电容温度读数的稳定性很好。在室温环境中连续跑了 72 小时最大波动不超过 ±0.3°C完全满足 HVAC 环境监测的要求。4. 远程监测实现RS485 通信与 Modbus 协议栈移植远程温度监测的通信方案我采用的是 RS485 总线加 Modbus RTU 协议。为什么选 RS485因为 HVAC 场景里设备分布范围广RS485 支持最长 1200 米的传输距离而且总线拓扑可以挂载多个节点一个主机就能轮询所有温度采集点。硬件上我用了一个廉价的 RS485 收发芯片A 和 B 引脚接总线RO 和 DI 分别接 STM32F334R8 的 USART 引脚DE/RE 接一个普通 GPIO 用于方向切换。这里有个容易踩坑的地方DE/RE 方向切换必须在上发送数据之前完成而且要留出一定的建立时间。我在调试中遇到的第一版程序就是发送前没有延时导致帧头丢字节。再说 Modbus 协议。Modbus RTU 是工业领域最通用的协议之一几乎所有的上位机、触摸屏和组态软件都支持。我用的寄存器规划如下寄存器地址功能寄存器数量0x0000本地温度值 ×1010x0001远程节点1温度值 ×1010x0002远程节点2温度值 ×1010x0010温度越限标志位1用 ×10 的原因是为了支持 0.1°C 的分辨率。Modbus 寄存器本身是 16 位整数直接用浮点数的话协议层处理太繁琐用整数放大 10 倍既保持了精度又避免了浮点传输的问题。关于 Modbus 轮询和中断接收的配合我建议用串口空闲中断来检测一帧数据的结束。STM32 的串口空闲中断是很实用的功能当总线安静下来说明一帧数据接收完毕这时候再解析数据就不会出现粘包或者半帧问题。我自己实现的简化版 Modbus 从机帧处理逻辑是收到一个字节就记入缓冲区同时记录字节数。当串口空闲中断触发后检查缓冲区前两位是地址和功能码。如果地址匹配本机地址就根据功能码执行对应操作。功能码 0x03 读保持寄存器是最常用的实现也最简单。void MODBUS_ProcessFrame(uint8_t *buffer, uint16_t len) { uint8_t address buffer[0]; uint8_t func_code buffer[1]; if (address ! DEVICE_ADDR) return; if (func_code 0x03) { uint16_t start_reg (buffer[2] 8) | buffer[3]; uint16_t reg_count (buffer[4] 8) | buffer[5]; MODBUS_BuildReadResponse(start_reg, reg_count); } if (func_code 0x06) { uint16_t reg_addr (buffer[2] 8) | buffer[3]; uint16_t reg_value (buffer[4] 8) | buffer[5]; MODBUS_ProcessWriteSingle(reg_addr, reg_value); } }这套通信方案实测下来在 9600 波特率下非常稳定一帧数据发送完成时间约 5ms对于一个最多 16 个从站的系统来说轮询一遍只要 80ms实时性完全够用。HVAC 系统里温度变化本来就缓慢这个刷新率绰绰有余。5. 本地监测的补充手段LCD 显示和按键操作远程监测解决的是“不在现场”的问题但本地监测同样不能少。我在系统上加了一块 12864 液晶屏和三个按键通过菜单可以切换显示不同节点的温度值也可以设置温度上下限。这里有个设计心得菜单逻辑要尽量简单不要搞那种层级很深的操作界面HVAC 维护人员不会有耐心去翻好几级菜单。我设计的方案是默认界面显示本地温度按下“切换”键可以循环切换到远程节点温度显示在温度显示界面按下“设置”键进入上限或下限设置模式用“加”和“减”键调整数值。LCD 显示温度时我用了简单的字库存储功能把 0 到 9 这 10 个数字和温度单位符号做成了一个数组查表显示。这么做的原因是 12864 屏幕本身集成了汉字字库直接写字符串就行但我发现直接调用字库接口有时候会造成显示缓冲和刷新的冲突所以统一走取模数组更可靠。按键处理这块必须要加消抖和松手检测。一个很常见的错误是按下按键一次程序却识别成了十几次。根本原因是机械按键的抖动和未加消抖逻辑。我的处理方式是在定时器中断里每 10ms 扫描一次按键状态连续两次状态一致才认为按键有效然后直到检测到松开状态才允许下一次按下。本地显示的温度和远程通信读取的温度可以使用同一套换算函数这样保证了本地和远程看到的数据一致性。不然本地显示 25.3°C远程上位机显示 25.8°C维护人员会有困惑。6. 完整系统搭建从接线到联调的现场记录这部分我说一下整机搭建过程中需要注意的地方。首先是电源设计。PJ85718DM 模拟输出对电源纹波敏感如果直接用开关电源供电纹波会在 ADC 采集中体现出来表现为读数周期性跳动。解决办法有两种一是加一个 LDO 给传感器单独供电二是用 π 型滤波电路。我用了前者效果立竿见影读数立刻稳定下来。其次是地线处理。如果系统里有继电器或接触器它们的开关瞬间会产生很大的电流突变在这个回路中会形成地线电位差直接影响 ADC 的参考地。我的做法是数字地和模拟地在 PCB 上单点连接用磁珠隔开。这个细节如果处理不好软件怎么写滤波都无法消除波动。再来是 RS485 总线的终端电阻。总线两端各接一个 120Ω 电阻是必须的。如果不接总线上的信号反射会导致通信误码率升高尤其是总线长度超过几十米之后。我自己测试过不加终端电阻时总线长度 50 米就有偶发通信故障加上电阻后彻底消失。联调过程中我遇到过一个问题STM32F334R8 的 ADC 读数始终比用万用表测量的电压对应值偏低。排查过程是这样的先检查参考电压配置发现是正常的 3.3V再用示波器测量传感器输出发现波形正常但幅值略低。最后发现是 ADC 引脚的输入阻抗和传感器输出阻抗形成分压导致 ADC 读到的电压偏低。解决方案就是在传感器输出和 ADC 引脚之间加了一个运放做电压跟随这里的运放我用的是 LM358工程上比较通用常见。换上之后读数就很准确了。7. 常见问题与排查技巧实录问题现象可能原因排查方法温度读数明显偏高/偏低零点偏移未校准对比参考温度计计算并存储校准偏移量读数周期性波动电源纹波干扰用示波器看传感器供电电压加 LDO 或 π 滤波多个节点读同一温度但数值不同ADC 引脚间串扰或参考电压不一致适当增加采样间隔时间检查参考电压回路通信偶发帧错误缺少终端电阻或波特率误差在总线两端各接 120Ω 电阻LCD 显示乱码刷新与数据写入冲突显示刷新加临界区保护避免在中断里写显示这里值得单独提一下的是波特率误差问题。STM32F334R8 的 USART 波特率是由时钟分频产生的如果用内部 RC 振荡器作为时钟源频率本身存在约 ±1% 的误差。在较长的 RS485 总线上这一误差会被放大导致帧错误。解决方法是使用外部晶振或者对上位机采用自动波特率检测机制。另外关于越限报警我利用了 STM32F334R8 的比较器。DAC 输出设置为温度上限对应的电压值PJ85718DM 输出电压与 DAC 输出进行比较一旦传感器电压超过阈值比较器输出电平翻转触发中断。GPIO 翻转中断里直接驱动一个 LED 或者继电器做本地报警。这个方案的好处是响应速度极快不依赖软件轮询周期。实测从传感器电压越过阈值到中断触发只需要几百纳秒。8. 这套方案的扩展空间从单点测温到物联网节点这套系统做完之后扩展空间其实不小。如果你有多个 STM32F334R8 节点分布在不同的房间每个节点都采集本地温度然后通过 RS485 总线级联到同一个主机就形成了一个典型的分布式温度监测网络。主机的 Modbus 主站可以轮询每个从站在组态软件上绘制实时温度曲线并生成历史数据报表。更进一步的方案是给主机接一个工业网关把 Modbus 数据转换成 WLAN 协议上传到云端或者接入现有的楼宇自控系统。这样运维人员就能通过云端平台远程查看所有节点的温度并设置报警策略。传统的 HVAC 系统大多以就地控制为主数智化改造升级在这类场景里是重要趋势。还有一个思路利用 STM32F334R8 的内置运放对 PJ85718DM 输出电压再进行一级放大提高低温段的采样分辨率。如果应用中关注低温极限工况这个改造就有意义。把 10mV/°C 放大到 20mV/°C在 12 位 ADC 下每个温度 LSB 对应的电压更小整个量程内的量化误差也相应缩小。我在实际使用中发现模拟温度传感器加高性能 MCU 的组合在工业级温度监测中反而比很多纯数字方案更抗造只要把硬件滤波和校准做扎实长期稳定性非常有保证。某次连续运行测试期间我的系统与标准温度计对比误差稳定在 ±0.3°C 以内这个精度对于 HVAC 环境监测绰绰有余。最后再分享一个小技巧如果你的项目需要使用多颗 PJ85718DM 而手上没有参考温度计做校准可以把所有传感器探头绑在一起放到恒温环境中读取它们的输出电压找到与均值的偏差作为一个相对校准补偿。这一步能消除不同传感器个体差异带来的读数不一问题实测效果还不错。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询