ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

STM32H743+LAN8720以太网配置从CubeMX到Ping通的完整指南

STM32H743+LAN8720以太网配置从CubeMX到Ping通的完整指南 最近在调一块 STM32H743 LAN8720 的以太网板子本以为就是 CubeMX 勾勾选选、生成代码、跑通 LWIP 的标准流程结果从“点灯工程”到“Ping 通”整整折腾了一天半。网上的参考大多停留在 F4 和 F7 系列H743 的以太网时钟来源、PHY 复位时序、PHY 地址这些细节单独拎出来都不难凑在一起就特别容易卡壳。这篇就把我从零配置到成功 Ping 通的完整过程记录下来包括 CubeMX 里每个关键参数怎么选、生成代码后必须手改哪几处、以及“网线插了却死活不通”时的完整排查思路。适合正在调 H7 系列以太网、或者准备从 LAN8720 入门 LWIP 的朋友直接对照操作。1. 方案选型与整体设计思路1.1 为什么选 STM32H743 LAN8720 这个组合STM32H743 自带 10/100M 以太网 MAC 控制器支持 MII 和 RMII 两种接口但 MCU 本身没有 PHY必须外接一颗以太网物理层芯片。LAN8720 是 Microchip 的低功耗 10/100M 以太网 PHY体积小、外围电路简单、价格便宜是 H7 开发板和工控板上的常客。两者配合一片 MCU 就能完成 TCP/UDP 通信、Web 服务、固件升级等常见网络功能。选择这个组合的另一个现实原因是生态成熟。正点原子、野火这两家 H743 核心板基本都是 LAN8720官方例程也是这套方案所以遇到问题能参考的资料相对多一些。相比 W5500 这种集成 MACPHY 的方案STM32H743 的 ETH 外设 LWIP 协议栈方案更灵活内核协议栈可控性更强适合做稍微复杂的网络应用。1.2 RMII 接口原理与以太网整体架构MII 接口需要 16 根数据/控制线占用引脚太多所以 H743 实际应用中几乎都选 RMIIReduced Media Independent Interface。RMII 把数据线从 8 位降到 2 位控制信号也做了合并总共只需要 9 根信号线省下的引脚可以给串口、SPI、ADC 用。RMII 的关键要点是数据位宽 2 位时钟频率固定为 50MHzMAC 和 PHY 之间必须共享同一个参考时钟。这个“共享时钟”正是 LAN8720 布线设计里最容易出问题的地方。H743 的 ETH 外设里RMII 模式下不能自己产生 50MHz 参考时钟而是需要外部输入。所以说白了网络能不能跑起来一半看软件配置一半看硬件时钟对不对。1.3 软件链路CubeMX LWIP 的工作流程软件层面STM32CubeMX 可以同时配置 ETH 外设和 LWIP 协议栈。CubeMX 会生成 HAL 初始化代码以及 LWIP 的移植层文件ethernetif.c、lwip.c 等我们只需要在 main 函数里调用 MX_LWIP_Init() 启动协议栈然后在主循环里反复调用 MX_LWIP_Process() 让协议栈跑起来。但 CubeMX 默认生成的 LWIP 代码只保证“能编译”并不保证“能 Ping 通”。PHY 芯片的地址、复位引脚、时钟极性这些需要按实际硬件去调整这正是很多人卡住的地方。下面从硬件到软件一步步拆。2. 硬件连接与 50MHz 时钟配置2.1 LAN8720 引脚功能与接线对照LAN8720 在 RMII 模式下与 H743 的连线如下表所示。不同开发板的引脚分配可能不同但信号对应关系基本一致LAN8720 信号功能说明STM32H743 引脚常见分配TXD0发送数据位0PG13TXD1发送数据位1PG14TX_EN发送使能PG11RXD0接收数据位0PC4RXD1接收数据位1PC5CRS_DV载波侦听/数据有效PA7MDC管理接口时钟PC1MDIO管理接口数据PA2REF_CLK50MHz参考时钟PA1NRSTPHY复位任意GPIO常用PG15nINT/REGOUT中断输出/稳压输出可不接这里最容易踩的第一个坑是 REF_CLK。很多同学在 CubeMX 里把 PA1 配成 ETH_REF_CLK 就以为完了却不知道这个引脚在硬件上必须以 50MHz 的时钟驱动而不是由 MCU 输出。2.2 50MHz 参考时钟的三种来源LAN8720 和 STM32H743 的 RMII 接口必须有一个共同的 50MHz 参考时钟常见做法有三种第一种外部 50MHz 有源晶振输出直接分成两路一路送给 LAN8720 的 XTAL1/CLK_IN通常 XTAL1 直接接时钟XTAL2 悬空另一路送给 H743 的 ETH_REF_CLKPA1。这种方案最简单可靠也是大多数官方开发板采用的做法。第二种25MHz 无源晶振接在 LAN8720 的 XTAL1/XTAL2 上由 LAN8720 内部 PLL 倍频到 50MHz从 CLK_OUTnINT/REGOUT 引脚输出给 H743。这种方案需要软件通过 SMI 总线写 PHY 寄存器来配置 CLK_OUT 使能如果配置不对H743 的 REF_CLK 就是 0HzMAC 直接收不到时钟。第三种外部 50MHz 时钟只进 LAN8720LAN8720 再把 50MHz 时钟缓冲输出给 H743本质上和第一种类似。我调试的板子采用的是第一种方案外部有源晶振提供 50MHz同时接到 LAN8720 和 PA1。这种方案在 CubeMX 里其实不需要额外配置时钟输出引脚但前提是硬件上确实把时钟送到位了。先用示波器或万用表确认 PA1 有没有 50MHz 时钟能省掉一大半排查时间。2.3 硬件设计检查清单硬件层面的坑软件永远补不回来。动手配置前建议先按下面的清单逐项确认LAN8720 的供电是否正常VDDCR 引脚是否接对了 3.3V很多模块把 VDDCR 和 VDDIO 分开设计接错会导致 PHY 完全不工作。REF_CLK 有没有 50MHz并且幅度是否足够。用示波器看波形至少要能稳定过 1.8V 阈值。复位引脚 NRST 是否有 RC 复位电路上电后能不能正常拉高。不能正常复位PHY 会一直处于非法状态。RMII 信号线上有没有串联电阻如果串了 33Ω 或 22Ω要确认信号质量不会差到丢包。网线变压器的中心抽头处理是否正确LAN8720 通常需要在 TX 差分对和 RX 差分对加上偏置电阻。MDIO/MDC 上拉是否到位MDIO 一般需要 2.2kΩ 到 10kΩ 上拉到 3.3V。我在调试时遇到过一个奇怪现象板子第一次上电 Ping 不通手动按一下复位键就能通。最后查出来是 LAN8720 的 NRST 引脚没有接上拉电容上电复位时序不可靠。这种问题最坑因为现象时好时坏光看软件配置看不出任何毛病。3. CubeMX 配置 LWIP 的完整流程3.1 新建工程与 ETH 外设配置打开 CubeMX选择对应型号的 STM32H743 芯片。我用的是一颗 STM32H743VIT6封装不同不影响 ETH 引脚分配。左侧 Categories 栏找到 Connectivity - ETH打开后在 Mode 下拉里选择 RMII。ETH 配置页里有几个关键参数PHY Address默认为 0。LAN8720 的 PHY 地址由 PHYAD0 引脚的上下拉决定绝大多数模块默认是 0。如果你的模块标着 PHYAD 是 1这里就要改成 1。MAC Address随便填一个合法的单播 MAC比如 02:00:11:22:33:44。注意第一个字节最低位必须是 0表示单播地址。时钟选择RMII 模式下ETH 外设的时钟来自外部 REF_CLKCubeMX 的时钟树里一般显示为 ETHERNET 时钟不需要手动配置分频。但要确认时钟树里 ETH 时钟源选择正确。PHY 相关的寄存器配置在 CubeMX 里也能指定。很多教程会建议把 PHY 的复位延时从默认值改大一些这个后面代码修改部分再细说。3.2 LWIP 协议栈参数设置在 Middleware and Software Packs 里勾选 LWIP。配置界面里有几个常用的选项Version选 2.1.2 或 2.1.3依赖的底层接口都差不多。Mode如果不跑 RTOS选 No OS如果后面要加 FreeRTOS选 RTOS。DHCP如果希望板子自动获取 IP勾上否则关掉用静态 IP。IP Address静态 IP 建议填 192.168.1.30 这类和 PC 同一网段的地址。Netmask 填 255.255.255.0Gateway 填网关 IP不联网也可以填同网段任意 IP。LWIP 的 MEM_SIZE、PBUF 等参数默认值就能满足 Ping 通和简单 TCP 通信。如果做大量数据传输再调大 MEM_SIZE 和 TCP_WND。这里特别提醒DHCP 在无路由器的点对点直连条件下不太省心有时会等很久拿不到 IP。首次测试建议直接用静态 IP排除 DHCP 超时带来的干扰。3.3 生成代码后必须检查的两个地方CubeMX 生成工程后别急着烧录先检查这两处第一处是 main.c 中生成的外设句柄。HAL 库里所有外设名都会带 h例如 ETH 句柄一般是 hethLWIP 的初始化文件里会用到这个句柄。如果工程里同时有多个外设要确认 LWIP 初始化函数用的是同一个 heth。第二处是 PHY 地址。CubeMX 在 LWIP 配置界面里填的 PHY Address 会传递到 LWIP 的 PHY 驱动读取函数中。生成的代码里LAN8720 这种 PHY 的读取逻辑其实并没有真正实现CubeMX 生成的 ethernetif.c 里会有一个默认的 PHY 探测逻辑。如果读不到 PHY ID说明 PHY 地址不对或者 MDIO 时序有问题。我的做法是生成代码后先不急着加业务逻辑直接在 main 函数里加一行读取 PHY ID 的测试确认 MDIO 能正常读回 0x0007 开头的 LAN8720 芯片 ID。能读到再继续读不到就回头查硬件。4. 关键代码修改与成功 Ping 通4.1 PHY 地址与软件复位修改生成的 main.c 里MX_LWIP_Init() 负责初始化协议栈它内部会调用 ethernetif.c 中的 low_level_init()。默认代码对 LAN8720 的兼容性一般建议做两处修改。第一处确认 PHY 地址。打开 LWIP 的头文件或者 CubeMX 生成的 lwipopts.h / ethernetif.c找到 PHY 地址相关宏确认是 0#define PHY_ADDRESS 0如果硬件 PHYAD0 引脚接的是高电平就要改成 1。这个地址一旦不对MDIO 通信等于全白搭。第二处在 MX_LWIP_Init() 之前加延时和 PHY 复位。LAN8720 上电后需要一段时间稳定如果 MCU 启动速度比 PHY 快直接初始化 ETH 会读到一堆无意义数据。在 main 函数的 MX_LWIP_Init() 调用前加上至少 100ms 延时HAL_GPIO_WritePin(GPIOG, GPIO_PIN_15, GPIO_PIN_RESET); // 复位LAN8720 HAL_Delay(100); HAL_GPIO_WritePin(GPIOG, GPIO_PIN_15, GPIO_PIN_SET); HAL_Delay(100); MX_LWIP_Init();如果你的板子把 NRST 固定接到了 MCU 复位电路上并不单独控制那这一步可以跳过用延时等待 PHY 自行稳定即可。但独立控制会可靠得多排查时也更方便。4.2 主循环中 LWIP 任务调度无 RTOS 环境下LWIP 需要周期性调用 MX_LWIP_Process() 来处理网络事件否则协议栈不工作。标准写法是在 while(1) 里反复调用while (1) { MX_LWIP_Process(); }如果主循环里还有其他任务注意不要用 HAL_Delay 挡住这个调度。LWIP 的 sys_check_timeouts() 需要靠 MX_LWIP_Process() 驱动长时间不调用会导致 TCP 重传超时、ARP 表过期等问题。我调试 Ping 不通的时候一开始以为是 IP 配置问题后来发现是因为主循环里加了一个 200ms 的阻塞延时ARP 请求发出去后迟迟没被协议栈处理。把这个阻塞去掉之后Ping 立刻通了。4.3 实际 Ping 测结果与网络状态验证编译烧录PC 网口直连板子PC 设置静态 IP 192.168.1.10子网掩码 255.255.255.0板子用 192.168.1.30。在 PC 终端输入ping 192.168.1.30 -t正常情况下能看到类似输出Reply from 192.168.1.30: bytes32 time1ms TTL255 Reply from 192.168.1.30: bytes32 time1ms TTL255TTL255 说明响应来自设备本身而不是经过路由转发时间在 1ms 左右说明链路非常健康。如果这块通了别急着开心再测两个东西。第一个把网线换到交换机上再 Ping排除直连线序差异。第二个连续 Ping 200 个包看有没有丢包ping 192.168.1.30 -n 200丢包率低于 0.5% 算正常。如果出现间歇性超时大概率是时钟问题、网线质量问题或者 DMA 配置问题。5. 常见问题与排查经验实录5.1 高频问题速查表按我遇到的以及帮别人排查过的经验网络不通的现象和原因可以整理成一张表现象可能原因排查方向LAN8720 灯完全不亮供电异常、NRST 一直被拉低先测 3.3V 电源再测 NRST 电平电源灯亮但 LINK 灯不亮网线接触不良、LAN8720 未初始化换网线检查 MDC/MDIO 是否通串口打印 PHY ID 失败PHY 地址不对、MDIO 时序异常确认 PHYAD 引脚检查上拉电阻Ping 完全不通LWIP 未调度、IP 不在同一网段、RMII 时钟缺失在 main loop 加 MX_LWIP_Process检查 PA1 波形Ping 通但丢包严重REF_CLK 质量差、电源纹波大、网线过长示波器看时钟换短网线加滤波电容板子一接网线就死机ETH 中断优先级问题、LWIP 堆栈溢出调低中断优先级增大 LWIP MEM_SIZEDHCP 一直获取不到 IP路由器 DHCP 池问题、PHY 没就绪先用静态 IP 测试5.2 从灯的状态快速定位故障LAN8720 模块上通常有两个 LED一个是电源/活动指示灯一个是 LINK/SPEED 灯。观察灯的状态能很快缩小问题范围。插上网线后LINK 灯应该常亮或闪烁。如果 LINK 灯亮说明 PHY 和交换机已经完成协商物理层基本没问题问题多半在 MAC、LWIP 或 IP 配置上。如果 LINK 灯不亮先检查 PHY 是否复位成功、RMII 时钟是否存在、网线本身是否坏的。特别提醒有些模块的 LINK 灯信号来自 LAN8720 的 LED1 引脚这个引脚默认配置是 10M/100M 速度指示不一定是 LINK 指示。所以灯灭也不能百分百断定物理层故障还是要以 MDIO 读取的 PHY 状态寄存器为准。我调这块板子时串口反复打印 PHY ID 失败但用示波器看 MDIO 波形又有数据。最后发现问题是 MDIO 引脚的上下拉配置不对CubeMX 默认把 PA2 配成了 ETH_MDIO 功能但硬件上缺少上拉电阻。在引脚配置里给 MDIO 加上内部上拉后PHY ID 就能正常读到了。5.3 独家避坑技巧与心得在 H743 上跑 LWIP有几个细节是常规教程不会写的但实际调试能救命。第一CubeMX 生成的 ETH 中断处理函数一定要正确挂到 NVIC 里。如果打开 ETH 唤醒中断、错误中断却没配置相应优先级可能出现“一插网线就进 HardFault”的诡异问题。我的做法是只使能 ETH 全局中断错误中断先用默认配置跑通基础通信后再细化。第二LWIP 的 DHCP 和静态 IP 不要来回切太频繁。DHCP 失败后协议栈内部计时器状态可能会有残留重新初始化比较稳妥。调试阶段我更建议在 main 函数里用宏控制 IP 模式编译期决定走 DHCP 还是静态 IP。第三复位顺序很讲究。正确顺序是先复位 PHY再初始化 ETH再启动 LWIP。很多网络不通的问题本质是“LWIP 启动时 PHY 还没准备好”。我在 MX_LWIP_Init() 前加延时就是这个原因。第四调试网络问题不要乱改 LWIP 参数。默认配置跑通 Ping 绰绰有余一上来就调大 TCP_WND、修改内存池大小反而可能掩盖真正的问题。先让最简配置通起来再叠加业务逻辑这是最稳妥的调试路径。最后说一个经验如果换了一块 H743 板子或者换了 PHY 芯片型号别假设寄存器配置还通用。LAN8720 和 DP83848、JL1101、IP101GRI 这些 PHY寄存器地址和读 ID 的方式都不一样。重点看 PHY ID 寄存器的返回值这是所有调试的第一步。我自己就是把排查步骤固定成“看电源、看时钟、看 PHY ID、看链路”每块新板子都按这个顺序走一遍基本不会卡太久。这个流程整套走下来从 CubeMX 配置到 Ping 通正常一次通过只需要半小时但前提是先把硬件时钟和 PHY 地址这两个最容易藏雷的地方确认好。剩下的就是耐心看灯、看串口日志、看示波器波形把问题一层层剥开。
返回列表