1. 以太网通信基础与协议选择
以太网通信作为现代网络技术的基石,其底层硬件接口协议的选择直接影响着设备性能和成本。在实际嵌入式开发中,RMII(Reduced Media Independent Interface)和MII(Media Independent Interface)是两种最常见的物理层接口标准。
MII作为经典接口,采用4位数据总线,时钟频率25MHz,理论带宽100Mbps。我在早期项目中使用的DP83825 PHY芯片就是典型代表,它的优势在于信号完整性好,布线相对简单,但需要16个引脚(TXD[3:0], RXD[3:0], TX_CLK, RX_CLK, TX_EN, RX_DV, CRS, COL)。记得第一次布线时,我按照教科书上的推荐使用了50欧姆阻抗匹配,结果发现实际传输距离超过1米时误码率明显上升。后来通过示波器测量才发现,PCB板材的介电常数与理论值存在偏差,调整到47欧姆后才稳定下来。
RMII则是精简版本,数据总线缩减到2位,时钟频率提升到50MHz。LAN8720这类芯片通过减少引脚数(仅需7个信号线:TXD[1:0], RXD[1:0], REF_CLK, CRS_DV, TX_EN)大幅降低成本。去年设计的一款工业控制器中,我们通过RMII节省了34%的PCB面积,但随之而来的是时序约束更严格。有次批量生产时,部分设备出现间歇性丢包,最后发现是REF_CLK的走线长度差异导致——RMII要求所有信号线长度差必须控制在±5mm以内,而MII可以放宽到±15mm。
关键经验:选择接口类型时,除了考虑引脚数量,更要评估PCB布局能力和时钟精度。消费类产品优先RMII,工业级长距离传输建议MII。
2. 硬件设计实战要点
2.1 原理图设计陷阱
以STM32F407+LAN8720的RMII设计为例,最常见的坑是忽视nINT/REFCLK引脚配置。LAN8720的nINT/REFCLK引脚默认为中断输出,必须通过下拉电阻设置为50MHz时钟输出模式。有次我忘记接这个10kΩ电阻,导致整个系统无法同步,花了三天才定位问题。
另一个易错点是电压匹配。DP83825的IO口电压是3.3V,但某些老款MCU的MII接口可能是2.5V电平。曾遇到过一个案例,工程师直接连接导致信号幅度不足,最后不得不增加电平转换芯片SN74LVC8T245。
2.2 PCB布局黄金法则
-
时钟线优先:REF_CLK走线必须最短(RMII要求<25mm),且远离高频信号。我习惯用嘉立创的4层板,将时钟线布置在中间层,上下用地平面屏蔽。
-
阻抗控制:差分对(如TXD±)需保持100Ω阻抗。有个项目因为没做阻抗匹配,100Mbps速率下误码率达到10^-5,后来改用Si9000计算后调整线宽/间距才达标。
-
去耦电容布局:每个电源引脚必须就近放置0.1μF电容。实测显示,距离超过3mm会导致LAN8720的纹波增加60mV。
3. 驱动开发关键代码解析
3.1 PHY寄存器配置
无论是MII还是RMII,上电后都必须初始化PHY寄存器。以LAN8720为例,这几个寄存器必须配置:
c复制// 设置自动协商
void PHY_Init(void) {
uint16_t reg;
// 复位PHY
HAL_ETH_WritePHYRegister(&heth, PHY_REG_BCR, PHY_RESET);
do {
HAL_ETH_ReadPHYRegister(&heth, PHY_REG_BCR, ®);
} while (reg & PHY_RESET);
// 启用自动协商
HAL_ETH_WritePHYRegister(&heth, PHY_REG_BCR, PHY_AUTONEGOTIATION);
// 设置RMII模式
HAL_ETH_WritePHYRegister(&heth, PHY_REG_SPECIAL, PHY_RMII_MODE);
}
调试时最容易忽略的是PHY地址问题。DP83825的默认地址是0x01,而LAN8720是0x00。有次移植代码时没改地址,导致读取的链路状态永远为down。
3.2 中断处理优化
好的驱动应该实现链路状态中断检测,而不是轮询。以下是实战中总结的中断服务例程模板:
c复制void ETH_IRQHandler(void) {
uint16_t phyReg;
// 读取中断状态寄存器
HAL_ETH_ReadPHYRegister(&heth, PHY_REG_ISR, &phyReg);
if (phyReg & PHY_LINK_STATUS_MASK) {
uint16_t speed;
HAL_ETH_ReadPHYRegister(&heth, PHY_REG_STATUS, &speed);
if (speed & PHY_SPEED_100M)
printf("100Mbps连接建立\n");
else
printf("10Mbps连接建立\n");
}
// 清除中断标志
HAL_ETH_WritePHYRegister(&heth, PHY_REG_ISR, phyReg);
}
4. 调试技巧与故障树
4.1 硬件诊断三板斧
-
电源检测:先测3.3V和1.2V(LAN8720内核电压)是否稳定。有次发现PHY频繁复位,最终是LDO输出电容ESR过大导致。
-
时钟测量:用示波器检查REF_CLK的50MHz方波(RMII)或25MHz(MII)。注意观察上升时间应<3ns,幅值误差<5%。
-
信号完整性:触发模式设为单次捕获,观察TXD[0]的第一个数据包。正常波形应该像下图所示:
code复制理想RMII信号波形:
___ ___ ___
TXD0 | |___| |___| |___
2ns 1ns 2ns 1ns 2ns
4.2 典型故障案例
案例1:能ping通但TCP吞吐量低
- 检查:ifconfig查看RX errors计数
- 根因:MAC层DMA缓冲区太小
- 解决:调整ETH_RX_BUF_SIZE到1524字节以上
案例2:连接时断时续
- 检查:phy寄存器1的LINK状态位
- 根因:变压器中心抽头未接合适偏置电压
- 解决:在RJ45的CT脚接0.1μF电容到地
案例3:只能10Mbps工作
- 检查:phy寄存器17的自动协商结果
- 根因:网线质量差导致协商降速
- 解决:更换CAT5e以上规格网线
5. 性能优化进阶技巧
5.1 零拷贝DMA优化
传统网络驱动需要CPU参与数据搬运,而现代MCU如STM32H7支持Descriptor链式DMA。这是我优化后的缓冲区描述符初始化代码:
c复制void ETH_DMA_Config(void) {
// 发送描述符
DMATxDscrTab[0].Buffer = Tx_Buff;
DMATxDscrTab[0].ControlBufferSize = ETH_TX_BUF_SIZE | DMA_TX_DESC_IC;
DMATxDscrTab[0].Status = DMA_TX_DESC_OWN;
// 接收描述符(环形队列)
for(int i=0; i<ETH_RX_DESC_CNT; i++) {
DMARxDscrTab[i].Buffer = Rx_Buff[i];
DMARxDscrTab[i].ControlBufferSize = ETH_RX_BUF_SIZE | DMA_RX_DESC_IC;
DMARxDscrTab[i].Status = DMA_RX_DESC_OWN;
}
// 注册到MAC
HAL_ETH_DMATxDescListInit(&heth, DMATxDscrTab, Tx_Buff, ETH_TX_DESC_CNT);
HAL_ETH_DMARxDescListInit(&heth, DMARxDscrTab, Rx_Buff, ETH_RX_DESC_CNT);
}
实测表明,启用DMA后CPU负载从35%降至8%,适合视频流传输场景。
5.2 低功耗设计
对于电池供电设备,PHY的节能模式至关重要。LAN8720的节能配置步骤如下:
- 写寄存器31选择page 0
- 写寄存器0启用自动协商
- 写寄存器16 bit[13]启用EEE模式
- 写寄存器31选择page 3
- 写寄存器16配置LPI时序
实测功耗对比:
| 模式 | 100Mbps功耗 | 10Mbps功耗 |
|---|---|---|
| 正常模式 | 120mW | 65mW |
| EEE模式 | 85mW | 40mW |
6. 生产测试方案
6.1 自动化测试脚本
批量生产时需要快速验证PHY功能,我开发了基于Python的测试工具:
python复制import pyvisa
class PHYTester:
def __init__(self):
self.rm = pyvisa.ResourceManager()
self.scope = self.rm.open_resource('TCPIP::192.168.1.100::INSTR')
def test_link(self):
# 发送测试脉冲
self.scope.write("WGEN:OUTP ON")
time.sleep(1)
# 检测RX数据
err = self.scope.query("MEASURE:EYE:BER?")
return float(err) < 1e-8
6.2 关键测试项
- 链路自协商测试:强制设置10/100Mbps模式各测试5分钟
- 环回测试:启用PHY内部环回,发送10^6个包检查误码
- 压力测试:用iperf3持续传输30分钟,监控温度变化
测试指标合格范围:
- 丢包率:<0.001%
- 延迟抖动:<50μs
- 工作温度:-40℃~85℃范围内功能正常
7. 替代方案选型指南
当主流芯片缺货时,这些替代型号经过实测可用:
| 原型号 | 替代型号 | 差异点 |
|---|---|---|
| LAN8720 | KSZ8081 | 需要修改复位电路 |
| DP83825 | RTL8201F | 不支持EEE节能模式 |
| LAN8742A | 内置稳压器,布线更简单 |
选型时特别注意三点:
- 封装兼容性:QFN24和SOP8焊盘不兼容
- 参考时钟需求:有些PHY需要外部25MHz晶振
- 变压器集成度:带变压器的型号如LAN8720Ai可省去网络变压器