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 上的数据逻辑就全乱套了。
MDIO:管理数据
MDIO 是双向数据线。主设备用它发读写命令和写数据,从设备用它回复读数据。
方向控制:
- 主设备驱动 MDIO:发送帧头、操作码、PHY 地址、寄存器地址,以及写数据。
- 从设备(PHY)驱动 MDIO:回复读数据。注意,PHY 是在 MDC 的下降沿切换数据,主设备在上升沿采样。
- 空闲状态:MDIO 必须保持高阻(高电平)。原因我后面讲电气特性时会细说。
这里有一个很容易踩的坑:我没见过哪个新手手册会告诉你,MDIO 的方向切换是有死区时间的。写操作结束时,主设备必须释放总线;而 PHY 需要几个 MDC 周期才能开始驱动。如果你没留够这个切换时间,双方就会“打架”——一个还在拉高,另一个想拉低,最后读回来的数据全是 0x00。
电气特性:把两根线说得明明白白
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 没响应,你又不知道是哪个,排查起来太痛苦了。
这图你看一眼就明白了。主设备在上方,通过 MDC 和 MDIO 跟下面的多个 PHY 通信。上拉电阻 R 挂在总线上,保证空闲时 MDIO 被拉到高电平。我特意把地址写进去了——你分配 PHY 地址时一定要小心,千万别冲突。有一次我把两个 PHY 都设成了 0x04,结果每次读寄存器,两个 PHY 同时在总线上回复,数据完全乱掉。
电气特性的实操建议
- PCB 走线:MDC 和 MDIO 尽量走在一起,长度差不超过 5 cm。别让 MDC 绕了半块板子,MDIO 就在旁边直接拉过去——那样时钟和数据到达每个 PHY 的时间差太多,高速下会出错。
- 上拉电阻位置:如果总线上挂了多个 PHY,上拉电阻应该靠近主设备放置,或者放在总线的中间位置。不要放在最远端,否则近端的 PHY 驱动时会感觉总线“太硬”。
- 电平转换:如果主设备是 1.8V 的,而 PHY 是 3.3V 的,必须加电平转换芯片。别想着用电阻分压糊弄过去——MDIO 是双向的,分压会影响高电平的识别,而且从设备拉低时,主设备那边可能读不到低电平。
- 调试三板斧:遇到 MDIO 通信不上,我通常按这个顺序查:① 示波器看 MDC 有没有时钟;② 看 MDIO 空闲状态是不是高电平;③ 写一个 PHY ID 读操作,抓波形看地址和数据段有没有对齐。这三步走完,90% 的问题都能定位。