资讯动态

STM32F107VC单总线温度传感器多点监测设计与LwIP远程上报

发布时间:2026/10/22 17:01:17 来源:尧图企业网站定制
搞过HVAC项目或者做过嵌入式环境监测的兄弟应该都有同感温度测点又多又分散回风口、送风管、室外新风、室内几个房间每个点都拉一堆模拟量线回来调试起来简直想骂人。最近我在做一个空调机组的温度监测改造方案上选了PJ85718DM这颗单总线数字温度传感器搭配STM32F107VC做主控把本地显示和远程网络上报一次做完了。这套组合解决的核心问题有两个一个是就地侧主控板旁边挂几个传感器OLED直接把所有温度打出来现场调试不用开电脑另一个是远程侧传感器通过一根双绞线分布在几十米外的风管和房间里全部温度汇总到MCU后再走以太网发给上位机。也就是说本地温度和远程温度都纳入了同一套监测体系。如果你是做嵌入式设备、楼宇自控或者暖通配套控制的这篇文章可以直接当参考笔记用。我不打算只贴代码而是把选型逻辑、硬件设计、单总线驱动、LwIP网络上报、调试现场踩过的坑从头到尾说透项目里遇到同类需求可以直接抄作业。1. 需求拆解与方案选型为什么是单总线传感器加F1071.1 HVAC场景下温度监测的真实需求先说现场需求。暖通空调的温度监测点和普通消费电子不太一样测点不但多而且位置极其分散。一个典型的空调机组回风温度传感器在机组回风口送风温度在盘管后风道内防冻开关旁边还要有一个低温保护测点室外新风温度探头得拉到屋外室内侧可能还分布在好几个房间。这些点离控制器的距离短则两三米长则三五十米。本地监测和远程监测是同时存在的需求。本地指设备机柜就地能看温度远程指把温度送到楼宇中控或者值班室电脑上。以前的做法很传统每个测点用一只NTC热敏电阻加一路模拟量输入测温范围窄、非线性还要查表校准最麻烦的是长距离传输时导线电阻会直接影响精度。后来改PT100加变送器精度上去了但调理电路和变送器成本也跟着上去了一个点就是大几十块十几个点成本就很可观。对比之后PJ85718DM这类单总线数字传感器优势很明显。温度值直接在传感器内部完成ADC转换通过单总线协议以数字方式输出全程不受线缆电阻和模拟干扰影响。一条总线上可以挂多个器件因为每个器件出厂有唯一的ROM序列号。这样HVAC现场常见的多点分散测温和长线传输问题一根双绞线就解决了不用每个点都单独拉一堆模拟线。1.2 器件选型逻辑为什么不是普通单片机加模拟量处理PJ85718DM属于单总线数字温度传感器这一类工作电压范围覆盖3.0V到5.5V测温范围覆盖常见HVAC场景的-55℃到125℃分辨率可以通过配置寄存器选择默认精度在±0.5℃左右。这些参数对于机房、风管、室内环境监测完全是够用的。这里要提醒一句不同厂商的单总线温度芯片在时序细节上多多少少有差异拿到实物先对一下器件手册我下面讲的代码逻辑是基于最常见的单总线协议来写的只要你手头的PJ85718DM遵循同类协议基本可以通用。主控选STM32F107VC最核心的原因就是它自带以太网MAC控制器。当时也纠结过用F103和F407F103便宜但内置MAC都没有要联网就必须外挂SPI转以太网芯片多一颗芯片意味着多一份BOM成本还要把SPI口和中断引脚占掉。F407性能过剩用在温度采集这种低频场景有点浪费。F107VC这颗芯片是Cortex-M3内核主频72MHz内部有256KB Flash和64KB SRAM带以太网MAC、CAN、USB OTG和多路串口。对于HVAC这类既要跑本地逻辑又要走网络协议的场景它的定位就是刚好合适。做HVAC设备还有一个现实问题工业现场电源环境并不干净变频压缩机启停、电磁阀动作都会带来干扰。F107的工作温度范围和抗干扰能力在同类MCU里属于比较稳的这也是工业类产品选型时的一个重要考量。1.3 整体架构本地温度和远程温度是如何组织在一起的项目里我把“本地”和“远程”拆成了两个维度这样容易说清楚。空间维度的远程指传感器不在主控板上而是通过长线分布在远端。我用两条独立的总线第一条总线放本地传感器挂在控制器的PCB端子座上测机柜环境温度和箱体进风温度第二条总线通过一个接插件引出用一根屏蔽双绞线拉到几十米外的风道和房间里挂上六到八个传感器。两条总线由MCU的两个不同GPIO引脚驱动互不干扰某一条总线被干扰时另一条还能正常工作。信息维度的远程指数据从设备端通过网络上传。F107内置以太网MAC外接一颗PHY芯片就能跑LwIP协议栈我在板子上实现了TCP Server上位机通过网络调试工具或者自写的Python脚本发起连接就能读取所有传感器的实时温度。相当于每个节点本身是一台小服务器上位机随时可以拉数据。整体数据流向是这样的MCU轮询两条总线上的所有传感器把温度值存到一个结构体数组里OLED本地循环显示同时TCP服务线程监听以太网端口收到上位机的读取指令后把整个温度数组打包发送出去。本地显示和远程读取用的是同一份数据源不需要额外同步。2. 硬件搭建要点总线、接口与外围电路2.1 单总线传感器接入电路上拉电阻不是随便选的单总线传感器的电气接口非常简单核心就是一根数据线DQ加上电源和地。数据线必须接一个上拉电阻到VCC这是因为器件工作在开漏模式没有总线主机拉高的时候数据线要靠上拉电阻维持高电平。上拉电阻的取值是第一个跳跃点。短距离、传感器少的时候4.7kΩ是标准值稳定可靠。但是HVAC现场动不动就是三五十米的长线线缆分布电容和电阻都会影响信号上升沿。线越长分布电容越大上升沿就越缓时序上就容易超时。我在远程那条总线上实测30米双绞线配4.7k上拉偶尔出现读不到应答的情况换成2.2k上拉后问题就消失了因为电阻变小充电电流变大上升沿变快时序裕量被找回来了。这里有个反直觉的坑不要在总线上并太大的电容。很多人习惯在电源引脚旁边加个100nF退耦电容这没错但如果把这颗电容直接并到DQ线上它会和上拉电阻形成RC延迟让上升沿变得更慢反而把时序搞坏。DQ线上的ESD保护或者滤波建议只保留寄生电容级别我一般不加额外的电容靠屏蔽线的分布电容就够。供电方式上PJ85718DM支持外部供电和寄生供电两种模式。实际项目里我毫不犹豫选了外部供电每个传感器单独接VDD和GNDDQ走数据。寄生供电看着省一根线但在长线场景下问题非常多传感器做温度转换时需要从DQ线上窃取电流总线电压会被拉低主机侧如果上拉能力不够强轻则转换超时重则直接导致复位失败。HVAC现场变频器一启动电源波动本来就不小别在这种地方省一根线。线缆选择上我用的屏蔽双绞线屏蔽层单端接地。普通平行线我在调试中发现附近有继电器吸合时偶尔会出现CRC校验错误换屏蔽线后这类问题明显减少。2.2 STM32F107VC最小系统与外置PHY芯片STM32F107VC的最小系统部分属于常规操作但还是有几个点值得说。MCU使用8MHz无源晶振配合两个20pF到22pF的负载电容通过PLL倍频到72MHz运行。注意晶振布局要尽量靠近MCU的OSC_IN和OSC_OUT引脚负载电容的地要短而粗地回到MCU的GND引脚这个细节直接影响主时钟的稳定性以太网通信的时钟源又对稳定性敏感不能马虎。以太网部分F107内置的MAC控制器不能直接接RJ45外面必须配一颗以太网PHY芯片。接口模式我选了RMII因为RMII相比MII少了一半引脚而且信号速率固定100Mbps模式下只需要50MHz的参考时钟。RMII的引线要求是等长处理特别是TX_EN、TXD0、TXD1这些信号长度差控制得越小越好我用的是两层板布线时尽量让这些信号走同一层且路径接近实测通信稳定。RMII参考时钟有几种来源用外部50MHz有源晶振直供PHY、由PHY内部倍频后输出、或者由MCU的MCO引脚输出50MHz。我用的是外部50MHz无源晶振配合PHY内部的振荡电路这样PHY和MAC能在同一时钟源下工作省去时钟不同步的麻烦。上电后调试的第一步一定要能正确读到PHY芯片的寄存器ID不然后面所有网络调试都是白费力气。RJ45我用了带网络变压器的集成座内部有隔离变压器这是以太网物理层的标配不要省。隔离变压器的中心抽头要按PHY芯片手册要求接偏置电压接法错了会出现能连接但无法通信的诡异问题。2.3 本地显示与交互接口设计本地显示选用了一块0.96英寸的I2C接口OLED4个引脚就搞定对于显示多个温度点完全够用。I2C地址一般是0x3C或0x3D买到的模块不确定时可以在初始化时扫描一下地址这个习惯能省不少排查时间。按键交互设计了三键方案一个模式切换键用于在“本地点选”和“远端点选”画面之间切换两个阈值调整键用于调整本地报警上限和下限阈值。报警执行部分是一个有源蜂鸣器加一个双色LED超上限报警时亮红灯低于下限报警时亮黄灯蜂鸣器通过三极管驱动GPIO直接驱动蜂鸣器的电流不够容易把引脚烧坏。蜂鸣器驱动引脚还要并联一个续流二极管不然断电瞬间的反向电动势会打坏三极管。GPIO分配可以给个参考我直接列在下面的表里功能MCU引脚说明本地总线DQPA0开漏输出外接4.7k上拉远程总线DQPA1开漏输出外接2.2k上拉OLED SDAPB7I2C数据线OLED SCLPB6I2C时钟线蜂鸣器PB0经三极管驱动报警LEDPB1双色灯模式键PA4内部上拉阈值加/减键PA5、PA6内部上拉ETH RMIIPD0-PD5F107专用引脚ETH MDIO/MDCPA2、PC1PHY管理接口按键全部使用内部上拉外部不用再放上拉电阻省一点BOM。OLED和蜂鸣器都是3.3V供电与MCU电平一致不需要电平转换。3. 软件驱动与通信协议实现3.1 用GPIO模拟单总线时序关中断是必须的单总线协议的基石就是精确的时序。整个通信过程是一系列特定时间长度的电平跳变对HAL库这种经过多层封装的函数来说延时精度太差必须用寄存器级别操作加空循环延时来实现。先定义总线结构体这样两条总线可以复用同一套驱动代码typedef struct { GPIO_TypeDef *port; uint16_t pin; } ow_bus_t; #define OW_BUS_LOCAL {GPIOA, GPIO_PIN_0} #define OW_BUS_REMOTE {GPIOA, GPIO_PIN_1}GPIO配置成开漏输出模式。开漏模式下写0就是把引脚拉低写1就是把引脚释放由外部上拉电阻拉高完美契合单总线协议的电平要求。复位时序是整个通信的起点主机拉低总线至少480us然后释放等待传感器回应。传感器上电后会主动拉低总线60us到240us作为存在脉冲。代码实现uint8_t ow_reset(ow_bus_t *bus) { uint8_t presence 0; __disable_irq(); /* 拉低总线 520us */ GPIO_ResetBits(bus-port, bus-pin); delay_us(520); /* 释放总线 */ GPIO_SetBits(bus-port, bus-pin); delay_us(40); /* 读取存在脉冲 */ presence !GPIO_ReadInputDataBit(bus-port, bus-pin); __enable_irq(); delay_us(200); return presence; }读写一位时序有严格区分。写0时隙和写1时隙都是60us到120us区别在于低电平持续时间。写0要求整个时隙都保持低电平写1则是先拉低1到15us然后释放总线让上拉电阻拉高。读时隙稍微复杂一点主机先拉低1到6us然后释放在释放后的15us窗口内读取引脚电平因为传感器如果返回0会在这段时间内把总线拉低。uint8_t ow_read_bit(ow_bus_t *bus) { uint8_t bit 0; __disable_irq(); GPIO_ResetBits(bus-port, bus-pin); delay_us(5); GPIO_SetBits(bus-port, bus-pin); delay_us(9); bit GPIO_ReadInputDataBit(bus-port, bus-pin); __enable_irq(); delay_us(60); return bit; }我刻意在时序操作前后调用__disable_irq()关闭全局中断这是非常重要的一步。如果不关中断延时过程中一旦有定时器中断或者串口中断插入时序就会超时单总线通信当场失败。这也是为什么我不用HAL_DelayHAL延时依赖系统滴答定时器但滴答定时器中断本身就会打乱时序。3.2 多传感器ROM枚举与温度数据读取单总线传感器每个器件在出厂时都有一个64位的唯一ROM序列号这个设计让多个传感器可以在同一条总线上共存。读取流程分两条路线如果一条总线上只挂一个传感器主机可以发跳过ROM指令0xCC直接进入温度转换或者读取暂存器操作简单快速。但我要的是多点采集所以必须先把总线上所有传感器的ROM码读出来存到数组里后续通信用匹配ROM指令0x55逐个指定访问。ROM搜索算法是单总线协议最经典的一段逻辑思路是逐位读取并记录分支先读第一位两次如果两次读到的值不同说明当前总线上只有一个器件在该位是0或1可以确定方向如果两次都读到0说明有分叉需要记录选择路径。这个算法说起来简单但在位级别上做回溯还是容易绕晕我实现时把搜索过程放在了温度采集初始化阶段设备上电后执行一次之后传感器位置固定ROM码不会变直接缓存使用。读取温度的核心流程是这样的复位总线发送匹配ROM指令0x55然后发送该传感器的64位ROM码发送温度转换指令0x44等待转换完成12位分辨率下典型转换时间在数百毫秒量级我配置成12位模式后等待了约800ms再次复位总线发送匹配ROM指令发送读暂存器指令0xBE连续读取9个字节完整读取一个传感器的关键代码int16_t ow_read_temperature(ow_bus_t *bus, uint64_t rom) { uint8_t data[9]; uint8_t crc 0; int16_t raw 0; if (!ow_reset(bus)) return TEMP_READ_ERR; ow_write_byte(bus, 0x55); /* 匹配ROM */ for (int i 0; i 8; i) ow_write_byte(bus, (uint8_t)(rom (i * 8))); ow_write_byte(bus, 0x44); /* 启动温度转换 */ delay_ms(800); if (!ow_reset(bus)) return TEMP_READ_ERR; ow_write_byte(bus, 0x55); for (int i 0; i 8; i) ow_write_byte(bus, (uint8_t)(rom (i * 8))); ow_write_byte(bus, 0xBE); /* 读暂存器 */ for (int i 0; i 9; i) data[i] ow_read_byte(bus); crc ow_crc8(data, 8); if (crc ! data[8]) return TEMP_READ_ERR; raw (data[1] 8) | data[0]; return (int16_t)raw; }CRC校验必须做。单总线传感器返回的9个字节中最后一个字节是前8字节的CRC8校验值多项式是X^8X^5X^41。在长线传输和高频干扰环境下CRC偶尔会报错程序里对返回错误的情况做一次重试重试三次仍失败就丢弃该测点本次数据并做故障标记上层逻辑就不会把错误温度显示出来了。3.3 本地数据处理滤波、报警与OLED显示直接从传感器读到的温度虽然经过了CRC校验但还是偶尔会有毛刺尤其是电机启停的瞬间。我在显示和上报之前加了一道滤波方案是中值滤波加滑动平均。中值滤波的做法是连续读取5次温度值取中间的第三个值作为有效值。这个方法对付单点尖峰特别有效因为哪怕五次里有一两次读到异常值排序后异常值都会被排在两端不会进入最终结果。滑动平均则是在中值滤波的基础上再做一次加权平均让曲线更平滑避免画面上的温度跳变太快。滤波的代码如下float temp_filtered(float new_value) { static float buffer[5]; static uint8_t idx 0; float temp[5], sum 0; buffer[idx] new_value; idx (idx 1) % 5; for (int i 0; i 5; i) temp[i] buffer[i]; /* 简单冒泡排序取中值 */ for (int i 0; i 5; i) for (int j i 1; j 5; j) if (temp[j] temp[i]) { float t temp[i]; temp[i] temp[j]; temp[j] t; } for (int i 1; i 4; i) sum temp[i]; return sum / 3.0f; }浮点运算是有点浪费MCU资源但这个场景下72MHz的Cortex-M3跑起来毫无压力而且温度采集频率不高不用过度优化。本地报警逻辑放在滤波之后。系统每个采样周期把当前温度与预设阈值比较超上限时置位报警标志OLED画面温度数字变红蜂鸣器以2Hz频率鸣响直到温度回落并进入回差区间才解除报警。回差很重要没有回差的话温度在阈值附近波动会导致报警频繁通断现场听起来非常烦人。OLED驱动部分要注意0.96寸OLED一屏最多能显示多少个字符要提前规划好。我的界面是这样布局的第一行显示“LOCAL”加上本地温度第二行显示远端总线上前三个测点温度如果远端超过三个点通过按键切换到下一页。显示格式固定为xx.x℃避免浮点转字符串时占用过多时间。3.4 基于LwIP的以太网远程温度上报STM32F107VC移植LwIP协议栈用无操作系统的RAW API就可以跑起来。F107有64KB SRAM跑一个TCP Server绰绰有余但LwIP的配置还是要裁剪一下TCP窗口不要开太大PBUF池数量和大小按实际负载设置我用的是4个TCP连接上限每个连接的接收窗口控制在1460字节内存开销非常可控。移植LwIP时需要把底层接口对接好F107的以太网MAC驱动提供发送和接收函数PHY的状态查询通过MDIO/MDC管理接口完成。我在初始化时做了PHY地址匹配从F107的以太网寄存器里读到PHY ID后与硬件实际配置比对确认链路协商到的速率。TCP Server的初始化流程如下static struct tcp_pcb *server_pcb; static err_t server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { char *cmd; if (err ERR_OK p ! NULL) { cmd (char *)p-payload; if (strncmp(cmd, READ_ALL, 8) 0) { char reply[256]; int len snprintf(reply, sizeof(reply), TEMP: %.2f, %.2f, %.2f, %.2f, %.2f\r\n, temp[0], temp[1], temp[2], temp[3], temp[4]); tcp_write(pcb, reply, len, TCP_WRITE_FLAG_COPY); } pbuf_free(p); tcp_recved(pcb, p-len); } return ERR_OK; } static err_t server_accept(void *arg, struct tcp_pcb *newpcb, err_t err) { tcp_recv(newpcb, server_recv); return ERR_OK; } void ethernet_tcp_server_init(void) { server_pcb tcp_new(); tcp_bind(server_pcb, IP_ADDR_ANY, 9090); server_pcb tcp_listen(server_pcb); tcp_accept(server_pcb, server_accept); }主循环里每隔10ms调用一次tcp_tmr()这个函数驱动LwIP的TCP定时器不调用的话TCP连接状态机不会自动超时重传连接会挂在半开状态。我在实际调试中还发现一个问题上位机断电或者程序退出时TCP连接不会干净地关闭板子这边如果不处理就会出现旧连接占用PCB资源的情况。解决办法是在accept回调里对同一个客户端的重复连接做清理或者依靠LwIP的TCP_KEEPALIVE选项自动探测死连接。3.5 通信帧格式与上位机脚本TCP上报的协议我设计得比较简单因为自用为主不需要复杂方案。客户端发送一个ASCII命令服务器返回一帧数据数据帧格式如下字段长度说明帧头1字节0xAA传感器数1字节0x01-0x10温度区N×2字节每个温度用int16放大100倍单位0.01℃CRC81字节对前面所有字节计算温度用int16放大100倍传输而不是直接用float这是网络传输的常规操作。float在跨平台通信中有字节序和表示格式差异的问题int16没有这个问题固定按小端序传输即可。上位机只需要做一次除法就能还原成摄氏温度。为了远程监控调试方便我写了一个简单的Python上位机脚本import socket import struct s socket.create_connection((192.168.1.233, 9090), timeout5) s.sendall(bREAD_ALL) header s.recv(1) if header b\xaa: count s.recv(1)[0] payload s.recv(count * 2 1) temps [struct.unpack(h, payload[i:i2])[0] / 100.0 for i in range(0, count * 2, 2)] print(本地温度: %.2f℃ % temps[0]) print(远程温度: , .join(%.2f℃ % t for t in temps[1:]))命令设计为READ_ALL和READ_ONLY两个指令实际操作中还可以扩展SET_THRESHOLD指令让上位机直接改写报警阈值省去现场按键操作。通信连接方式用TCP主要考虑HVAC监控室上位机和设备之间可能跨交换机TCP有重传机制比UDP可靠得多。4. 完整联调过程与关键参数记录4.1 分级联调从点灯到全系统打通整个系统不是一次性上电就通的我习惯严格遵守从小到大的联调路径。第一级是电源和最小系统上电后先用万用表确认3.3V输出正常然后用一个LED点灯程序验证MCU核心和晶振工作正常。第二级调试单总线部分。先用一根很短的杜邦线接一个传感器用串口打印复位应答和ROM码。这个阶段最容易暴露的问题是GPIO配置错误比如忘记配置成开漏模式或者上拉电阻没有焊接表现就是复位永远不成功。把第一个传感器读通之后再往总线上挂第二个、第三个逐步增加节点数观察搜索到的ROM码数量是否与实际一致。第三级调试OLED显示。等到总线上的温度数据能稳定读到了再驱动OLED显示检查是否有花屏、地址不对、字库缺字等问题。OLED地址错误时屏幕完全不亮或者全亮这个很好判断。第四级调试以太网。先用网线连接路由器和开发板通过串口打印DHCP分配到的IP地址然后在PC上ping一下通了再跑TCP Server用Python脚本连接测试。这个阶段我踩过最大的坑是RMII时钟问题导致PHY无法协商后面单独讲。第五级接入真实的HVAC试点环境。把远程总线的传感器分别放到回风口、送风管、室外新风处本地传感器留在控制机柜开启空调运行观察温度变化趋势是否合理。送风温度在制冷模式下应该明显低于回风温度室外温度如果比室内高或者低都取决于季节这些规律能帮我快速判断传感器是否安装正确。4.2 关键参数与配置记录整理一份项目参数记录方便复现时对照参数项配置值备注MCU主频72MHz8MHz晶振×9倍频本地总线上拉4.7kΩ短线短距离远程总线上拉2.2kΩ30米双绞线实测传感器数量本地2个远程6个最多可扩到8个每路温度分辨率12位转换时间约800ms采样周期1秒轮询一遍所有测点滤波策略中值滑动平均5次取中值再平均以太网接口RMIIPHY外置TCP端口9090服务端监听静态IP192.168.1.233避免DHCP抖动报警回差1℃防止阈值反复触发远程总线长度超过30米时2.2k上拉还能不能稳取决于线缆质量和现场干扰强度建议先用示波器看一下上升沿和下降沿上升沿时间控制在1us以内比较保险。4.3 实测数据本地和远程到底准不准联调完成后我把所有测点跑了一天对比水银温度计的数据如下测点PJ85718DM读数水银参照偏差本地机柜26.4℃26.1℃0.3本地进风24.9℃25.0℃-0.1远程回风27.2℃27.0℃0.2远程送风15.8℃15.9℃-0.1远程室外18.3℃18.1℃0.2远程房间25.6℃25.5℃0.1从数据看最大偏差在0.3℃以内对于HVAC环境监测完全够用。上位机通过TCP读取到的数据与OLED本地显示一致两者来自同一份内存数据不存在二次采集差异。网络读取延时在局域网内基本可以忽略每秒刷新一次完全没压力。连续24小时运行时远程总线出现过几次CRC错误但重试机制都自动恢复了没有丢点数。调试中还发现一个现象送风温度测点在制冷刚启动时读数会先掉到很低再回升这是传感器贴在风管壁上的热惯性导致的不是硬件问题属于正常现场现象。5. 常见故障与排查技巧实录5.1 总线上读不到任何设备这是初次上电最常遇到的问题。排查顺序坚决固定不要跳步。第一步用万用表量总线上三个引脚的电平DQ应该是高电平如果DQ被拉低到地说明总线上有传感器短路或者接线错误这时候复位永远读不到应答。第二步检查上拉电阻是否焊接没焊上拉的话DQ悬空电平不确定也会有诡异表现。第三步用示波器观察复位波形看是否存在480us以上的低电平脉冲以及低电平释放后是否有应答脉冲。如果示波器看到主机复位脉冲但没看到应答脉冲把传感器在断电状态下重新插拔一次排除接触不良。远程总线上的设备排查还有个技巧把总线上的传感器从远端逐段断开从靠近主控的一端开始试每断一段就扫一次总线很快就能定位到故障节点。千万不要在总线上挂着一堆设备的时候做替换测试那样很难区分是哪个节点把总线拖死的。常见问题整理现象可能原因处理办法复位无应答DQ接反或短路量电平查接线复位无应答上拉电阻缺失补焊4.7k或2.2k应答不稳定线缆过长干扰大换屏蔽线或降上拉电阻只识别到部分传感器ROM搜索中止关中断时间过长查延时函数读温度全为85℃上电后未等待转换完成转换指令后等足时间85℃这个现象特别说一下这是单总线传感器的上电复位默认值。如果你读到85℃且所有点都一样说明程序在温度转换还没完成时就去读暂存器了读到了初始化后的原始数据。解决办法就是等足转换时间再读别省这几百毫秒。5.2 温度读数乱跳或明显不合理读数和实际温度差好几度或者数值一直在跳这个问题的根源多半不在传感器本身而在电源和安装。供电不稳是最常见的元凶。传感器是数字器件对电源质量仍然敏感供电电压纹波太大会导致内部ADC参考电压抖动读数自然不准。我的对策是所有传感器的VDD和GND在远端统一并联一个100nF电容这个电容不能放在DQ线上只能放在电源引脚上。其次传感器不要和继电器、接触器共用一个电源回路MCU用一路隔离电源总线传感器用另一路中间用DC-DC隔离或者至少用地线分开走。安装位置也是一个大坑。传感器直接贴在金属风管壁上温度反映的是管壁温度而不是空气温度和真实空气温度差好几度。正确的做法是让传感器探头伸进风管内约10到20cm悬在气流中不要碰管壁。室外测点要加防辐射罩避免阳光直射导致读数偏高。空调传感器、水管温度计其实都有类似问题安装方式对测量精度的影响常常比传感器本身的精度误差还大。软件上如果确认硬件没问题滤波参数也要重新审视。中值滤波的窗口取5次的话如果总线上有传感器连续两次读取失败重试期间插入了旧值会导致转折处的毛刺这种情况下改成时间序列判断更合理如果新值比上一次值高出超过8℃且持续不到两个采样周期直接判定为无效数据丢弃。5.3 以太网连接不上或频繁断开TCP连接不上的排查我的顺序是先物理层再网络层最后应用层。物理层的第一步是读PHY的寄存器。F107初始化后如果能正确读出PHY ID和链接状态寄存器说明RMII接口和时钟没问题。如果PHY寄存器读出来全是0xFF物理层就没通重点检查RMII时钟和PHY地址配置。第二步看RJ45指示灯通常Link灯亮代表物理链路已经协商成功。网络层就是ping。如果PC能ping通板子的IP但TCP连不上多半是TCP Server没有正常启动或者监听端口不对。应用层问题则集中在LwIP的tcp_tmr没调用、accept回调里没调用tcp_recv、接收缓存区太小导致数据丢失这几个地方。还有个细节上位机的TCP连接在数据读取后要主动调用recv清空数据否则服务端pcb的接收窗口会慢慢填满连接看起来是通的但数据发不出去。这个问题在长连接、高频读取的场景下特别容易出现。现象可能原因处理办法PHY寄存器读不到RMII时钟未配置检查50MHz时钟源能ping通但连不上TCP端口被防火墙拦截检查PC防火墙或换端口TCP连上后收不到数据recv回调未注册注册tcp_recv并处理pbuf连接频繁断开LwIP定时器未驱动主循环调用tcp_tmr上报数据字节错位帧格式解析错误用调试助手逐字节核对5.4 远程总线长线部署的专项问题远程总线用于HVAC现场时最大的敌人是两个线缆压降和电磁干扰。线缆压降影响的是传感器供电。远程传感器到主控板的距离超过30米时如果VDD线径太细传感器转换期间的大电流会在导线上产生明显压降导致传感器供电电压低于最低工作电压表现就是远程节点间歇性丢失。解决方法是加大供电线径或者直接采用24V供电再在每个传感器附近用LDO降到3.3V。第二个方案在工业现场更常见因为24V是标配而且压降远小于3.3V供电场景。电磁干扰对单总线的影响主要是上升沿被拉缓或者被毛刺打断。应对方法是总线使用屏蔽双绞线屏蔽层单端接地如果干扰非常大可以在总线末端加一个约100Ω的阻尼电阻到地这能在不破坏时序的前提下抑制振铃。我在一个变频器功率很大的试验间里试过加阻尼电阻后CRC错误率显著下降。最后是节点数限制。单总线的理论挂载数量上限有几十个但实际长线部署时每增加一个节点总线上寄生电容就大一点时序裕量就少一点可靠性会逐步下降。一般建议每条总线控制在8到10个以内确实有更多测点就分两路总线。不要贪多出问题时排查成本比多挂几个传感器高得多。结尾这套本地加远程温度监测方案我在实际项目里用了很长时间过程中最大的感悟是温度采集本身不复杂复杂的反而是总线的物理层处理和现场的干扰防护。如果你只是把一堆传感器接上然后读数据嵌入式本身就能跑通但要把这些数据稳定地用在HVAC控制上就得把上拉电阻、屏蔽布线、供电隔离这些基础细节做扎实这些功夫不显眼却是整套系统可靠性的真正保障。最后再分享一个小技巧如果你也遇到温度读数在某个时刻统一跳变的问题别急着怀疑传感器先看看是不是主控板上的ADC那条高精度参考电压被电磁干扰拉偏了或者看看传感器电源上是不是有间歇性的高电平毛刺。我后来在总线传感器供电线上加了一个共模电感然后再也没出现过这个现象。希望这篇笔记能帮你少踩几个坑省下的调试时间拿去喝茶都是好的。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑