MDIO 接口信号定义:MDC、MDIO 与电气特性

好了,咱们今天聊点实在的。MDIO 总线说白了就两条线:一条时钟,一条数据。你要是搞过 I2C 或 SPI,会发现这玩意儿简单得有点“简陋”。但别小看它,这两条线要是没伺候好,你写再多代码也是白搭。

我记得刚入行那会儿,总觉得这种低速总线没啥好学的。结果呢?板子调了三天,死活读不回 PHY 的 ID。最后拿来示波器一看——MDIO 的上升沿根本没对齐 MDC 的下降沿。所以,我们把这两根线的脾气摸透,比啥都重要。

MDC:管理时钟

MDC 是主设备(通常是 MAC 或 CPU)发给从设备(PHY)的时钟信号。它的作用很简单:给数据采样提供一个时间基准。

几个关键点:

  • 频率范围:IEEE 802.3 标准规定 MDC 最高为 2.5 MHz。但实际项目中,很多 PHY 能跑到 12.5 MHz,甚至更高。我个人的习惯是:除非需要高速轮询,否则老老实实用 2.5 MHz 以下。兼容性最好,省心。
  • 占空比:标准要求 50% ± 10%。说白了,高电平和低电平的时间别差太多。否则 PHY 那边采样容易出错。
  • 空闲状态:MDC 在空闲时必须保持低电平。这一点和很多时钟协议不一样。你想想看,要是空闲时 MDC 乱跳,MDIO 上的数据逻辑就全乱套了。
我的小习惯:设计 PCB 时,MDC 尽量走短走直,别在它旁边跑大电流的信号。虽然它只有几兆赫兹,但边沿太缓也会让 PHY 误判时钟沿。我碰到过一次,就是因为 MDC 走线绕了个大弯,结果上升沿变缓,PHY 在上升沿和下降沿都采到了数据——双倍采样,数据全错。

MDIO:管理数据

MDIO 是双向数据线。主设备用它发读写命令和写数据,从设备用它回复读数据。

方向控制:

  • 主设备驱动 MDIO:发送帧头、操作码、PHY 地址、寄存器地址,以及写数据。
  • 从设备(PHY)驱动 MDIO:回复读数据。注意,PHY 是在 MDC 的下降沿切换数据,主设备在上升沿采样。
  • 空闲状态:MDIO 必须保持高阻(高电平)。原因我后面讲电气特性时会细说。

这里有一个很容易踩的坑:我没见过哪个新手手册会告诉你,MDIO 的方向切换是有死区时间的。写操作结束时,主设备必须释放总线;而 PHY 需要几个 MDC 周期才能开始驱动。如果你没留够这个切换时间,双方就会“打架”——一个还在拉高,另一个想拉低,最后读回来的数据全是 0x00。

曾经我翻过的一个跟头:我用 GPIO 模拟 MDIO 时序,为了省代码,写操作结束后紧接着就切到输入去读 PHY 的回复。结果 PHY 那边还没准备好驱动总线,我自己又没加内部上拉,MDIO 浮空了。读回来的数据一会儿全 1,一会儿全 0。折腾了两天才发现是方向切换太快,加了个 1 μs 的延时就好了。

电气特性:把两根线说得明明白白

MDIO 总线的电气特性,核心就两件事:驱动能力和终端匹配。

驱动类型:漏极开路 / 推挽

特性 传统方式(漏极开路) 常见现代方式(推挽 + 三态)
高电平驱动 依靠上拉电阻 主动拉高
低电平驱动 主动拉低 主动拉低
空闲状态 高阻(电阻上拉为高电平) 高阻(通常片内上拉)
上拉电阻 必须外接,1.5kΩ – 10kΩ 可选,部分 PHY 内置
总线最大长度 受上拉电阻和电容限制,通常 < 7 cm 稍好一些,但也不建议太长

我个人建议:无论用什么方式驱动,MDIO 都要接一个上拉电阻到 3.3V 或 1.8V。为什么呢?因为 MDIO 总线是多从设备共享的。如果一个 PHY 出了故障,把 MDIO 拉死了,上拉电阻至少还能把总线“救”回高电平,让其他设备能继续通信。

上拉电阻怎么选?

  • 阻值太小(< 1kΩ):驱动电流大,信号边沿陡,但功耗高。而且 PHY 在拉低时,电流太大会导致输出级发热甚至损坏。
  • 阻值太大(> 10kΩ):省电,但上升沿变缓。总线电容一大(比如挂了多个 PHY),波形就不行了。
  • 我的经验值:2kΩ – 4.7kΩ 通常是个安全范围。挂 1 个 PHY 用 4.7kΩ,挂 4 个以上用 2.2kΩ。具体还得算一下总线电容。

电气参数速查表

参数 最小值 典型值 最大值 备注
MDC 频率 – 2.5 MHz 12.5 MHz 非标,需 PHY 支持
MDC 占空比 40% 50% 60% 低速时可放宽
MDIO 上拉电阻 1.5 kΩ 4.7 kΩ 10 kΩ 根据总线电容调整
输入高电平 2.0 V – – CMOS 阈值
输入低电平 – – 0.8 V CMOS 阈值
总线电容 – – 50 pF 全部 PHY 及走线的总电容
避坑总结:

我曾经在一个项目里,把 5 个 PHY 挂在同一条 MDIO 总线上。按照数据手册算了一下,总电容大概 30 pF。但我用了 10 kΩ 的上拉电阻,结果 MDC 跑到 12.5 MHz 时,MDIO 的上升沿几乎是正弦波了,采样点在抖动,根本无法稳定通信。后来换成 2.2 kΩ 的电阻,波形才恢复正常。

总线拓扑:主从结构

MDIO 总线是典型的主从结构。一个主设备(通常是 MAC 控制器或 CPU 的 GPIO 模拟)可以管理最多 32 个从设备(PHY)。每个 PHY 有 5 位地址,从 0x00 到 0x1F。注意,地址 0x00 通常是广播地址,用来同时配置所有 PHY。但我不建议你用广播写——你想想看,万一其中一个 PHY 没响应,你又不知道是哪个,排查起来太痛苦了。

MDIO 管理接口:主从结构 主设备(MAC / CPU) MDC MDIO R 上拉电阻 PHY 1(地址 0x01) PHY 2(地址 0x02) PHY n(地址 0x0n) 说明: • 主设备通过 MDC 提供时钟,通过 MDIO 发送地址和命令。 • 所有从设备共享 MDC 和 MDIO,但只有地址匹配的那个 PHY 才会响应。 • 上拉电阻保证空闲时 MDIO 为高电平,避免总线浮动。

这图你看一眼就明白了。主设备在上方,通过 MDC 和 MDIO 跟下面的多个 PHY 通信。上拉电阻 R 挂在总线上,保证空闲时 MDIO 被拉到高电平。我特意把地址写进去了——你分配 PHY 地址时一定要小心,千万别冲突。有一次我把两个 PHY 都设成了 0x04,结果每次读寄存器,两个 PHY 同时在总线上回复,数据完全乱掉。

电气特性的实操建议

  1. PCB 走线:MDC 和 MDIO 尽量走在一起,长度差不超过 5 cm。别让 MDC 绕了半块板子,MDIO 就在旁边直接拉过去——那样时钟和数据到达每个 PHY 的时间差太多,高速下会出错。
  2. 上拉电阻位置:如果总线上挂了多个 PHY,上拉电阻应该靠近主设备放置,或者放在总线的中间位置。不要放在最远端,否则近端的 PHY 驱动时会感觉总线“太硬”。
  3. 电平转换:如果主设备是 1.8V 的,而 PHY 是 3.3V 的,必须加电平转换芯片。别想着用电阻分压糊弄过去——MDIO 是双向的,分压会影响高电平的识别,而且从设备拉低时,主设备那边可能读不到低电平。
  4. 调试三板斧:遇到 MDIO 通信不上,我通常按这个顺序查:① 示波器看 MDC 有没有时钟;② 看 MDIO 空闲状态是不是高电平;③ 写一个 PHY ID 读操作,抓波形看地址和数据段有没有对齐。这三步走完,90% 的问题都能定位。
一个真实的教训:有一回客户说他们的板子冷启动时偶尔读不到 PHY,热启动就正常。我分析了两天,发现是 MDC 的上电时序问题:主设备先上电,但 PHY 还没准备好,MDC 就开始跑了。PHY 在复位期间收到了几个不完全的时钟边沿,状态机就乱了。解决办法是在主设备软件里做延迟,等 PHY 稳定后再拉 MDC。从那以后,我所有项目的上电时序都会留至少 10 ms 的等待窗口。