ARTICLE DETAIL

资讯详情

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

STM32以太网ETH外设从原理到实战:硬件设计、CubeMX配置与lwIP调试指南

STM32以太网ETH外设从原理到实战:硬件设计、CubeMX配置与lwIP调试指南 做嵌入式这些年我接过的项目里十有八九会碰到“给设备加个网口”的需求。客户一句“直接连路由器不就行了”背后其实藏着一整套东西MAC、PHY、协议栈、DMA、中断哪一个环节没处理好设备就连不上网。STM32以太网外设ETH是很多朋友入门嵌入式联网的第一站STM32内部集成了一个带DMA的以太网MAC控制器配上一颗外部PHY芯片就能让单片机接入标准的以太网络。这篇文章我打算把STM32 ETH从硬件到软件、从原理到实操完整拆一遍重点讲讲CubeMX怎么配置ETH和lwIP、PHY芯片怎么选、调试的时候那些坑怎么绕过去。适合正准备用STM32做联网设备、做工业采集器、做毕业设计的同学参考纯新手也能按步骤跑通。1. 先把STM32的ETH外设看明白它是MAC不是网口1.1 以太网外设在芯片内部到底干了什么STM32的ETH外设准确说是一个符合IEEE 802.3协议的以太网MAC控制器。它负责的事情可以理解成“快递分拣中心”网络数据从网口进来MAC负责把帧头解析出来、校验数据完整性、然后交给DMA直接存储器访问搬到内存里发送的时候反过来DMA把内存里的数据搬到MACMAC加上帧头帧尾和CRC校验再通过MII或RMII接口送给外面的PHY芯片。这里有个关键点要搞清楚ETH外设不负责电信号处理也不负责把数据变成网线上的差分信号。这些脏活累活是PHY芯片干的它会把MAC传来的并行数据编码成适合双绞线传输的物理信号同时处理载波侦听、冲突检测这些底层机制。STM32内部集成的SMI接口MDIO/MDC专门用来配置PHY芯片的内部寄存器比如查链路是否通、协商速率和双工模式。所以你在芯片手册里会看到ETH这个外设有三部分MAC核心、DMA控制器、SMI管理接口。DMA让CPU在收发数据时基本不用参与SMI让单片机可以“指挥”外部PHY。理解了这个架构后面配置的时候你就知道每个选项是干什么的了。1.2 哪些STM32带ETH哪些只是“看起来很接近”不是所有STM32都带ETH外设很多朋友在选型时踩过这个坑。整体来说F1、F0、L0、L4这些系列基本都没有以太网MAC你要用它们做联网只能外挂SPI接口的W5500或者串口转以太网模块。而F407、F429、F767、H743这些中高端型号内部才集成了ETH外设。即便带ETH的型号细节上也有差异。F407和F429的ETH是同一代设计支持MII和RMII两种接口速率最高100Mbps。F7和H7系列在DMA和缓存一致性上做了改进ETH的收发描述符管理更复杂尤其H7有Cache问题需要额外处理。选型建议很直接如果只是做简单的数据采集上传F407完全够用如果追求性能、打算跑复杂协议甚至做网关直接上H7。还有一个容易忽略的点ETH需要一定数量的引脚F407用RMII接口大约是9个引脚用MII接口要16个引脚以上加上PHY芯片PCB面积和走线难度都要考虑进去。别选完型发现引脚冲突或者布线太痛苦那就被动了。1.3 它与“SPI转以太网”方案的本质区别市面上很火的W5500这类芯片内部是MACPHY合封在一起的MCU通过SPI口读写它对单片机来说它更像一个“外部外设”协议栈也固化在芯片内部。而STM32的ETH只是一个MACPHY在外面协议栈比如lwIP跑在MCU自己身上。这两种方案没有绝对的谁好谁坏区别主要看场景。W5500方案开发快、MCU负载低但成本高、带宽有限SPI瓶颈而且难以应对大流量和复杂协议。STM32 ETH方案的成本低H7这类芯片跑满100Mbps完全没问题灵活性也高协议栈随便改功能扩展空间大。代价就是开发难度高你要稍微懂一点PHY的原理还要会调协议栈参数。我自己给客户的建议是如果只是采集几个传感器数据上传到PLCW5500省事如果要做网关、做视频传输、做较大流量的边缘计算设备老老实实选STM32 ETH方案后面扩展不会想哭。2. 硬件电路设计与PHY选型一半的调试错误都出在这里2.1 RMII还是MII选型背后的信号与时序逻辑STM32的ETH外设支持MII和RMII两种与PHY连接的接口标准。MII是标准接口16根信号线速率10/100Mbps自适应RMII是简化版只要7根信号线但参考时钟从25MHz提到了50MHz数据线从4位降到了2位。很多新手会觉得“信号线越少越好”直接选了RMII这个方向没错但要注意RMII对时钟的要求更严格。RMII模式下MAC和PHY必须使用同一个50MHz参考时钟不管是MAC提供还是PHY提供两侧的时钟必须同步否则收发时序会乱。MII的时钟则分别由PHY提供发送和接收各自独立虽然信号多但时序容错更强。实话说在100Mbps的速度下RMII是完全够用的而且能省一半引脚。PCB布线也更轻松我建议大多数项目直接用RMII。更关键的是现在市面上大多数低成本PHY芯片比如LAN8720A主打的就是RMII模式资料和参考设计一抓一大把。MII模式更适合那些对时序有特殊要求或者想兼容其他MAC的场景一般项目用不上。这里给个信号对照表方便画原理图的时候核对功能MIIRMII发送数据TXD[3:0] 4位TXD[1:0] 2位发送时钟TX_CLK25MHz/2.5MHz共用REF_CLK50MHz接收数据RXD[3:0] 4位RXD[1:0] 2位接收时钟RX_CLK共用REF_CLK控制信号TX_EN、RX_DV、CRS、COLTX_EN、CRS_DV管理接口MDC、MDIOMDC、MDIO2.2 PHY芯片怎么选地址、时钟、LED这些“配置引脚”别想当然PHY芯片是你的设备能不能上网的第一道关口选型时除了看速率和接口更要关注那些“悄悄起作用”的配置引脚。我常用的是LAN8720A、DP83848和KSZ8081这三款它们的共同点是都支持RMII价格也不贵。不同点在于内部寄存器的默认值、复位时序、参考时钟产生方式各有差异。先说PHY地址。STM32通过SMI接口MDIO/MDC访问PHY芯片而总线上每个PHY芯片必须有一个唯一的地址。这个地址不是软件里随便写的而是由PHY芯片的PHYAD引脚在上电时的电平状态决定。LAN8720A的PHYAD0引脚内部有下拉默认地址是0DP83848有一组PHYAD[4:0]引脚默认值要看板子上的上下拉电阻配置。我见过太多人把CubeMX里的PHY Address填错了导致PHY初始化的寄存器读出来全是0xFFFF网口灯都不亮。所以画原理图的时候一定要确认PHYAD引脚接法然后按手册算出实际地址再填到CubeMX里。再说时钟。RMII模式需要50MHz参考时钟这个时钟的来源有三种常见做法一是把50MHz有源晶振直接接到PHY的REF_CLK引脚二是用25MHz晶振接到PHY由PHY内部倍频后把50MHz输出给MCU三是从STM32的MCO引脚输出50MHz给PHY。具体用哪种要配合PHY芯片的参考设计来定LAN8720A常用第二种DP83848常用第一种或第三种。时钟接错了现象很典型PHY能读到ID但Link状态永远起不来。2.3 硬件布线上的经验与常见坑硬件上的坑比软件难查得多我吃过不少亏把最容易出问题的几个点列一下网络变压器的接法不能省。STM32的ETH接口与外接RJ45座子之间必须接网络隔离变压器。现在很多RJ45座子自带变压器选型时要注意区分。变压器的作用是隔离电平、抑制共模干扰省掉它的后果是通信不稳定丢包严重而且静电防护一塌糊涂。差分信号线要尽量等长、阻抗匹配。RMII虽然数据线是单端信号但PHY到RJ45之间网口的TX±和RX±差分线要控制100欧姆差分阻抗走线尽量短不要打过孔不要在中间跨分割。要是布线实在没办法保证至少也要保证TX±和RX±各自等长。PHY芯片的复位电路要靠谱。很多PHY芯片要求复位信号至少有几百微秒的低电平时间而且上电后要等时钟稳定再释放复位。如果只是简单接个RC复位很容易出现PHY芯片“半醒不醒”的状态表现为MDIO能读到寄存器但Link状态灯死活不亮或者隔一段时间就死掉。建议用MCU的一个GPIO来控制PHY复位软件里严格按时序操作。LED指示灯的限流电阻别省。PHY的Link/Activity指示灯引脚通常需要外部限流电阻有些精简电路直接把它挂到3.3V结果就是指示灯常亮不灭或者根本不亮干扰我们排查问题。3. CubeMX配置ETH lwIP从建工程到跑通TCP回环3.1 建工程前的准备工作用CubeMX配置ETH之前有几件事先确认好不然生成的代码会花很多时间收拾。确认选型。打开CubeMX的MCU选择器在搜索框里输入你手里的芯片型号然后看它的Peripherals列表里有没有ETH。没有ETH的芯片后面步骤直接免谈。确认引脚冲突。ETH用的是GPIO复用功能RMII模式下至少要占用PA1、PA2、PA7、PC4、PC5等引脚这些引脚常常和SDIO、USART、定时器等功能复用。我的建议是先把原理图里ETH相关引脚固定下来再排其他外设让CubeMX的引脚冲突检查和自动分配帮你规避问题。我试过好几次让CubeMX自己分配引脚结果它把ETH引脚和调试串口的引脚挤在了一起最后只能重新画板子很被动。准备一个固定的MAC地址。虽然MAC地址可以写成任何不冲突的值但严谨的产品要申请企业唯一的MAC段开发阶段随便填一个也不会影响功能。比如我常用02:00:11:22:33:44这类本地管理地址这种地址第二位是02属于本地管理地址范围不会和公网设备冲突。3.2 一步一步配置ETH与lwIPCubeMX里的操作流程我一步步拆开讲。第一步打开ETH外设。在Pinout Configuration界面找到Connectivity展开ETH勾选Activate。这时候会出现MII和RMII的选择按你硬件设计选。RMII模式下还需要在ETH配置里把PHY Address填成你PHY芯片对应的地址。LAN8720A默认0那就填0。第二步设置RMII参考时钟。在ETH配置的Parameter Settings里有个PHY Clock选择。这里选哪一项取决于你的时钟方案。如果你用MCO输出50MHz给PHY需要先去RCC配置里打开MCO2选择50MHz输出如果你用外部晶振给PHY、由PHY输出时钟给MCU那软件里不需要额外配置但要在原理图上把这个时钟方向画对。第三步配置MAC地址和DMA描述符。ETH配置界面里会有MAC Address、DMA Descriptor Count这些选项。MAC地址填你定好的值描述符数量我一般设为4到8个。描述符数量影响收发缓冲的深度数量太少容易在突发数据时丢帧数量太多会占用RAM。128KB RAM以上的芯片建议直接给8个接收描述符和8个发送描述符性能更好。第四步添加lwIP。在Middleware组里双击LWIP勾选Activate。这里有几个关键的参数要设置IP Address、Netmask、Gateway调试阶段建议先用静态IP比如192.168.1.10、255.255.255.0、192.168.1.1。开启DHCP反而容易因为网络环境问题干扰判断。Memory settingslwIP会根据你设定的内存池大小分配RAM默认值在内存小的芯片上可能偏大要根据芯片RAM容量调整。Protocol默认启用TCP和UDP。如果只是做TCP通信可以去掉UDP还能省一点内存。TCP开启TCP设置好TCP_MSS最大报文段长度和TCP_WND接收窗口。这两个参数直接决定吞吐率我建议TCP_MSS设为1460以太网最大报文1500字节减去IP头20字节再减去TCP头20字节TCP_WND设为4个MSS左右也就是5840到8192字节之间。配置完成后点击Project菜单选择Generate Code生成的代码里会自动包含ETH和lwIP的初始化函数。这里有个细节生成的main函数里会调用MX_LWIP_Init()它会完成所有协议栈初始化你不需要自己再另外初始化。3.3 代码验证先Ping通再跑TCP Server生成完代码编译下载到板子第一步先做链路测试。用网线把开发板直接连到电脑网口把电脑的网卡IP设成和开发板同一网段比如192.168.1.2然后从电脑上ping开发板的IP。能ping通说明MAC、PHY、lwIP基本都正常了。ping通之后就可以试着跑TCP通信了。我用lwIP的netconn API写一个最简单的TCP回环服务器把收到的数据原样返回。核心代码大致这样#include lwip/netconn.h void tcp_echo_server(void) { struct netconn *conn, *newconn; struct netbuf *buf; err_t err; conn netconn_new(NETCONN_TCP); if (conn NULL) { return; } err netconn_bind(conn, IP_ADDR_ANY, 8080); if (err ! ERR_OK) { netconn_delete(conn); return; } err netconn_listen(conn); if (err ! ERR_OK) { netconn_delete(conn); return; } while (1) { err netconn_accept(conn, newconn); if (err ! ERR_OK) { continue; } while (netconn_recv(newconn, buf) ERR_OK) { netconn_write(newconn, buf-payload, buf-len, NETCONN_COPY); netbuf_delete(buf); } netconn_close(newconn); netconn_delete(newconn); } }这个代码放在lwIP启动之后循环执行就行。需要注意的是netconn API在调用accept和recv时会阻塞当前线程所以最好把TCP服务器逻辑放到一个独立的RTOS任务里或者用lwIP自带的tcpip_thread上下文中运行。我最早是直接在main的主循环里死等netconn_accept结果发现整个系统都卡住了后来才意识到问题在于netconn API会阻塞不适合放在主循环里裸奔。3.4 给新手的建议先用官方板或开发板起步我见过太多人拿着自己画的板子第一次通电就出问题然后调了一整天也不知道是硬件问题还是软件问题。新手起步强烈建议先买一块现成的开发板比如正点原子、野火那些带网口的高性能STM32开发板最便宜的带LAN8720A的也就一两百块。先用开发板把软件流程跑通确认你对ETH和lwIP的理解是对的再回过头来折腾自己的板子。如果一定要直接做自己的板子第一版回来之后先别急着下载程序。第一步先量PHY芯片的供电、复位波形、时钟波形确认这几个基本条件正常了再写软件。至少先写一个小程序通过SMI接口读取PHY芯片的ID寄存器如果读出来的值和数据手册对不上说明硬件有问题或者PHY地址配置错误这时候就不要继续往下调了。4. 常见问题与排查技巧实录4.1 Link Up了但Ping不通从ARP查起这是最常遇到的问题PHY的Link灯已经亮起来了说明物理层已经协商成功但电脑Ping开发板就是不通。排查顺序按我的经验这样来第一步用wireshark抓包。抓包工具能看到物理网卡上所有接收和发送的报文这是定位网络问题最重要的工具。具体做法是电脑连着开发板在电脑的网卡上抓包。如果电脑持续发出ARP请求询问“192.168.1.10的MAC地址是多少”而开发板没有任何回复说明问题出在开发板接收路径或者协议栈回复逻辑上。第二步检查PHY的中断和轮询状态。lwIP通过一个ethernetif_input线程不断轮询PHY当ETH_DMA收到数据后会触发中断或者被轮询线程读取。如果你的工程里没有正确使能ETH中断或者轮询线程没有运行数据就会一直堆在DMA描述符里ARP请求自然没有回复。第三步查看MAC地址过滤。STM32的ETH外设有接收地址过滤功能如果你的MAC地址配置错了或者过滤器设置得过严MAC层会把发往本机的帧直接丢弃。调试时可以把过滤配置放宽允许接收所有帧配置成Promiscuous模式确认协议栈能正常收到数据再说。4.2 初始化卡死在ETH或lwIPDMA描述符与内存对齐STM32的ETH DMA要求收发描述符和缓冲区必须按特定边界对齐。在F4上要求4字节对齐在F7和H7上由于有Cache的存在还涉及Cache一致性问题。如果初始化时程序跑飞或者卡在HardFault多半就是内存对齐或者Cache配置出了问题。F4系列比较简单CubeMX生成的代码会自动分配对齐的内存默认不用操心。但如果你自己移植代码、自己定义描述符数组就要确保数组的起始地址是按32字节对齐的STM32的DMA对描述符有对齐要求。F7和H7系列就要小心Cache了。我在H743上调以太网时遇到过一种诡异现象程序正常运行一段时间突然收发数据开始乱表现为Ping时断续TCP连接极不稳定。查了好久才发现是DMA写入内存后CPU读到的却是Cache里的旧数据因为DMA不经过CPU Cache。解决办法有两个一是把ETH的DMA描述符和缓冲区所在内存区域配置成Non-cacheable用MPU二是在每次收发完数据后手动做Cache clean和invalid操作。我刚接触H7时忽略了这个问题浪费了一整天。CubeMX的默认工程在H7上已经会配置MPU但如果你自己裁剪代码很容易就把这部分弄丢。4.3 吞吐率上不去、频繁丢包协议栈参数与双缓冲能ping通TCP也能连上但传大文件时速度很慢或者传输过程中丢包严重。这个问题要从两方面排查。先看DMA描述符的数量。接收描述符如果只有2个网络流量一大DMA还没处理完一个数据帧新的帧已经到了描述符队列就满了后面的帧会被硬件直接丢弃。解决办法是增大描述符数量我建议至少配置8个接收描述符。再看lwIP的内存池大小。lwIP内部使用pbuf管理报文缓冲区如果内存池太小协议栈处理不过来时会把数据包丢弃。TCP_MSS和TCP_WND这两个参数尤其重要。TCP_WND控制发送方在没有收到确认之前最多可以发送多少数据它太小会严重影响吞吐率。我建议TCP_WND至少是TCP_MSS的4倍如果内存充足可以更大。我调试过的一个项目默认TCP_WND是4KB传文件速度只有几百KB/s改成16KB后直接跑到了5MB/s以上。还可以打开lwIP的统计功能在lwipopts.h里把LWIP_STATS设为1然后通过串口打印协议栈的各项统计信息看看哪些数据包被丢弃了一目了然。这个功能在定版前的性能调优阶段特别有用最终产品里可以关掉以节省RAM。4.4 问题速查表以太网调试现场记录把这些年遇到的典型问题整理成一张表方便大家照着排查现象可能原因排查方法PHY Link灯不亮供电问题、差分线接反、网线质量问题、PHY地址错误测量PHY供电、检查TX±/RX±方向、读PHY ID寄存器Link灯亮但Ping不通MAC过滤、ARP未回复、IP地址冲突、中断未使能wireshark抓包、检查MAC地址、确认lwIP线程运行数据时通时断时钟不稳定、差分走线太长、PHY复位时序不对示波器看时钟波形、缩短走线、软件复位PHY初始化HardFault描述符未对齐、内存不足、PHY初始化失败检查地址对齐、增大RAM分配、打印PHY IDH7上数据错乱Cache一致性问题配置MPU为Non-cacheable、做Cache清理传输速度极低DMA描述符太少、TCP_WND太小、内存池不足增大描述符数量、调大TCP_WND、调整内存池串口打印乱码且网络不通MCU时钟配置错误检查系统时钟、确认是否稳定输出50MHz给PHY排查以太网问题最忌讳的就是瞎猜。很多人一看到Ping不通就怀疑是协议栈没配好把lwIP的配置改来改去结果发现其实是网线质量差或者PHY供电不干净。我的习惯是先物理层、后协议层从底层往上查。指示灯、示波器、wireshark这三个工具能解决90%的问题。最后再分享一个小技巧调试以太网功能之前先花十分钟把PHY芯片的数据手册和你的原理图对照看一遍确认PHY地址、时钟源、复位脚、LED指示脚的接法全部正确再开始写代码。很多人以为这类信息不重要结果恰恰是这些细节让整个调试过程变得痛苦万分。STM32的ETH外设一旦掌握了这套调试方法后续做车载以太网测试或者扩展更多网络协议的时候思路都会清晰很多你也有了自己的一套排查逻辑。
返回列表