资讯动态

STM32F429以太网底层实战:MAC与PHY接口、DMA描述符及LwIP对接

发布时间:2026/10/15 3:31:13 来源:尧图企业网站定制
1. 项目缘起与整体设计思路搞嵌入式网络通信的朋友大概率都经历过这样一个过程拿到一块带以太网外设的开发板兴冲冲地插上网线结果发现数据死活收发不了要么ping不通要么丢包严重要么跑一会儿就死机。我这次拿STM32F429IGT6做以太网通信的实践也是从这个阶段过来的。这块芯片自带MAC控制器外挂一颗PHY芯片就能实现完整的以太网通信链路配合LwIP这个轻量级TCP/IP协议栈能在资源受限的MCU上跑出相当稳定的网络功能。整个学习笔记系列我打算分几篇来写这一篇专门聊以太网底层的东西——从MAC到PHY的硬件接口、RMII模式下的引脚配置、DMA描述符的管理机制以及LwIP是怎么跟底层网卡驱动对接的。先说说为什么选STM32F429IGT6这颗芯片来做以太网通信。F429属于STM32F4系列里的高性能型号Cortex-M4内核跑180MHz自带FPU和DSP指令集SRAM有256KB其中112KB64KB64KB的分区Flash有1MB。最关键的是它内置了以太网MAC控制器支持10/100Mbps自适应符合IEEE 802.3标准。这意味着你不需要外挂MAC芯片只需要配一颗PHY就能搞定物理层。常见的搭配是LAN8720A或者DP83848前者便宜量又足RMII接口只要7根信号线后者工业级更稳但贵一些。我手头用的是LAN8720A的方案所以后面的配置都围绕这个组合来展开。整体设计思路是这样的STM32F429的ETH外设负责MAC层的数据帧组装和解析通过RMII接口跟外部PHY芯片通信PHY再通过网线跟对端设备交互。软件层面LwIP协议栈跑在MAC驱动之上提供TCP/UDP/IP等协议支持。应用层就可以直接用Socket API或者RAW API来收发数据。这个架构的好处是分工明确——硬件处理物理层和MAC层的高速数据流软件协议栈处理上层逻辑MCU的CPU只需要关注业务代码就行。为什么不用软件模拟以太网因为软件模拟的话CPU要不停轮询GPIO来收发曼彻斯特编码10Mbps都跑不满更别说100Mbps了。STM32F429的ETH外设自带DMA控制器能自动在内存和MAC之间搬运数据帧CPU只需要处理描述符和中断就行。这是硬件加速带来的性能优势也是为什么做嵌入式网络通信一定要用带MAC外设的芯片。再说说LwIP的选择。嵌入式领域常见的TCP/IP协议栈有LwIP、uIP、FreeRTOS-TCP等。LwIP的优势在于功能完整、内存占用可配置、社区活跃。它支持RAW API、NETCONN API和Socket API三种编程接口从裸机到RTOS都能适配。对于STM32F429这种资源相对充裕的芯片跑LwIP绰绰有余。而且ST官方提供了STM32CubeF4软件包里面直接包含了LwIP的移植代码和示例工程省去了大量底层适配工作。这一篇的重点放在以太网底层具体包括ETH外设的时钟配置、RMII引脚映射、PHY芯片的初始化和自协商、DMA描述符链的构建、数据收发流程、中断处理机制。这些内容搞清楚了后面跑LwIP就是水到渠成的事。如果你之前没接触过嵌入式网络建议先把这一篇的硬件部分吃透不然后面调LwIP的时候遇到问题会不知道从哪查起。2. 以太网硬件接口与PHY配置细节2.1 RMII接口的引脚连接与时钟方案STM32F429的ETH外设支持两种MAC-PHY接口MII和RMII。MII需要16根信号线RMII只需要7根REF_CLK、CRS_DV、RXD0、RXD1、TX_EN、TXD0、TXD1外加MDC和MDIO两根管理线。对于引脚资源紧张的方案RMII是首选。我这次用的就是RMII模式下面把引脚连接关系理清楚。先看数据线。RMII模式下接收方向有RXD0和RXD1两根线每个时钟周期传输2个bit所以需要50MHz的参考时钟才能达到100Mbps的速率。发送方向有TXD0和TXD1同样是每个时钟周期2个bit。CRS_DV是载波侦听和接收数据有效信号TX_EN是发送使能。这7根线加上MDC/MDIO总共9根线就能完成MAC和PHY之间的全部通信。参考时钟REF_CLK是RMII模式的关键。50MHz的时钟可以由STM32提供也可以由外部PHY提供。我选择的是由外部PHY的晶振经过内部PLL倍频后输出50MHz给STM32。具体来说LAN8720A外挂一颗25MHz晶振内部倍频到50MHz通过REF_CLK引脚输出给STM32的PA1引脚。这种方案的好处是STM32不需要额外配置MCO输出时钟省事。但要注意LAN8720A的REF_CLK输出使能需要通过寄存器配置默认状态下可能是不输出的需要在初始化代码里设置。引脚映射方面STM32F429的ETH外设引脚是固定的不能随意重映射。具体对应关系如下信号STM32引脚方向说明REF_CLKPA1输入50MHz参考时钟MDIOPA2双向管理数据输入输出MDCPC1输出管理时钟CRS_DVPA7输入载波侦听/接收数据有效RXD0PC4输入接收数据位0RXD1PC5输入接收数据位1TX_ENPB11输出发送使能TXD0PB12输出发送数据位0TXD1PB13输出发送数据位1这些引脚在配置时要注意几点PA1、PA2、PA7要配置为复用功能但不需要上下拉PC1、PC4、PC5配置为复用推挽输出或浮空输入PB11、PB12、PB13配置为复用推挽输出速度建议设为Very High。另外PA1作为REF_CLK输入时要确保时钟信号质量走线尽量短避免干扰。注意有些开发板把REF_CLK接到PA1有些接到PA8MCO输出。如果你的板子REF_CLK是PA8那说明是STM32输出时钟给PHY这时候需要配置RCC的MCO1输出50MHz。两种方案都行但配置代码不一样拿到板子第一件事就是确认原理图上的时钟走向。2.2 PHY芯片初始化与自协商流程PHY芯片的初始化是通过MDIO接口读写寄存器完成的。MDIO是类似I2C的串行接口MDC提供时钟最高2.5MHzMDIO传输数据。STM32的ETH外设自带MDIO控制器只需要配置好时钟分频就行。PHY的寄存器地址空间是5位共32个寄存器。标准寄存器0到15是IEEE 802.3定义的16到31是厂商自定义的。初始化流程一般是这样的先读PHYIDR1和PHYIDR2确认PHY型号然后配置BMCR基本模式控制寄存器启动自协商等待自协商完成最后读BMSR基本模式状态寄存器和PHYSRPHY特殊状态寄存器确认连接速度和双工模式。以LAN8720A为例关键寄存器操作如下// 读取PHY ID uint16_t phy_id1 ETH_ReadPHYRegister(PHY_ADDRESS, PHY_ID1_REG); uint16_t phy_id2 ETH_ReadPHYRegister(PHY_ADDRESS, PHY_ID2_REG); // LAN8720A的ID应该是0x0007和0xC0F1 // 启动自协商 ETH_WritePHYRegister(PHY_ADDRESS, PHY_BCR, PHY_AUTONEGOTIATION); // 等待自协商完成 do { uint16_t bmsr ETH_ReadPHYRegister(PHY_ADDRESS, PHY_BSR); if (bmsr PHY_AUTONEGO_COMPLETE) break; HAL_Delay(100); } while (timeout--); // 读取连接状态和速度 uint16_t phy_sr ETH_ReadPHYRegister(PHY_ADDRESS, PHY_SR); // LAN8720A的PHY_SR寄存器bit2是链接状态bit3是速度bit4是双工模式这里有个坑要注意LAN8720A的PHY地址由PHYAD0引脚决定接下拉电阻时地址是0接上拉时是1。如果你读不到PHY ID先检查这个引脚的电平。另外LAN8720A的PHY_SR寄存器地址31的位定义跟DP83848不一样移植代码时不能直接照搬。自协商完成后PHY会自动跟对端设备协商出最佳的速度和双工模式。100Mbps全双工是理想状态但如果网线质量差或者对端设备老旧可能协商成10Mbps半双工。这时候虽然能通信但性能会大打折扣。我遇到过一根劣质网线导致协商成10Mbps的情况换线后立马恢复到100Mbps。所以调试阶段一定要打印出协商结果确认速度和双工模式。2.3 硬件复位与电源管理要点PHY芯片通常有一个复位引脚低电平有效。STM32F429开发板上一般会用GPIO控制PHY复位。复位时序要求是拉低至少100微秒然后拉高等待至少100毫秒让PHY内部稳定。这个时间不能省我试过只等10毫秒就初始化结果PHY寄存器读写全错。电源方面LAN8720A需要3.3V供电电流大概几十毫安。要注意的是PHY的模拟电源和数字电源最好分开滤波否则网络通信时会有偶发丢包。有些低成本板子为了省电容把模拟电源和数字电源直接连在一起跑TCP大流量时丢包率明显上升。如果你的板子有这个问题可以在PHY的AVDD引脚附近加一个10uF钽电容和一个0.1uF陶瓷电容。还有一点RMII的REF_CLK时钟质量直接影响通信稳定性。用示波器量一下PA1引脚上的50MHz时钟峰峰值应该在3.3V左右上升时间要快抖动要小。如果时钟信号有振铃或者幅度不够PHY可能工作不正常。我遇到过一块板子REF_CLK走线太长导致时钟幅度只有2VPHY时好时坏后来在PA1引脚附近加了一个33欧姆的串联电阻才解决。3. DMA描述符与数据收发机制3.1 DMA描述符链的构建与管理STM32F429的ETH外设使用DMA来搬运数据帧DMA描述符是理解整个收发流程的核心。每个描述符包含4个32位字状态字、缓冲区大小、缓冲区指针、下一个描述符指针。发送和接收各有独立的描述符链通过ETH_DMATDLAR和ETH_DMARDLAR寄存器告诉DMA链表的起始地址。描述符的状态字包含了很多控制位和状态位。以接收描述符为例OWN位表示描述符是否被DMA占用如果OWN1说明DMA正在使用这个描述符CPU不能碰如果OWN0说明DMA已经接收完数据CPU可以读取。还有FS首段和LS末段位表示帧的起始和结束如果一帧数据跨多个描述符中间描述符的FS和LS都是0。ES错误摘要位表示接收过程中是否有错误。发送描述符的OWN位含义相反OWN1表示CPU已经把数据准备好DMA可以发送OWN0表示DMA已经发送完成CPU可以回收缓冲区。这个OWN位的翻转是CPU和DMA之间的同步机制理解了这个就理解了整个收发流程。我一般会分配4到8个接收描述符和4个发送描述符。接收描述符的缓冲区大小设为1524字节以太网最大帧长加上一些余量发送描述符的缓冲区大小根据实际发送的数据长度动态设置。描述符本身要放在内存里注意对齐要求——STM32的ETH DMA要求描述符地址按4字节对齐缓冲区地址最好也按4字节对齐否则性能会下降。// 描述符定义示例 typedef struct { volatile uint32_t Status; uint32_t ControlBufferSize; uint32_t Buffer1Addr; uint32_t Buffer2NextDescAddr; } ETH_DMADescTypeDef; // 接收描述符数组注意对齐 ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __attribute__((aligned(4))); uint8_t Rx_Buff[ETH_RXBUFNB][ETH_MAX_PACKET_SIZE] __attribute__((aligned(4)));初始化的时候要把接收描述符的OWN位设为1让DMA开始接收。发送描述符的OWN位设为0表示CPU可以填充数据。然后启动DMA的接收和发送ETH就进入工作状态了。3.2 数据接收流程与中断处理数据接收的流程是这样的PHY收到网线上的差分信号解码后通过RMII接口送给MAC。MAC检查帧格式去掉前导码和SFD计算CRC如果CRC正确且目的MAC地址匹配或者广播/组播就把数据写入DMA描述符指向的缓冲区。写完后DMA把描述符的OWN位清零并触发接收中断。在中断服务函数里CPU遍历接收描述符链找到OWN0的描述符这就是有新数据的描述符。然后检查状态字里的FS和LS位如果FS1且LS1说明这一帧在一个描述符里直接处理就行。如果跨多个描述符需要把数据拼起来。处理完后把描述符的OWN位重新设为1交还给DMA。这里有个细节接收中断触发后不要在处理函数里做太多事情。我一般是在中断里只做标记把实际的数据处理放到主循环或者任务里。因为中断处理时间太长会影响后续数据接收导致丢包。特别是跑TCP大流量的时候中断里如果打印调试信息丢包率会飙升。还有一个常见问题接收描述符耗尽。如果CPU处理速度跟不上DMA接收速度所有描述符的OWN位都是1DMA就没地方写新数据了只能丢弃。这时候ETH的MMC计数器会记录丢包数量。解决办法是增加描述符数量或者提高CPU处理速度。我一般用8个接收描述符跑100Mbps满速时基本不会丢包。3.3 数据发送流程与零拷贝优化发送流程跟接收相反CPU把要发送的数据填入发送描述符的缓冲区设置好ControlBufferSize然后把OWN位设为1最后写ETH_DMATPOLR寄存器触发发送。DMA会自动把数据从内存搬到MACMAC加上前导码、SFD和CRC后通过RMII发给PHY。发送完成后DMA把OWN位清零并触发发送中断。发送中断里CPU遍历发送描述符找到OWN0的描述符说明这一帧已经发送完成可以回收缓冲区了。如果还有数据要发就继续填充下一个描述符。如果没有数据要发就把发送描述符链恢复到初始状态。零拷贝优化是提高发送性能的关键。默认情况下LwIP会把数据从应用层缓冲区拷贝到pbuf再从pbuf拷贝到发送描述符缓冲区两次拷贝浪费CPU时间。零拷贝的做法是让pbuf直接指向发送描述符的缓冲区省去第二次拷贝。具体实现是自定义pbuf的alloc函数从发送描述符的空闲缓冲区里分配内存。这样LwIP组装数据包时直接写在DMA缓冲区里发送时不需要再拷贝。不过零拷贝也有代价发送描述符的缓冲区被pbuf占用期间不能用于其他发送。所以发送描述符数量要足够多否则会出现pbuf分配失败。我一般用4个发送描述符配合零拷贝跑TCP吞吐量能到90Mbps以上。如果不用零拷贝吞吐量大概只有60Mbps左右差距还是很明显的。4. 常见问题排查与实操避坑指南4.1 PHY识别失败与MDIO通信异常PHY识别失败是最常见的问题现象是ETH_ReadPHYRegister返回0xFFFF或者0x0000。排查思路按以下顺序来先查硬件。用万用表量PHY的供电引脚应该是3.3V。量复位引脚初始化后应该是高电平。量REF_CLK引脚应该有50MHz时钟用示波器或者频率计。如果REF_CLK没有时钟检查PHY的晶振是否起振以及PHY的时钟输出配置是否正确。再查MDIO通信。MDC时钟频率不能超过2.5MHzSTM32的ETH_MACMIIAR寄存器的CR位域控制分频系数。如果系统时钟是180MHz分频系数设为150的话MDC就是1.2MHz比较合适。如果分频系数太小MDC太快PHY可能来不及响应。我试过用180分频1MHz和100分频1.8MHz都能正常工作。然后查PHY地址。LAN8720A的PHYAD0引脚决定地址如果悬空或者接错地址就不对。可以用ETH_ReadPHYRegister遍历0到31所有地址看哪个能读到正确的PHY ID。这个方法很实用我靠它发现过好几次地址配置错误的问题。最后查软件配置。ETH_MACMIIAR寄存器的MB位是忙标志写1启动MDIO传输硬件完成后自动清零。如果一直不清零说明MDIO通信有问题。这时候要检查PA2MDIO和PC1MDC的GPIO配置必须是复用开漏模式并且使能了ETH时钟。实操心得调试MDIO的时候可以在读写寄存器前后加打印看看是读操作失败还是写操作失败。如果写成功但读失败多半是PHY地址不对如果写也失败那就是MDIO硬件或者时钟配置有问题。4.2 丢包严重与通信不稳定的排查丢包问题比PHY识别失败更隐蔽因为PHY能识别链路也能建立就是数据传着传着就丢了。常见原因有以下几个第一DMA描述符配置错误。如果接收描述符的缓冲区大小设得太小比如只设了64字节那超过64字节的帧就会被截断或者丢弃。以太网最大帧是1518字节加上VLAN标签是1522字节所以缓冲区至少要设1524字节。我一般设1536字节留点余量。第二中断优先级配置不当。ETH中断如果被其他高优先级中断频繁打断可能导致接收描述符来不及处理。建议把ETH中断优先级设得高一些但不要最高避免影响系统滴答定时器。我一般设成优先级50最高15最低。第三内存访问冲突。ETH的DMA通过AHB总线访问内存如果CPU同时频繁访问同一块内存区域会产生总线仲裁延迟。解决办法是把描述符和缓冲区放在CCM RAM里STM32F429有64KB CCM RAMCCM RAM只供CPU访问不参与DMA但DMA可以通过AHB总线访问。等等这里说反了——CCM RAM是CPU专用DMA不能访问。所以描述符和缓冲区要放在普通SRAM里不能放CCM RAM。我踩过这个坑把描述符放CCM RAM里结果DMA完全不动。第四PHY自协商结果不对。如果协商成10Mbps半双工而你的代码按100Mbps全双工配置就会大量丢包。一定要在初始化后打印PHY_SR寄存器的值确认速度和双工模式。第五网线质量差。这个听起来简单但实际调试中经常被忽略。劣质网线的线序不对、屏蔽层没接好、水晶头压接不良都会导致丢包。我习惯用一根已知良好的短网线1米以内做调试排除网线因素后再换长线测试。4.3 LwIP与底层驱动对接的常见坑虽然这一篇重点在以太网底层但LwIP跟底层驱动的对接是绕不开的。这里说几个常见的对接问题第一个是pbuf分配失败。LwIP的pbuf池大小是固定的如果发送数据量太大或者接收数据来不及处理pbuf池会耗尽。解决办法是增大PBUF_POOL_SIZE和MEM_SIZE。我一般把PBUF_POOL_SIZE设成16MEM_SIZE设成16KB跑TCP吞吐量测试基本够用。第二个是ethernetif_input的调用时机。在裸机环境下ethernetif_input要在主循环里轮询调用不能在中断里直接调用。因为LwIP的处理函数可能会阻塞在中断里调用会导致系统卡死。我一般是在ETH接收中断里设置一个标志主循环检测到标志后调用ethernetif_input。第三个是MAC地址配置。STM32F429的ETH外设有自己的MAC地址寄存器但LwIP也有自己的MAC地址配置。两边要一致否则会出现能收不能发或者能发不能收的怪现象。我一般是在ETH初始化时设置MAC地址寄存器同时把同样的地址传给LwIP的netif结构体。第四个是checksum卸载。STM32F429的ETH外设支持硬件checksum卸载可以自动计算IP、TCP、UDP的校验和。开启这个功能能显著降低CPU占用率。配置方法是在ETH_MACCR寄存器里设置IPC和TCPCSPC位然后在发送描述符的状态字里设置CIC位。不过要注意接收方向的checksum验证需要PHY支持LAN8720A不支持接收checksum卸载所以接收方向的校验和还是得软件算。4.4 常见问题速查表现象可能原因排查方法解决方案PHY ID读不到供电异常万用表量3.3V检查电源电路PHY ID读不到复位时序不对示波器看复位引脚延长复位低电平时间PHY ID读不到MDIO通信失败读ETH_MACMIIAR的MB位检查GPIO配置和时钟PHY ID读不到PHY地址错误遍历0-31地址修正PHYAD引脚电平链路建立但丢包描述符缓冲区太小检查ControlBufferSize设为1536字节链路建立但丢包中断优先级太低查看NVIC配置提高ETH中断优先级链路建立但丢包自协商结果不对读PHY_SR寄存器强制100M全双工链路建立但丢包网线质量差换已知良好网线更换网线发送正常接收异常MAC地址不匹配对比ETH和LwIP的MAC统一MAC地址接收正常发送异常发送描述符未触发检查ETH_DMATPOLR写寄存器触发发送跑一会儿死机描述符耗尽查看MMC计数器增加描述符数量跑一会儿死机pbuf池耗尽查看LwIP统计增大PBUF_POOL_SIZE这张表是我调试过程中一点点积累的基本上覆盖了80%的常见问题。遇到问题先查表能省不少时间。5. 性能测试与优化经验5.1 吞吐量测试方法与结果分析吞吐量测试是验证以太网通信性能的直接手段。我一般用两种方法一种是PC端跑iperfSTM32端跑LwIP的TCP echo服务器另一种是STM32端主动发送大量数据PC端用网络调试助手接收统计。用iperf测试时STM32端跑TCP服务器PC端执行iperf -c 192.168.1.100 -t 30 -i 1测试30秒每秒打印一次结果。我实测下来STM32F429跑LwIP的TCP吞吐量大概在70到90Mbps之间取决于是否开启零拷贝和checksum卸载。开启零拷贝后发送吞吐量能到92Mbps左右接收吞吐量大概85Mbps。这个成绩对于180MHz的M4来说相当不错了。影响吞吐量的因素有几个第一是TCP窗口大小LwIP默认的TCP_WND是4个MSS对于100Mbps网络来说偏小我一般设成8个MSS。第二是PBUF_POOL_SIZE太小会导致频繁分配失败我设成16。第三是MEM_SIZE设成16KB。第四是中断处理效率中断里做的事情越少越好。测试的时候要注意PC端的防火墙和杀毒软件可能会影响测试结果。我遇到过Windows Defender实时扫描导致吞吐量从90Mbps掉到40Mbps的情况关掉实时扫描后恢复正常。另外PC端的网卡也要支持100Mbps全双工有些老网卡只支持100Mbps半双工会成为瓶颈。5.2 CPU占用率优化技巧跑网络通信的时候CPU占用率是另一个关键指标。如果CPU被网络任务占满应用层就没法干活了。我实测过不开启任何优化的情况下跑100Mbps TCP流CPU占用率大概在60%到70%。开启零拷贝和checksum卸载后降到30%左右。降低CPU占用率的手段有几个第一开启DMA接收和发送这个前面说过了。第二开启硬件checksum卸载发送方向的IP、TCP、UDP校验和都由硬件算CPU不用管。第三减少中断频率把接收中断改成轮询模式或者用中断加轮询的混合模式。第四优化LwIP的配置参数比如把TCP_MSS设成1460避免分片。还有一个容易被忽略的点调试打印。如果在数据收发路径上有printf哪怕只是打印一个字符都会显著增加CPU占用率。我调试的时候习惯用GPIO翻转加示波器来观察时序比printf高效得多。如果一定要打印用SWO或者RTT比UART快很多。5.3 长时间稳定性测试与内存泄漏排查网络通信的稳定性很重要跑几分钟没问题不代表跑几天没问题。我一般会做24小时连续收发测试观察是否有丢包、死机、内存泄漏。内存泄漏是LwIP常见的问题特别是用Socket API的时候如果忘记close或者freepbuf会慢慢耗尽。排查方法是定期打印LwIP的统计信息看pbuf池的已用数量是否持续增长。如果持续增长说明有泄漏。我一般会在主循环里每秒打印一次memr_get_mem_used()和pbuf_free()的统计观察趋势。另一个稳定性问题是DMA描述符溢出。如果接收描述符的OWN位长时间都是1说明CPU处理不过来。这时候可以增加描述符数量或者降低接收中断的触发阈值。STM32的ETH支持接收中断阈值配置可以设置收到多少个帧后才触发中断减少中断频率。还有一点PHY芯片在长时间工作后可能会因为温度漂移导致链路不稳定。工业级PHY比如DP83848比商业级PHY比如LAN8720A在这方面表现好很多。如果产品要在恶劣环境下工作建议选工业级PHY并且做好散热。6. 从底层到应用的衔接思路以太网底层调通之后下一步就是跑LwIP协议栈。LwIP的移植主要做三件事第一实现ethernetif_init函数把netif结构体跟ETH驱动对接起来第二实现ethernetif_input函数把接收到的数据帧交给LwIP处理第三实现ethernetif_output函数把LwIP要发送的数据帧交给ETH驱动发送。ethernetif_init里要做的事情包括设置netif的name、output、linkoutput等回调函数设置MAC地址初始化ETH外设启动DMA接收。ethernetif_input里要做的事情是从接收描述符里取出数据帧封装成pbuf调用netif-input把pbuf交给LwIP。ethernetif_output里要做的事情是把pbuf里的数据拷贝到发送描述符缓冲区触发DMA发送。这三个函数是LwIP跟底层驱动的桥梁写好了就能跑通。ST官方的STM32CubeF4软件包里已经有现成的实现可以直接参考。但要注意官方代码里有些配置是针对特定开发板的移植到自己的板子上要改PHY地址、引脚配置、时钟配置等。跑通LwIP之后就可以用Socket API写应用层代码了。比如做一个TCP echo服务器或者UDP数据采集终端或者HTTP服务器。这些应用层的开发就是常规的Socket编程跟PC上写网络程序差不多只是资源受限要注意内存和CPU的使用。我个人建议的学习路径是先把以太网底层调通能ping通、能收发原始帧然后跑LwIP的RAW API理解pbuf和netif的机制最后用Socket API写应用。这样一步步来遇到问题容易定位。如果一上来就跑LwIP的Socket示例底层出问题的时候会不知道从哪查起。最后分享一个小技巧调试以太网的时候用Wireshark抓包是最有效的工具。在PC端装Wireshark把网卡设成混杂模式就能看到STM32发出的所有帧。如果STM32发出的帧格式不对Wireshark会标红提示。如果STM32收不到PC发的帧可以在Wireshark里看PC有没有发出去。抓包分析比盲猜高效得多强烈建议每个搞嵌入式网络的人都熟练掌握。

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

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

免费获取报价 →
↑