第二讲:物理层与数据链路层——以太网帧结构、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,初始化流程都差不多:
- 复位PHY(拉低RST引脚,保持至少1ms)
- 配置PHY地址(通过ADDR引脚设置,通常是0或1)
- 读取PHY ID寄存器(确认芯片型号)
- 配置基本控制寄存器(自动协商、速度、双工模式)
- 等待Link Up(检查状态寄存器)
- 配置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驱动的关键点:
- 复位时序:拉低RST至少1ms,然后释放。释放后等待至少5ms再操作寄存器。
- 自动协商:默认开启,但建议手动配置速度/双工模式,避免协商失败。
- 中断处理:LAN8720支持Link Up/Down中断,可以用来检测网线插拔。
- 功耗管理:不使用时可以进入省电模式,电流从150mW降到几十微瓦。
小技巧:调试PHY时,先读寄存器0(基本控制寄存器)和寄存器1(基本状态寄存器)。如果读出来全是0xFFFF,说明SMI通信有问题。如果读出来是0x3100,说明PHY正常工作。
好了,这一讲就到这里。物理层和数据链路层是网络通信的基石,看似简单,但坑不少。下一讲我们聊聊ARP协议和IP协议,看看数据怎么从二层走到三层。
记住:搞嵌入式网络,底层协议搞不懂,上层应用再花哨也是空中楼阁。