ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

以太网采集单元设计实战:从硬件选型到协议栈移植全解析

以太网采集单元设计实战:从硬件选型到协议栈移植全解析 1. 为什么要把采集单元从串口搬到以太网做工业现场采集的老工程师应该都有过这种体会早期项目里RS485加Modbus RTU几乎是无敌的组合成本低、稳定、开发快。但最近几年越来越多的项目开始点名要以太网采集单元而且不是那种可有可无的升级要求而是直接把网络接口写进招标技术规格书里。我去年接的一个产线能耗监测项目就是典型。现场有62个采集点包括温度、电流、电压、开关状态原来用的是三路RS485总线轮询每路挂20多个节点。初期点位少的时候还能跑等到点位加满之后一个完整轮询周期已经拖到了8秒以上上位机画面上的数据肉眼可见地在跳秒。更要命的是偶尔一个节点掉线整条总线的诊断要靠人去现场一台台看状态灯运维成本和体验都非常糟糕。甲方提了两个硬性要求一是全通道刷新周期压到1秒以内二是设备数据要直接能进厂里的数据中台不再经过串口服务器转接。这两个需求叠加基本就锁定了方案形态——采集单元直接带以太网口。很多人觉得以太网采集单元无非是把串口换成网口底层逻辑不变。实际上这个迁移牵扯的东西比想象中多硬件上要重新选MCU和PHY协议栈要选型移植采集数据和网络传输之间要做合理的缓冲设计再加上一整套应用层协议。本文把这个方案拆开来讲按我实际做项目的路线从需求分析、硬件选型、协议栈移植到数据帧设计和问题排查完整过一遍。适合正在做或者准备做工业采集、环境监测、实验室台架数据采集的朋友参考。1.1 一个真实需求场景的指标拆解还是以上面那个产线能耗监测项目为例。我们在项目初期把需求拆成了下面这张表这一步非常关键因为后面所有硬件选型和软件设计都是围绕这些指标展开的。指标项需求值备注模拟量输入16路差分支持0~10V和4~20mA软件可切数字量输入8路干接点带光耦隔离采样率1kSPS/通道每通道独立采样全通道刷新周期≤500ms从上位机视角看的更新周期通信接口100Base-TX百兆以太网RJ45应用协议Modbus TCP 自定义UDP兼容现有PLC和自研中台供电24V DC工业现场标准电源功耗≤5W连续运行温升可控指标定下来之后方案的大方向就清楚了MCU内置以太网MAC加外置PHY芯片跑轻量级TCP/IP协议栈模拟量采集走定时器触发ADC加DMA搬运。这套组合在工业采集单元里非常成熟开发风险低供应链也稳定。1.2 为什么轮询周期和节点规模决定了方案形态顺带说一个很多人容易忽略的点。串口采集升级到以太网采集并不仅仅是快一点而是通信模型的根本变化。RS485总线上所有节点共享一条物理链路同一时刻只能有一个节点发言所以节点越多轮询周期线性增长这是物理层决定的软件优化空间很小。以太网这边就不一样了。虽然百兆以太网理论带宽12.5MB/s而工业采集单元的实际数据量往往很小——16路1kSPS的16位采样数据也就32KB/s加上协议开销也远小于带宽上限。但关键在于单条网线连接的是采集中枢比如交换机和上位机而不是一条共享总线上一长串节点。你可以把以太网采集单元理解成一个自带接驳口的独立设备任意两个节点之间通信互不占用彼此的通道拓扑灵活度完全不同。当然咯以太网也不是没有代价。物理层从RS485的差分两线变成了变压器加RJ45PCB设计门槛高了一截协议栈从Modbus RTU的简单状态机变成了TCP/IP栈对MCU资源的消耗也上了一个量级。这也就是为什么本文要花大量篇幅讲协议栈选型和数据链路设计。2. 硬件方案选型MCU、PHY与网络变压器的搭配逻辑硬件选型是大方向定完之后的第一关也是最容易被细节绊倒的一关。我见过不少朋友一上来就画板子结果PHY芯片的时钟方式和MCU不匹配、RMII引脚复用冲突、变压器参数选错导致link up都不稳定最后全部推倒重来。这一节把几条关键选择链路讲透。2.1 MCU选型为什么ST家在采集单元里最常见工业采集单元对MCU的核心要求是带以太网MAC、有足够DMA通道、ADC精度够且触发方式灵活、成本适中。目前市面上满足这些条件的方案里ST的STM32系列是绝对主流尤其是F4、F7和H7三个家族。具体到型号选择我的经验是分三档STM32F407系列百兆以太网MAC标配168MHz主频内置12位ADC价格便宜资料最多。适合采样率要求不高1kSPS量级、协议栈负载不重的中低端采集单元。STM32F429/F767系列主频更高180~216MHz有图形加速器和更大的RAM适合需要本地显示或有更复杂协议处理的设备。F767有硬件双精度浮点做边缘计算类的预处理很方便。STM32H743系列主频480MHzRAM近1MB以太网MAC集成了DMA描述符增强功能性能余量很大。但成本和PCB要求也上去了一般高速多通道同步采集才会用到。做个简单对比表格型号主频RAM以太网MAC典型定位STM32F407168MHz192KB10/100M基础型采集单元STM32F767216MHz512KB10/100M带显示/复杂协议STM32H743480MHz1MB10/100M多通道高速采集我那个产线能耗项目选的是STM32F407ZET616路模拟量加8路数字量1kSPS采样Modbus TCP和UDP双协议栈同时跑CPU负载实测大概45%RAM占用稳定在60KB以内余量充足。2.2 PHY芯片选型与RMII接口的底层原因MCU确定的下一步就是选PHY芯片。STM32内置的MAC只负责数据链路层的逻辑部分物理层的编码、电平转换、载波监听都要靠外挂PHY芯片完成。PHY选型时主要关注三件事接口模式、时钟方案、PHY地址。接口模式上MII接口需要14根信号线数据线16位引脚占用太大在采集单元这种对PCB面积敏感的设备上一般不划算。RMII接口只要7根信号线TXD[1:0]、RXD[1:0]、TX_EN、CLK、CRS_DV引脚少了一大半代价是对时钟要求更严格——RMII必须提供一个50MHz的参考时钟。这个50MHz时钟的来源有三种做法板载晶振、MCU的MCO引脚输出、专用时钟芯片。第一个方案最省心PHY自己带晶振电路第二个方案可以省一个晶振但要注意MCO输出时钟的稳定度和相位噪声STM32F407的MCO1配置成PLL时钟输出50MHz是成熟做法。实际设计中我倾向于独立晶振方案软件配置少调试时也少一个变量。常用PHY芯片我列一下选型参考PHY型号接口自动协商工作温度备注LAN8720ARMII支持0~85℃性价比高量大KSZ8081RMII/MII支持-40~105℃工业级温度范围DP83848RMII/MII支持-40~85℃TI老牌稳定PHY芯片的地址通过引脚电平设定比如LAN8720A的PHYAD0引脚拉低是地址0x00拉高是地址0x01。驱动代码里的PHY地址必须和板卡上的硬件设置一致否则MDIO通信直接失败。这个问题在批量生产时尤其要小心换PCB版本后如果改过地址引脚固件里忘了同步就会出现同一套代码在这个板子上能跑在另一个板子上link不起来的诡异现象。2.3 网络变压器与RJ45的细节处理很多初学者容易忽略网络变压器的作用以为它就是走个隔离。实际上变压器承担了三个功能隔离直流分量、抑制共模干扰、完成阻抗匹配。选择集成变压器的RJ45插座还是分离式变压器取决于空间和成本。集成方案比如HR911105A这类带变压器的RJ45布线简单、占板面积小适合做小型采集节点分离方案则方便灵活调整变压器参数维修时也容易单点替换。无论哪种方案都建议选带中心抽头且内置共模电感的型号抗静电和抗浪涌能力会好很多。PCB布局上差分走线TX_P/TX_N、RX_P/RX_N要成对等长距离尽量短旁边不要走高速数字信号线RJ45附近的PCB开槽隔离是常见做法目的是减少变压器耦合同模信号。另外PHY芯片的电源滤波要单独处理用磁珠加去耦电容的组合避免电源噪声串入模拟采集电路。3. 协议栈的选型与移植裸机lwIP还是RTOS加lwIP硬件平台确定之后软件架构就成了项目的核心决策点。以太网采集单元和普通MCU项目的最大区别在于要跑TCP/IP协议栈而协议栈的选型和配置直接决定了系统稳定性、实时性以及后续可维护性。3.1 不同软件方案的真实差别市面上主流的方案大致有四种裸机循环加lwIP轮询只有一个主循环协议栈在循环里被周期调用。优点是无操作系统代码简单调试直观缺点是无法真正并行处理多个任务当采集、存储、网络传输交织时延时控制容易失衡。FreeRTOS加lwIP最常用的组合。网络协议栈运行在单独任务里采集在高优先级任务或中断里完成通过队列和信号量让数据在任务间传递。优点是任务隔离清晰稳定性好缺点是首次上手有一定学习曲线需要理解RTOS的调度机制。RT-Thread加lwIPRT-Thread把lwIP适配做得很完善标准版系统自带完整ETH驱动框架和lwIP组件开发效率很高生态里也有大量现成设备驱动。商用或者芯片原厂封装的协议栈比如一些MCU厂商提供的闭源协议栈胜在省心但可定制性差出了问题排查困难。针对以太网采集单元这个具体场景我个人的建议是如果产品功能简单数据量不大而且你对RTOS不太熟悉可以先裸机跑lwIP数据采集用定时器中断、网络处理用主循环轮询能把项目在最短时间内跑通。但如果计划长期迭代有多个功能模块要往上加那建议直接上FreeRTOS加lwIP后面做远程升级、日志管理、多连接接入都会方便很多。3.2 lwIP移植的几个关键配置项无论是裸机还是带OSlwIP的移植都绕不开lwipopts.h这个配置文件。这里把几个直接决定采集单元稳不稳定的配置项拿出来讲透。内存配置lwIP有两种内存机制一种是内存池memp提前分配固定大小的内存块速度快但灵活性差另一种是内存堆mem动态分配灵活但可能产生碎片。在lwipopts.h里PBUF_POOL_SIZE决定收发缓冲区池的数量TCP_SND_BUF和TCP_WND决定TCP发送窗口和接收窗口。采集单元的数据量一般不大但要求传输及时、稳定所以我通常把PBUF_POOL_SIZE调到16以上TCP_WND设置成8KB左右这样单个连接就能流畅传输。内存不足是lwIP下最常见的隐性故障源。数据量上来后如果内存池被耗尽协议栈会静默丢包表现就是上位机偶尔收到不完整数据或采集值跳变。排查时最有效的手段是把lwIP的LWIP_STATS功能打开统计各层的丢包数和内存不足次数基本能一眼定位。中断处理与轮询的取舍STM32以太网外设收到一帧数据后会产生ETH中断中断服务函数里只做收包标记真正的协议栈处理放到主循环或以太网任务里这是防止中断风暴的正确做法。3.3 移植完成后的基本验证移植完后不要急着写应用层先做基础联调。用一条网线把板子和电脑交换机连上分别在板子和PC上配置静态IP例如板子192.168.1.100、PC192.168.1.2。先ping通了再测简单TCP回环。这里给一个Linux下常用的网络自测指令组合适合验证链路有没有通# 查看网卡状态和IP配置 ifconfig eth0 # 查看网卡协商速率和链路状态 ethtool eth0 # 用ping初步验证连通性 ping 192.168.1.100 # 用iperf3测TCP吞吐量 iperf3 -s # 板子端如果支持的话跑服务端 iperf3 -c 192.168.1.100Linux下的以太网回环测试里拿一根网线把两台设备直连跳过交换机是最快捷的排障方式。曾经有客户反馈板子连交换机不通但连电脑直连能通最后发现是交换机端口VLAN配置的问题链路协商本身是OK的。这类问题如果一上来就抓包很容易被表象带偏。4. 采集数据处理与以太网帧设计数据链路层网络通了不等于业务数据没问题。以太网采集单元的核心难题在于采集侧是连续不断的实时数据流网络侧是分包的传输模型这两者之间如何高效、无损地衔接。这节讲采集链路和应用层协议的设计。4.1 采集链路定时器触发ADC加DMA搬运工业采集单元的ADC采样必须保持严格的时间一致性单纯依赖CPU周期转换是不可靠的因为CPU要处理网络中断转换时序会被打断。推荐的做法是用一个定时器产生PWM或更新事件作为ADC外部触发源ADC在每个周期完成一次转换并把结果通过DMA直接搬运到内存缓冲区。整个过程中CPU不参与数据处理只在DMA传输完成时收到一个中断信号标记这一批数据已经准备好了。具体到STM32F407的实现思路是配置TIM2产生更新事件连接到ADC1的触发输入端ADC1开启DMA循环模式DMA的目的地址是一个环形缓冲区。环形缓冲区做双缓冲设计——当DMA指针走到缓冲区的后半段时说明前半段数据是完整的可以打包发送反过来同理。这样采集和网络传输就解耦了采集不会因为网络拥堵而丢数据。数据量计算16路模拟量采样率1kSPS每个样本16位每秒产生32KB原始数据。加上12字节的应用层头部每秒约是32.5KB。100M以太网净荷带宽约11MB/s实际占用不到0.3%带宽完全不是瓶颈。这时候真正需要花心思的反而是时间戳打标——因为以太网传输有延迟和抖动如果上位机需要计算三相电的相位差或者分析波形时序每个数据包必须带上采集时刻的时间戳而不是上位机接收时刻。4.2 应用层协议设计与以太网帧格式以太网帧格式本身很固定前导码和帧起始定界符由PHY自动处理MAC层实际收发的帧结构是目的MAC地址6字节、源MAC地址6字节、类型/长度2字节、数据46到1500字节、帧校验序列4字节。MCU的MAC外设会自动填充MAC地址、计算CRC所以应用层代码看到的数据从目的MAC开始到数据结束。以下是经典以太网帧结构理解它有助于后续设计自己的应用层数据包- 前导码 7字节硬件处理 - 帧起始定界符 1字节硬件处理 - 目的MAC地址 6字节 - 源MAC地址 6字节 - 类型/长度 2字节 - 载荷数据 46~1500字节 - 帧校验序列 4字节硬件计算在上面的载荷数据里lwIP会再拆出IP头20字节、TCP/UDP头20或8字节。做应用层协议设计时真正留给业务数据的部分要扣掉这些开销来计算。以太网数据的传输模式上TCP和UDP的选择要结合采集单元的实际场景来权衡。Modbus TCP跑在TCP之上适合与PLC、组态软件对接因为TCP有重传和确认机制传输可靠。但TCP的确认机制也带来一个问题当采集端持续高速发送数据而接收端处理不及时的时候TCP窗口会被占满发送端被迫暂停这会引入较大的延迟波动。UDP则没有这种问题数据发出即走代价是丢包要靠应用层自己处理。对于实时性要求高的波形采集UDP加序列号是更务实的选择。4.3 帧序列号与协议设计细节自定义UDP协议时帧序列号是一个容易被忽视但极其重要的字段。TCP协议帧本身有序列号机制网络层可以自动重组乱序的数据包但UDP没有。一旦网络中存在跃点或者交换机缓存压力较大UDP包就可能乱序到达。客户端如果依赖到达顺序还原数据就会出现数据错位的隐蔽问题。解决办法是在应用层协议里显式加入序列号字段比如每秒发送一个新的周期计数每次发送一个静态自增序号。接收端在解析数据时检查序列号如果发现跳号就说明有数据包丢失可以做补发请求或者至少记录一条日志。以下是采集单元里常用的一种精简数据帧定义帧头2字节固定0xAA55 版本号1字节 消息类型1字节0x01表示采样数据0x02表示设备状态 数据长度2字节表示后续数据的字节数 序列号4字节自增 时间戳4字节秒级时间戳 通道状态位图2字节标记各通道的有效性 通道数据N * 2字节逐通道排列 CRC162字节对整个包做校验加上这么十几字节的头部对带宽的影响可以忽略但对排查问题、保证数据一致性帮助巨大。我做产线项目时上位机曾出现过某通道数值间歇性跳变。靠序列号比对发现是交换机在流量突增时丢了一个UDP包导致后续数据偏移了两个通道。加序列号和通道状态位图后这类问题两分钟就能定位。Modbus TCP协议本身是标准的大多数情况下直接用现成库就行。需要注意的细节是Modbus TCP的MBAP头里有协议标识符和单元标识符组态软件默认用0xFF作为单元标识符通配有些实现会严格要求匹配设备地址联调前要先确认清楚。5. 系统调通后的实测数据与问题排查系统开发接近尾声时测试和问题排查才是真正体现项目水平的地方。这一节把我自己实测中遇到的高频问题和排查链路完整过一遍很多方法属于常规文档里不写但现场救过命的级别。5.1 实测性能数据在百兆网络中测试用的以太网采集单元最终实测数据如下全通道采集刷新周期大约120ms远优于需求里的500ms网络吞吐量持续发送自定义UDP包时约2.4Mbps完全满足32KB/s的数据量需求丢包率在无拥塞的千兆交换机环境下连续运行72小时总丢包率为0CPU占用率STM32F407168MHz双协议栈加采集任务大约45%功耗24V输入整板功耗约3.8W抓包验证是肯定要做的。Wireshark挂在PC端抓板子发出的UDP帧检查帧序列号是否连续、时间戳是否单调递增、CRC校验是否全部正确。实际抓包发现过一个问题DMA双缓冲切换后由于中断处理时另一个缓冲区还在写入导致一帧数据里可能出现半个旧周期和半个新周期的拼接。之后在协议头里加了一个批次号字段这个问题才彻底暴露出来并在驱动层做了同步修正。5.2 常见问题的完整排查链路问题一板子上电后link up不上链路层的故障排查顺序非常固定我的经验是先看PHY状态寄存器再看中断最后看DMA配置。# 通过MDIO读取PHY状态寄存器基本寄存器1是状态寄存器 # PHY地址为0寄存器1的bit2是link status为1表示链路已建立具体做法是写一个小函数循环读取PHY寄存器把值通过串口打印出来。如果在插入网线后link status始终是0问题基本集中在硬件变压器、RJ45、差分线、PHY供电如果link status能变成1但数据不通再去查MAC的DMA描述符和lwIP的netif状态。问题二Windows系统弹出以太网没有有效IP配置这个现象在电脑直连采集单元时很常见根源是电脑设置了自动获取IP地址而采集单元往往只配置了静态IP没有DHCP服务。解决办法有两种一是把电脑网卡改成静态IP例如192.168.1.2子网掩码255.255.255.0网关留空二是在采集单元里实现一个简单的DHCP服务端自动给电脑分配同网段IP。前者适合调试后者适合产品化交付。问题三TCP连接时断时续间隔数分钟一次排查这种问题不能只盯应用层。先把lwIP的LWIP_STATS打开统计TCP重传次数。如果重传次数高同时伴随PBUF内存池不足基本可以确定是内存耗尽导致的。此时增加PBUF_POOL_SIZE和TCP_SND_QUEUELEN问题通常会缓解。另一种可能是网卡驱动的DMA描述符数量和缓冲长度不匹配导致大帧被截断这种情况抓包会看到大量TCP校验和错误。问题四以太网TC8测试规范与协议一致性TC8是汽车电子领域以太网ECU的测试规范别以为它只适用于车载以太网。TC8定义了从物理层一致性测试到协议层一致性测试的完整方法论工业以太网采集单元完全可以参考它的思路来设计测试用例比如中断唤醒测试、帧格式异常测试、高流量压力测试。虽然我们不必完整跑TC8的用例矩阵但它的分层测试思想——先物理层后MAC层再TCP/IP层最后应用层——和实际排障的思路完全一致。合理借鉴TC8的方法论能让采集单元在各种网络环境下的表现更可预期。5.3 几个藏得比较深的坑踩过的坑里最值得说的是PHY地址配置错乱。量产后的某一批板子用了不同批次的PHY芯片有的默认地址是0x00有的是0x01而固件里写死了0x00结果一批板子在客户现场link不上。后来在软件里加了PHY地址自动扫描的逻辑上电后依次尝试0x00到0x03的地址直到MDIO读取状态寄存器成功从此一劳永逸。第二个坑是RMII参考时钟的相位要求。部分PHY芯片要求MCU提供的50MHz时钟和PHY内置的时钟域有一定相位关系如果你的板子在低温和常温下表现不一致优先检查时钟源和RMII走线的等长处理。这个坑在批量应用前尤其要重点做高低温测试。第三个坑更隐蔽TCP连接在长时间空闲后无法唤醒。原因是TCP的保活机制默认关闭中间设备比如路由器在长时间没有流量时会把连接老化掉。解决方案是开启lwIP的LWIP_TCP_KEEPALIVE并配置合理的保活探测间隔同时在应用层增加心跳机制每5秒或10秒发一次心跳包成本几乎为零但能省掉大量现场运维工单。6. 最后再分享一点实战心得以太网采集单元相比传统串口采集多出来的工作量和难度主要在网络这一侧。硬件上要处理好PHY、变压器、差分走线这些之前完全不涉及的东西软件上要从裸机状态机思维切换到协议栈思维。但反过来看一旦把以太网链路跑稳了后面的扩展空间会大得多——远程升级、多机同步采集、边缘计算、云平台直连都是顺理成章的事。根据我个人的经验给正在做类似项目的朋友几句真心话第一需求里的刷新周期和通道数量一定要先量化工程上最怕大概就行这些数字直接决定MCU选型和协议栈配置第二现场部署时不要图省事用默认IP段尽量在设备里做拨码开关或者Web配置界面可管理性在产品交付后比你想的重要得多第三数据帧里的序列号和CRC千万别省这是以后排查问题的底气。做到这几条你的以太网采集单元跑上几年都不会出大乱子。
返回列表