第二讲:物理层与数据链路层——以太网帧结构、MAC地址、PHY芯片驱动(LAN8720/DP83848)、RMII/MII接口

各位同学,咱们今天聊点实在的。

嵌入式网络开发,说白了就是让单片机学会“说话”。但怎么说得清楚、听得明白?这就要靠物理层和数据链路层来打底了。我当年刚入行时,总觉得这些底层协议离应用层太远,直到被一个丢包问题折磨了三天三夜……嗯,从那以后,我再也不敢小看这两层了。

一、以太网帧结构:数据在线上怎么跑?

先看一个最基础的问题:数据在网线上是怎么组织的?

以太网帧,就是数据在物理介质上传输的基本单位。你想想看,就像寄快递,你得有包裹、有地址、有校验码,缺一不可。

标准以太网帧(IEEE 802.3)结构如下:

| 前导码(7B) | 帧起始定界符(1B) | 目标MAC(6B) | 源MAC(6B) | 长度/类型(2B) | 数据(46-1500B) | FCS(4B) |

我来拆开讲讲:

  • 前导码(7字节):一串101010...的交替码,用来让接收端同步时钟。说白了就是“喂,我要发数据了,你准备好!”
  • 帧起始定界符(1字节):最后两位是11,表示“数据要来了,注意接收”。
  • 目标MAC和源MAC(各6字节):这个后面细说。
  • 长度/类型(2字节):如果值小于1536(0x0600),表示数据长度;大于等于1536,表示上层协议类型(比如0x0800是IP)。
  • 数据(46-1500字节):实际载荷。注意,最少46字节,不够要填充。为什么?因为要保证帧长至少64字节,防止冲突检测出问题。
  • FCS(4字节):CRC32校验。我在项目中遇到过,有一次FCS计算错误,导致整个网络丢包率高达30%。查了半天,结果是DMA配置错了,数据没对齐。

小提示:实际抓包时,前导码和SFD是物理层处理的,软件层看不到。你看到的第一个字段就是目标MAC地址。

二、MAC地址:设备的身份证

MAC地址,全称Media Access Control Address。每个网卡出厂时都有一个全球唯一的48位地址。前24位是厂商代码(OUI),后24位是厂商分配的序列号。

举个例子:00:1A:2B:3C:4D:5E,前三个字节00:1A:2B代表厂商(比如Microchip),后三个字节是设备唯一标识。

我曾经踩过一个坑:在一个产品中,我用了软件随机生成MAC地址,结果同一局域网内两台设备MAC冲突,导致网络时断时续。排查了整整两天……后来我老老实实从芯片OTP里读取唯一ID来生成MAC,再也没出过问题。

注意:MAC地址是二层地址,只在同一个广播域内有效。跨网段通信要靠IP地址(三层)。别搞混了。

三、PHY芯片驱动:LAN8720 vs DP83848

PHY芯片,就是物理层收发器。它负责把数字信号变成模拟信号,再通过网线发出去。反过来也一样。

市面上常见的PHY芯片有LAN8720(Microchip)和DP83848(TI)。我两个都用过,说说区别:

特性 LAN8720 DP83848
接口 RMII(仅支持) MII/RMII(可选)
工作电压 3.3V(I/O) 3.3V(I/O),内核1.8V
功耗 较低(约150mW) 较高(约300mW)
价格 便宜(约2-3元) 稍贵(约5-8元)
稳定性 一般(对PCB布局敏感) 较好(工业级常用)

我个人习惯,如果项目成本敏感、对稳定性要求不高,选LAN8720。如果是工业控制、车载等场景,我建议用DP83848,抗干扰能力强很多。

3.1 PHY芯片初始化流程

不管用哪款PHY,初始化流程都差不多:

  1. 复位PHY(拉低RST引脚,保持至少1ms)
  2. 配置PHY地址(通过ADDR引脚设置,通常是0或1)
  3. 读取PHY ID寄存器(确认芯片型号)
  4. 配置基本控制寄存器(自动协商、速度、双工模式)
  5. 等待Link Up(检查状态寄存器)
  6. 配置MAC与PHY之间的接口(MII/RMII)

代码示例:读取PHY ID(以LAN8720为例)

// 通过SMI/MDIO接口读取PHY寄存器
uint32_t phy_read_id(uint8_t phy_addr) {
    uint16_t id1, id2;
    
    // 读取寄存器2(PHY ID高16位)
    id1 = smi_read(phy_addr, 2);
    // 读取寄存器3(PHY ID低16位)
    id2 = smi_read(phy_addr, 3);
    
    return ((uint32_t)id1 << 16) | id2;
}

// LAN8720的ID应为0x0007C0F0
// DP83848的ID应为0x20005C90

四、RMII vs MII接口:怎么连?

MAC和PHY之间怎么通信?靠MII或RMII接口。

MII(Media Independent Interface):

  • 数据线:4位并行(TX/RX各4位)
  • 时钟:25MHz(100Mbps)或2.5MHz(10Mbps)
  • 引脚数:约16根
  • 优点:兼容性好,时序宽松
  • 缺点:占用引脚多

RMII(Reduced MII):

  • 数据线:2位并行(TX/RX各2位)
  • 时钟:50MHz(固定,不分速率)
  • 引脚数:约9根
  • 优点:引脚少,适合小封装MCU
  • 缺点:需要外部50MHz时钟源

我建议,如果你的MCU引脚够用,用MII更稳定。如果引脚紧张,比如STM32F103C8T6这种48脚芯片,RMII是唯一选择。

避坑指南:我曾经在一个项目里,RMII的REF_CLK没处理好,导致PHY和MAC时钟不同步,数据全错。后来发现,REF_CLK必须由外部晶振提供,不能从MCU输出。因为MCU的时钟抖动太大,PHY受不了。

五、实战:LAN8720驱动要点

最后,我分享几个LAN8720驱动的关键点:

  1. 复位时序:拉低RST至少1ms,然后释放。释放后等待至少5ms再操作寄存器。
  2. 自动协商:默认开启,但建议手动配置速度/双工模式,避免协商失败。
  3. 中断处理:LAN8720支持Link Up/Down中断,可以用来检测网线插拔。
  4. 功耗管理:不使用时可以进入省电模式,电流从150mW降到几十微瓦。

小技巧:调试PHY时,先读寄存器0(基本控制寄存器)和寄存器1(基本状态寄存器)。如果读出来全是0xFFFF,说明SMI通信有问题。如果读出来是0x3100,说明PHY正常工作。

好了,这一讲就到这里。物理层和数据链路层是网络通信的基石,看似简单,但坑不少。下一讲我们聊聊ARP协议和IP协议,看看数据怎么从二层走到三层。

记住:搞嵌入式网络,底层协议搞不懂,上层应用再花哨也是空中楼阁。