HDMI协议基础:从TMDS到EDID,一个工程师的实战笔记
各位同学,今天我们来聊聊HDMI。说实话,HDMI这玩意儿看着简单,不就是一根线连显示器吗?但真要在FPGA上把它实现出来,坑可不少。我当年第一次调HDMI输出时,画面全是雪花,折腾了两天才发现是TMDS时序差了几个纳秒。嗯,咱们今天就把这些基础打扎实。
TMDS编码原理:为什么需要它?
TMDS,全称是Transition Minimized Differential Signaling。翻译过来就是「最小化转换差分信号」。名字挺长,但核心思想很简单:减少信号跳变,降低电磁干扰。
你想想看,如果原始数据是连续的0和1交替,比如01010101,那信号线每传输一个bit就要跳变一次。高频跳变会产生大量EMI,而且接收端也容易误判。TMDS编码就是来解决这个问题的。
具体怎么做的?它把8bit数据编码成10bit。这10bit里,保证跳变次数最少,同时直流平衡(DC平衡)。直流平衡是什么意思?就是传输的0和1数量尽量相等,这样信号的平均电压稳定,接收端不容易漂移。
核心要点:TMDS编码后,10bit数据中最多只有5次跳变,最少可以做到0次跳变。同时,编码器会记录当前「不平衡度」,动态调整编码方向。
我在项目中遇到过一个问题:用逻辑分析仪抓TMDS信号,发现某些像素点总是错位。后来排查发现,是编码器在DC平衡计算时,没有考虑复位后的初始状态。说白了,就是状态机没初始化好。
差分信号与电气特性
HDMI用的是差分信号传输。什么是差分?就是一对线,一根传正信号,一根传反信号。接收端看的是两根线的电压差。
这样做的好处很明显:
- 抗共模干扰:外部噪声同时影响两根线,但差值不变
- 低电压摆幅:差分信号只需要几百毫伏的摆幅,功耗低
- 高速传输:可以跑到几Gbps
HDMI的电气特性,我简单列几个关键参数:
| 参数 | 典型值 | 说明 |
|---|---|---|
| 差分电压 | 400mV ~ 600mV | 峰峰值,取决于TMDS电流源 |
| 共模电压 | 3.3V | 以GND为参考 |
| 阻抗 | 100Ω ± 15% | 差分阻抗,PCB走线要匹配 |
| 上升时间 | < 0.3 UI | UI = 单位间隔,即一个bit的时间 |
注意:我曾经在PCB布局时,把差分对的两根线走了不同长度,结果信号质量一塌糊涂。差分对必须等长,误差控制在5mil以内。这是血的教训。
HDMI 1.4 vs 2.0 对比
很多同学问我,到底该用1.4还是2.0?我的建议是:看你的分辨率和刷新率需求。
直接上对比表:
| 特性 | HDMI 1.4 | HDMI 2.0 |
|---|---|---|
| 最大带宽 | 10.2 Gbps | 18 Gbps |
| 最大分辨率 | 4K@30Hz | 4K@60Hz |
| TMDS时钟 | 最高340 MHz | 最高600 MHz |
| 色彩深度 | 8bit/10bit | 8bit/10bit/12bit |
| HDR支持 | 有限 | 完整支持 |
说白了,如果你只是做1080p@60Hz的显示,HDMI 1.4完全够用。但要做4K@60Hz,必须上2.0。我有个项目,客户非要1.4跑4K@60Hz,结果画面闪烁得跟迪斯科一样。嗯,物理定律是绕不过去的。
像素时钟与分辨率关系
这个知识点,我建议你死记硬背也要记住:像素时钟 = 水平总像素 × 垂直总行数 × 刷新率
举个例子,1080p@60Hz:
- 水平总像素:2200(包含消隐区)
- 垂直总行数:1125(包含消隐区)
- 刷新率:60 Hz
- 像素时钟 = 2200 × 1125 × 60 ≈ 148.5 MHz
为什么总像素和总行数比有效像素多?因为有消隐区(blanking)。消隐区是干嘛的?说白了,就是给显示器一个喘息的时间,让它从一行末尾回到下一行开头。
小技巧:我在FPGA里生成像素时钟时,通常用PLL锁相环。但要注意,PLL的输入时钟和输出时钟要算好倍数关系。比如输入50MHz,要得到148.5MHz,倍频系数是2.97,不是整数。这时候我会用两个PLL级联,或者用MMCM(混合模式时钟管理器)。
常见的分辨率与像素时钟对应关系:
| 分辨率 | 刷新率 | 像素时钟 |
|---|---|---|
| 640×480 | 60 Hz | 25.175 MHz |
| 1280×720 | 60 Hz | 74.25 MHz |
| 1920×1080 | 60 Hz | 148.5 MHz |
| 3840×2160 | 60 Hz | 594 MHz |
EDID与DDC通道解析
EDID,全称Extended Display Identification Data。说白了,就是显示器的「身份证」。里面存着显示器支持的分辨率、刷新率、色彩格式等信息。
DDC通道是I2C总线,用来读取EDID。HDMI规范里,DDC的I2C地址是0xA0(写)和0xA1(读)。EDID数据总共128字节,存储在显示器的EEPROM里。
我当年调试EDID时,遇到一个奇葩问题:显示器明明支持1080p,但FPGA读到的EDID里却没有这个分辨率。后来发现,是显示器的EDID版本太老,只写了720p的信息。解决办法是手动在FPGA里写一个「虚拟EDID」,覆盖掉显示器的数据。
实战要点:EDID的前128字节是强制标准,后128字节是扩展块。读取时,先读前128字节,如果支持扩展,再读后128字节。扩展块里通常包含更详细的信息,比如音频格式、3D支持等。
DDC通道的时序,就是标准的I2C协议。速率一般是100kHz,但有些显示器支持400kHz。我建议你按100kHz来设计,兼容性最好。
知识体系总览
下面这张图,是我自己画的HDMI协议知识体系。你可以把它当作学习地图:
这张图把今天讲的内容串起来了。你看,TMDS编码是底层传输机制,差分信号是物理层实现,版本对比告诉你选型依据,像素时钟是时序核心,EDID/DDC是握手协议。最后,所有知识都要落到FPGA实现上。
好了,今天的内容就到这里。记住,HDMI协议看着复杂,但拆开来看,每个模块都不难。关键是动手实践,调一次波形,比看十遍书都管用。
可可精品资料库