DKENNY 发表于 2025-5-22 15:24

揭秘以太网通信的幕后故事:RMII(以LAN8720为例)与MII(以DP83825为例)通信全解析

本帖最后由 DKENNY 于 2025-5-22 15:22 编辑

#技术资源# #申请原创# @21小跑堂

前言
      接上文讲了PHY的原理,也以LAN8720(RMII)为例,实现了一些伪代码,我们知道以太网通信是嵌入式系统中连接世界的“高速公路”,而APM32F407单片机就像一个高效的“交通指挥中心”,通过其内置的以太网MAC模块,与外部PHY芯片(如LAN8720和DP83825)协作,完成数据的收发任务。
      在这篇文章中,我们将以LAN8720(RMII协议)和DP83825(MII协议)为例,深入讲解这两种接口的通信过程,涵盖原理、时序、代码实现。

1、背景:为什么要用LAN8720和DP83825?
      - LAN8720:一款常用的RMII接口PHY芯片,支持10Mbps和100Mbps速率,引脚少、设计简单,适合资源受限的嵌入式系统。
      - DP83825:一款支持MII接口的PHY芯片,同样支持10Mbps和100Mbps,信号线多但功能全面,适合需要高可靠性的场景。
      MII和RMII作为MAC与PHY之间的“桥梁”,决定了数据如何在这两者间高效传递。LAN8720用RMII协议,引脚少、设计紧凑;DP83825用MII协议,信号丰富、可靠性高。接下来,我们将详细剖析这两种模式的通信过程,带你看清数据在“高速公路”上是如何跑起来的!

2、MII与RMII通信原理:从“大路”到“窄路”的区别
      在深入通信过程之前,我们先搞清楚MII和RMII的原理和区别。

2.1 MII:宽敞的“四车道高速公路”
      MII(Media Independent Interface,介质无关接口)就像一条宽敞的四车道高速公路,专门为MAC和PHY之间传递数据设计。它的特点是:
      - 数据宽度:每次传输4位数据(用TXD发送,RXD接收)。
      - 时钟信号:用两个独立的时钟——TX_CLK(发送时钟)和RX_CLK(接收时钟)。10Mbps时钟频率是2.5MHz,100Mbps是25MHz。
      - 信号线多:总共需要18根信号线,包括数据线、控制线(像TX_EN、RX_DV)和管理线(MDC、MDIO)。
      MII的优点是传输稳定,适合需要高可靠性的场景,比如工业控制。但缺点也很明显:信号线多,占用了很多引脚,PCB布线也更复杂。
      MII就像一条宽路,每次能跑四辆车(4位数据),但需要很多车道(18根线),修路成本高。

2.2 RMII:高效的“双车道快车道”
      RMII(Reduced Media Independent Interface,精简介质无关接口)是MII的“瘦身版”,像一条双车道快车道,通过优化设计减少了引脚需求。它的特点是:
      - 数据宽度:每次只传输2位数据(TXD发送,RXD接收)。
      - 时钟信号:用一个统一的50MHz参考时钟(REF_CLK),取代MII的两个时钟,发送和接收都靠这个时钟同步。
      - 信号线少:总共只需要9根信号线,合并了部分控制信号(如CRS和RX_DV合并为CRS_DV)。
      RMII通过提高时钟频率(50MHz)和减少数据位宽,实现了与MII相同的传输效率,同时大大降低了引脚数,适合引脚资源紧张的嵌入式系统。
      相比MII来说,RMII像一条窄路,每次只能跑两辆车(2位数据),但车速快(50MHz),车道少(9根线),修路成本低。



3、LAN8720(RMII)通信过程:数据在“双车道”上如何跑?
      LAN8720是一款典型的RMII接口PHY芯片,广泛用于嵌入式以太网设计。我们以APM32F407和LAN8720的组合为例,详细讲解RMII通信的整个过程,从初始化到数据收发,再到时序分析。

3.1 RMII通信的硬件连接
      在RMII模式下,APM32F407的MAC通过9根信号线与LAN8720连接。以下是典型的引脚分配:


信号名
APM32F407引脚
LAN8720引脚
功能

TXD0
PB12
TXD0
发送数据位0

TXD1
PB13
TXD1
发送数据位1

TX_EN
PB11
TX_EN
发送使能,告诉PHY有数据要发

RXD0
PC4
RXD0
接收数据位0

RXD1
PC5
RXD1
接收数据位1

CRS_DV
PA7
CRS_DV
载波检测/数据有效,告诉MAC有数据可收

REF_CLK
PA1
REF_CLK
50MHz参考时钟,同步发送和接收

MDC
PC1
MDC
管理时钟,用于配置PHY

MDIO
PA2
MDIO
管理数据,读写PHY寄存器

      注意:
      - REF_CLK可以由LAN8720提供(通过其内部晶振),也可以由外部50MHz晶振或APM32F407的时钟输出提供。
      - LAN8720还需要连接RJ45接口(带变压器)和25MHz晶振(用于其内部时钟)。


3.2 RMII通信的初始化流程
      在数据传输之前,APM32F407需要初始化以太网MAC和LAN8720。初始化就像“修好高速公路并设置交通规则”,主要步骤如下:
      1. 使能时钟:
         - 打开APM32F407的以太网MAC、GPIO和DMA的时钟。
         - 确保LAN8720的电源和25MHz晶振正常工作。
      2. 配置GPIO引脚:
         - 将TXD0、TXD1、TX_EN、MDC、MDIO配置为复用推挽输出。
         - 将RXD0、RXD1、CRS_DV配置为输入。
         - REF_CLK根据时钟源配置为输入或输出。
      3. 配置MAC:
         - 设置RMII模式(通过ETH_MACCR寄存器)。
         - 配置速度(100Mbps或10Mbps)和双工模式(全双工或半双工)。
         - 使能DMA传输。
      4. 配置LAN8720:
         - 通过MDC和MDIO接口,写入LAN8720的寄存器,设置速度、双工模式和自动协商。
         - 读取LAN8720的状态寄存器,确认链路已建立。
      5. 启动通信:
         - 使能MAC的发送和接收功能,准备好数据缓冲区。

      代码示例:RMII初始化
#include "apm32f4xx_eth.h"
#include "apm32f4xx_gpio.h"
#include "apm32f4xx_rcm.h"

void RMII_Init(void)
{
    GPIO_Config_T gpioConfig;
    ETH_Config_T ethConfig;

    // 使能时钟
    RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_ETHMAC | RCM_AHB1_PERIPH_ETHMACTX | RCM_AHB1_PERIPH_ETHMACRX);
    RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA | RCM_APB2_PERIPH_GPIOB | RCM_APB2_PERIPH_GPIOC);

    // 配置GPIO引脚
    gpioConfig.mode = GPIO_MODE_AF;
    gpioConfig.speed = GPIO_SPEED_50MHz;
    gpioConfig.outType = GPIO_OUT_TYPE_PP;
    gpioConfig.pupd = GPIO_PUPD_NOPULL;

    gpioConfig.pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
    GPIO_Config(GPIOA, &gpioConfig);
    gpioConfig.pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
    GPIO_Config(GPIOB, &gpioConfig);
    gpioConfig.pin = GPIO_PIN_4 | GPIO_PIN_5;
    GPIO_Config(GPIOC, &gpioConfig);

    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_1, GPIO_AF_ETH); // REF_CLK
    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_2, GPIO_AF_ETH); // MDIO
    // ... 其他引脚复用配置

    // 配置MAC
    ethConfig.mode = ETH_MODE_FULLDUPLEX;
    ethConfig.speed = ETH_SPEED_100M;
    ethConfig.interface = ETH_INTERFACE_RMII;
    ETH_Config(ðConfig);

    // 配置LAN8720
    ETH_WritePHYRegister(0x00, 0x00, 0x3100); // 设置100Mbps,全双工
    ETH_Start();
}
3.3 RMII发送数据的通信过程
      假设APM32F407要发送一个数据包(比如一个UDP包),RMII的发送过程就像“把货物装上卡车,通过双车道送到目的地”。具体步骤如下:
      1. 准备数据:
         - 应用程序(比如LwIP协议栈)生成一个数据包,存储在内存中。
         - MAC的DMA控制器将数据从内存搬到TX缓冲区。
      2. 通知发送:
         - MAC把数据分成2位一组,依次放到TXD上。
         - 同时置TX_EN为高,告诉LAN8720“有数据要发”。
      3. 数据传输:
         - LAN8720在REF_CLK的上升沿采样TXD上的2位数据。
         - 因为RMII每次只传2位,而MII一次传4位,所以RMII用50MHz的REF_CLK,速度快一倍,保证传输效率。
         - 数据传输完成后,MAC置TX_EN为低,表示发送结束。
      4. PHY处理:
         - LAN8720将收到的数字数据编码为物理信号(比如曼彻斯特编码),通过RJ45接口发送到网线。


3.4 RMII接收数据的通信过程
      接收过程就像“从网线收到货物,通过双车道运回仓库”。具体步骤如下:
      1. PHY接收信号:
         - LAN8720从网线接收物理信号,解码为数字数据。
         - 数据被分成2位一组,准备通过RXD发送给MAC。
      2. 通知接收:
         - LAN8720置CRS_DV为高,表示“有数据可收”或“链路有信号”。
         - 数据被放到RXD上。
      3. 数据传输:
         - MAC在REF_CLK的上升沿采样RXD上的2位数据。
         - 每2位数据需要一个50MHz时钟周期,MAC将数据拼凑成完整的数据包。
      4. 存储数据:
         - MAC的DMA控制器将接收到的数据搬到RX缓冲区。
         - 应用程序读取缓冲区数据,完成接收。


3.5 RMII的管理接口(MDC/MDIO)
      除了数据传输,MAC还需要通过MDC和MDIO配置LAN8720或读取其状态。比如:
      - 设置LAN8720为100Mbps全双工模式。
      - 检查链路是否连接(通过读取状态寄存器)。

      过程:
      - MDC提供1-2.5MHz的时钟信号。
      - MDIO传输数据帧,包含操作码(读/写)、PHY地址、寄存器地址和数据。
      - 比如,写入LAN8720的控制寄存器(地址0x00)值为0x3100,设置100Mbps全双工。

      代码示例:MDIO配置
void ConfigureLAN8720(void)
{
    // 设置100Mbps,全双工
    ETH_WritePHYRegister(0x00, 0x00, 0x3100);

    // 读取状态寄存器
    uint16_t status;
    ETH_ReadPHYRegister(0x00, 0x01, &status);
    if (status & 0x0004) {
      printf("Link is up!\n");
    }
}
4、DP83825(MII)通信过程:数据在“四车道”上如何跑?
      DP83825是一款MII接口PHY芯片,信号线多但功能全面。同样的,我们以APM32F407和DP83825为例,讲解MII通信的完整过程。

4.1 MII通信的硬件连接
      MII模式需要18根信号线,APM32F407与DP83825的引脚分配如下:

信号名
APM32F407引脚
LAN8720引脚
功能

TXD0
PG13
TXD0
发送数据位0

TXD1
PG14
TXD1
发送数据位1

TXD2
PC2
TXD2
发送数据位2

TXD3
PB8
TXD3
发送数据位3

TX_EN
PG11
TX_EN
发送使能,告诉PHY有数据要发

TXCLK
PC3
TXCLK
发送时钟(2.5/25MHz)

RXD0
PC4
RXD0
接收数据位0

RXD1
PC5
RXD1
接收数据位1

RXD2
PH6
RXD2
接收数据位2

RXD3
PH7
RXD3
接收数据位3

RX_DV
PA7
RX_DV
接收数据有效

RX_CLK
PA1
RX_CLK
接收时钟(2.5/25MHz)

RX_ER
PI10
RX_ER
接收错误

CRS
PH2
CRS
载波检测/数据有效,告诉MAC有数据可收

COL
PH3
COL
冲突检测

MDC
PC1
MDC
管理时钟,用于配置PHY

MDIO
PA2
MDIO
管理数据,读写PHY寄存器

      注意:
      - TX_CLK和RX_CLK由DP83825提供,频率根据速率(10Mbps为2.5MHz,100Mbps为25MHz)。
      - DP83825还需要25MHz晶振和RJ45接口。


4.2 MII通信的初始化流程
      MII的初始化与RMII类似,但需要配置更多引脚和设置MII模式。步骤如下:
      1. 使能时钟:
         - 打开以太网MAC、GPIO和DMA时钟。
         - 确保DP83825的电源和晶振正常。
      2. 配置GPIO引脚:
         - 配置TXD、TX_EN、MDC、MDIO为复用推挽输出。
         - 配置RXD、RX_DV、RX_CLK、CRS、COL为输入。
      3. 配置MAC:
         - 设置MII模式(ETH_MACCR寄存器)。
         - 配置速度和双工模式。
    4. 配置DP83825:
         - 通过MDC/MDIO设置速度、双工模式和自动协商。
    5. 启动通信:
         - 使能MAC的发送和接收。

    代码示例:MII初始化
#include "apm32f4xx_eth.h"
#include "apm32f4xx_gpio.h"
#include "apm32f4xx_rcm.h"

void MII_Init(void)
{
    GPIO_Config_T gpioConfig;
    ETH_Config_T ethConfig;

    // 使能时钟
    RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_ETHMAC | RCM_AHB1_PERIPH_ETHMACTX | RCM_AHB1_PERIPH_ETHMACRX);
    RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA | RCM_APB2_PERIPH_GPIOB | RCM_APB2_PERIPH_GPIOC);

    // 配置GPIO引脚
    gpioConfig.mode = GPIO_MODE_AF;
    gpioConfig.speed = GPIO_SPEED_50MHz;
    gpioConfig.outType = GPIO_OUT_TYPE_PP;
    gpioConfig.pupd = GPIO_PUPD_NOPULL;

    gpioConfig.pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
    GPIO_Config(GPIOA, &gpioConfig);
    gpioConfig.pin = GPIO_PIN_8;
    GPIO_Config(GPIOB, &gpioConfig);

    // ... 其他引脚初始化配置

    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_1, GPIO_AF_ETH); // RX_CLK
    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_2, GPIO_AF_ETH); // MDIO
    // ... 其他引脚复用配置

    // 配置MAC
    ethConfig.mode = ETH_MODE_FULLDUPLEX;
    ethConfig.speed = ETH_SPEED_100M;
    ethConfig.interface = ETH_INTERFACE_MII;
    ETH_Config(ðConfig);

    // 配置DP83825
    ETH_WritePHYRegister(0x00, 0x00, 0x3100); // 设置100Mbps,全双工
    ETH_Start();
}

4.3 MII发送数据的通信过程
      MII的发送过程就像“用四车道大卡车运送货物”。步骤如下:
      1. 准备数据:
         - 应用程序生成数据包,DMA将数据搬到TX缓冲区。
    2. 通知发送:
         - MAC将数据分成4位一组,放到TXD上。
         - 置TX_EN为高,通知DP83825开始发送。
      3. 数据传输:
         - DP83825在TX_CLK的上升沿采样TXD上的4位数据。
         - TX_CLK由DP83825提供,100Mbps时为25MHz。
         - 发送完成后,MAC置TX_EN为低。
    4. PHY处理:
         - DP83825将数据编码为物理信号,发送到网线。


4.4 MII接收数据的通信过程
      MII的接收过程就像“从网线收到货物,用四车道运回”。步骤如下:
    1. PHY接收信号:
         - DP83825从网线接收信号,解码为4位数据。
    2. 通知接收:
         - DP83825置RX_DV为高,表示数据有效。
         - 将4位数据放到RXD上。
      3. 数据传输:
         - MAC在RX_CLK的上升沿采样RXD上的4位数据。
         - RX_CLK由DP83825提供,100Mbps时为25MHz。
    4. 存储数据:
         - DMA将数据搬到RX缓冲区,应用程序读取。


4.5 MII的管理接口(MDC/MDIO)
      与RMII类似,MII也通过MDC和MDIO配置DP83825,过程相同,不再赘述。

5、MII与RMII的对比:LAN8720 vs DP83825
      通过LAN8720和DP83825的通信过程,我们可以总结两者的差异:


特性
LAN8720(RMII)
DP83825(MII)

数据宽度
2位(TXD, RXD)
4位(TXD, RXD)

时钟
单一50MHz REF_CLK
两个时钟(TX_CLK, RX_CLK,25MHz)

信号线数量
9根
18根

引脚需求
少,适合小型封装
多,适合引脚充足的芯片

PCB布线
简单,但REF_CLK需严格阻抗匹配
复杂,信号线多需避免干扰

适用场景
成本敏感、引脚受限的系统
高可靠性、支持半双工的系统


      总结上文,
      - LAN8720(RMII)就像一辆轻便的快递车,跑得快(50MHz),占道少(9根线),适合短途快速送货。
      - DP83825(MII)就像一辆重型卡车,载货多(4位/周期),占道多(18根线),适合长途稳定运输。

6、调试与常见问题
      在实际开发中,RMII和MII通信可能会遇到问题。以下是常见问题和解决办法:
    1. 问题:无法ping通:
         - RMII:检查REF_CLK是否为50MHz,LAN8720的晶振是否正常。
         - MII:检查TX_CLK和RX_CLK是否正确输出(用示波器测量)。
         - 确认PHY地址和寄存器配置是否正确。
      2. 问题:数据包丢失:
         - RMII:检查REF_CLK布线是否过长,添加33Ω串联电阻。
         - MII:确保TXD/RXD信号线等长,减少信号偏差。
    3. 问题:链路未建立:
         - 检查MDC/MDIO时序,确认PHY寄存器是否正确配置。
         - 检查RJ45接口和网线连接。

7、总结
      通过对LAN8720(RMII)和DP83825(MII)的通信过程的详细剖析,我们从硬件连接、初始化、数据收发到时序分析,全面揭开了以太网通信的“神秘面纱”。RMII以其高效和低引脚数的优势,适合成本敏感的嵌入式系统;MII则以高可靠性和全面的功能,适合复杂场景。




页: [1]
查看完整版本: 揭秘以太网通信的幕后故事:RMII(以LAN8720为例)与MII(以DP83825为例)通信全解析