
HDMI 这玩意儿现在满大街都是电视、显示器、机顶盒、笔记本、游戏机甚至树莓派和 FPGA 开发板上都标配。但真要问一句“HDMI 到底是怎么把画面和声音从一根线送过去的”能说清楚的人并不多。我当初调 FPGA 的 HDMI 输出时对着示波器看那几对差分线一开始也是一头雾水——为什么是四对为什么视频三对、时钟一对音频又是怎么塞进去的后来把协议啃了一遍又用逻辑分析仪抓了 TMDS 波形才算把整条链路串起来。这篇就把我踩过的坑和理清的思路完整写出来从物理层的差分信号到 TMDS 编码再到音频 PCM 打包、RGB 与 YUV 两种色彩格式的取舍尽量讲透。适合做嵌入式视频输出、FPGA 图像处理、显示器驱动或者单纯想搞懂 HDMI 接口信号定义的朋友。1. HDMI 整体架构与设计思路拆解1.1 为什么 HDMI 要用四对差分线先把最直观的问题说清楚一根 HDMI 线里面真正跑高速数据的就四对差分线外加几根低速的控制线。四对里面三对叫 TMDS Data0/1/2一对叫 TMDS Clock。很多人第一次看到会问视频不是 RGB 三个分量吗那三对数据线是不是刚好对应 R、G、B答案是对但又不完全对——这是理解 HDMI 的第一个关键点。在 HDMI 1.4 及更早的版本里三对数据线在“视频数据周期”内确实承载像素的三个分量但具体哪个分量走哪对线是由编码和通道映射决定的并不是物理上焊死 R 对 Data0。更准确的说法是TMDS 把每个像素的三个 8 位分量不管是 RGB 还是 YCbCr分别送到三个通道每个通道独立做 8b/10b 编码后串行差分发送。时钟通道则发送像素时钟的 TMDS 版本接收端用它来恢复采样时序。那为什么非要差分因为 HDMI 的像素时钟可以跑到几百 MHzTMDS 串行速率是像素时钟的 10 倍1080p60 时大约 1.485 Gbps 每通道4K 更高。这么高的速率单端信号抗干扰能力差、EMI 大、地弹严重。差分信号用两根线传一个相反的信号接收端做差共模噪声被抵消同时差分对的电流方向相反辐射也相互抵消。这是高速接口的通用做法不是 HDMI 独创但 HDMI 把它用到了消费级线缆上成本压得很低。注意差分对的阻抗必须控制在 100 欧姆差分单端对地约 50 欧姆。PCB 走线时如果阻抗不连续眼图会明显变差表现为高分辨率下花屏或间歇黑屏。我见过不少自制板子 1080p 能亮、4K 就闪八成是走线阻抗或等长没做好。1.2 TMDS 编码到底解决了什么问题TMDS 全称 Transition Minimized Differential Signaling翻译过来叫“最小化传输差分信号”。名字里就藏着它的核心目标减少信号跳变。为什么要减少跳变因为跳变越多高频成分越丰富EMI 越大同时接收端恢复时钟越困难。TMDS 用的是 8b/10b 编码的一种变体。每 8 位数据经过编码变成 10 位多出来的 2 位是开销用来做直流平衡和跳变最小化。直流平衡的意思是长时间看发送的 0 和 1 数量要基本相等这样线路上的平均电压稳定接收端的耦合电容不会积累电荷导致基线漂移。跳变最小化则是通过选择编码方式让相邻位之间翻转次数尽量少。具体编码过程分两步第一步把 8 位数据根据跳变情况映射成 9 位其中第 9 位表示这次映射是否做了反转第二步根据当前的直流平衡状态running disparity决定是否把 9 位整体取反并输出第 10 位作为标志。这样接收端就能逆向还原。整个过程是纯组合逻辑延迟固定非常适合 FPGA 或专用芯片实现。我当初用 FPGA 手写 TMDS 编码器时最开始的版本没做直流平衡结果短线上能跑换根长线就挂。后来老老实实按规范实现 running disparity问题立刻消失。这说明 TMDS 的这两个机制不是可选项是必须项。1.3 视频、音频、控制信息是怎么共用一根线的HDMI 的巧妙之处在于它把视频、音频、辅助信息全部复用到同样的三对数据线上靠“周期”来区分。一个完整的传输周期分为三个阶段视频数据周期Video Data Period、数据岛周期Data Island Period、控制周期Control Period。视频数据周期里三对线传的是像素数据就是前面说的 RGB 或 YUV 分量。数据岛周期里三对线传的是音频包和辅助信息包比如音频采样、InfoFrame、EDID 读取相关的信息。控制周期则传一些短的控制码比如行同步、场同步的前导码。接收端怎么知道当前是哪个周期靠的是控制周期里发送的前导码preamble。前导码是几个特定的 10 位码字接收端检测到它们就知道下一个周期是什么类型。这就像快递分拣先看面单上的标记再决定往哪个格口放。这种时分复用的设计好处是线少、成本低坏处是协议复杂时序要求严格。音频不是独立通道而是“插空”塞进视频的消隐期里所以音频的采样率、位深和视频时序是耦合的。这也是为什么改视频时序有时会影响音频输出的原因。2. 核心细节解析与实操要点2.1 三对差分信号与通道映射的细节前面说三对数据线传三个分量但具体映射关系在 HDMI 规范里有明确定义。对于 RGB 格式通常 Data0 传 BData1 传 GData2 传 R注意顺序不是 RGB 而是 BGR 的通道顺序这是历史原因。对于 YCbCr 4:4:4Data0 传 CbData1 传 YData2 传 Cr。对于 YCbCr 4:2:2情况又不同因为色度分量采样率减半需要特殊的打包方式。这个映射不是随便定的它和 TMDS 编码器的输入顺序、接收端的解码顺序必须严格一致。如果你自己写 FPGA 发送端通道映射搞错画面颜色就会不对比如红蓝互换。我调试时就遇到过 R 和 B 反了人脸变成蓝色一开始还以为是摄像头问题后来查通道映射才发现是 Data0/Data2 接反。实操中PCB 布线要保证三对数据线之间等长偏差一般控制在几个 mil 以内时钟对和数据对之间的偏差也要控制。等长的目的是让三个分量同时到达接收端否则采样时某个分量还是上一个像素的值会出现颜色拖影。高速设计里等长不是可选项是硬性要求。提示如果你用现成的 HDMI 发送芯片通道映射通常由芯片内部固定或通过寄存器配置查数据手册即可。如果是 FPGA 直接驱动务必对照规范确认映射别想当然。2.2 音频 PCM 打包与采样率的那些事HDMI 音频走的是 PCM脉冲编码调制无压缩传输这一点和 S/PDIF 类似但打包方式不同。PCM 简单说就是把模拟声音每隔固定时间采一次样量化成数字。CD 音质是 44.1 kHz、16 位、双声道HDMI 支持到 192 kHz、24 位、最多 8 声道甚至更多。音频数据不是连续发送的而是打包成音频采样包Audio Sample Packet在数据岛周期里发送。每个包包含若干个采样帧具体数量取决于音频采样率和视频时序。这里有个关键概念叫“音频采样率与视频像素时钟的比值”因为音频包是插在视频消隐期的消隐期长度由视频时序决定所以能塞多少音频包是有限的。举个例子1080p60 的像素时钟是 148.5 MHz行消隐和场消隐期间有固定的空闲时间。音频采样率如果是 48 kHz那么每秒钟需要传 48000 个采样帧。这些采样帧要均匀分布到视频帧的空闲时间里。如果视频时序变了比如从 60 Hz 变成 50 Hz空闲时间变了音频包的分布也要跟着调整否则音频会断断续续。我实际调试时遇到过一个坑视频时序改了但音频包配置没改结果声音每隔几秒卡一下。后来用逻辑分析仪抓数据岛周期发现音频包发送间隔不均匀有的帧塞太多有的帧塞太少接收端缓冲区溢出。解决办法是根据新的视频时序重新计算每帧应发送的音频采样数均匀分配。音频的采样率不是随便设的必须和发送端、接收端都匹配。HDMI 通过 Audio InfoFrame 把采样率、位深、声道数告诉接收端接收端据此配置自己的音频解码器。如果 InfoFrame 写错接收端可能不出声或出噪声。2.3 RGB 与 YUV 两种格式的取舍逻辑HDMI 可以传 RGB也可以传 YUV也叫 YCbCr。RGB 是红绿蓝三原色每个像素三个分量直观适合计算机图形。YUV 把亮度Y和色度U/V 或 Cb/Cr分开人眼对亮度敏感、对色度不敏感所以可以降低色度采样率来省带宽适合视频压缩和传输。在 HDMI 里RGB 和 YUV 都可以用 4:4:4 采样即每个像素都有完整的三个分量。YUV 还支持 4:2:2 和 4:2:0色度分量采样率减半或减到四分之一。4:2:2 在专业视频里很常见因为带宽省一半画质损失人眼几乎看不出。4:2:0 主要用于 4K 视频带宽省更多但 HDMI 2.0 之前支持有限。选择哪种格式取决于源端和显示端的能力。计算机显卡通常输出 RGB因为操作系统和图形 API 都是 RGB 体系。视频播放器、机顶盒可能输出 YUV因为视频解码出来就是 YUV。显示端通过 EDID 告诉源端自己支持哪些格式源端选一个双方都支持的。这里有个常见问题RGB 和 YUV 之间的转换。如果源端输出 RGB显示端只支持 YUV就需要转换。转换公式是标准的但要注意量化范围。RGB 通常是全范围0-255YUV 有有限范围16-235和全范围之分。如果范围搞错画面会发灰或过曝。我见过有人接显示器发现黑色不够黑就是 YUV 有限范围被当成全范围处理了。注意调试颜色问题时先确认两端协商的是什么格式、什么量化范围。很多“颜色不对”的问题不是硬件坏是格式或范围不匹配。3. 实操过程与核心环节实现3.1 从像素时钟到 TMDS 串行流的完整链路假设我们要用 FPGA 实现一个 1080p60 的 HDMI 输出源数据是 RGB888。整个链路可以拆成这几步第一步生成视频时序。1080p60 的像素时钟是 148.5 MHz每帧 1125 行每行 2200 个像素时钟包括消隐。有效像素是 1920x1080。行同步、场同步、数据有效信号都要按 CEA-861 规范生成。CEA-861 是 HDMI 引用的视频时序标准定义了各种分辨率的详细参数。第二步把 RGB 数据送到 TMDS 编码器。每个像素时钟三个 8 位分量分别进入三个编码器。编码器输出 10 位然后做并串转换变成串行差分信号。并串转换通常用 FPGA 的 OSERDES 或 SelectIO 资源速率是像素时钟的 10 倍即 1.485 Gbps。第三步生成 TMDS 时钟。时钟通道发送的是像素时钟经过 TMDS 编码后的版本实际上就是把像素时钟做 10 倍频后按固定模式发送。接收端从时钟通道恢复像素时钟再用它采样三个数据通道。第四步插入控制周期和数据岛周期。在行消隐和场消隐期间发送端要切换到控制码或数据岛。控制码包括行同步前导、场同步前导等。数据岛里放音频包和辅助包。这部分逻辑比较复杂需要状态机精确控制。我当初实现时最头疼的是周期切换的时序。视频数据周期、数据岛周期、控制周期的边界必须和像素时钟严格对齐差一个时钟就可能被接收端误判。后来用示波器同时抓时钟和数据线对照规范里的时序图一点点调才稳定下来。3.2 参数计算以 1080p60 为例算清带宽和音频容量1080p60 的像素时钟 148.5 MHz每通道 TMDS 速率 1.485 Gbps三通道合计 4.455 Gbps。这是原始速率去掉 8b/10b 编码开销有效数据率是 4.455 x 8/10 3.564 Gbps。再减去消隐期的开销实际视频有效数据率是 1920 x 1080 x 60 x 24 2.986 Gbps24 位 RGB。剩下的带宽就是消隐期可以用来传音频和辅助信息。音频方面假设 48 kHz、24 位、8 声道每秒音频数据量是 48000 x 24 x 8 9.216 Mbps。这个量相对于消隐期的带宽来说很小所以音频传输很轻松。但要注意音频包不是连续发的是分散到每帧的消隐期里。1080p60 每帧的消隐期总时长大约是2200-1920x 1125 1920 x (1125-1080) 个像素时钟算下来约 40 万个像素时钟。每个音频采样包占用的时钟数取决于包大小一般几十到几百个时钟。所以每帧能塞的音频包数量是足够的。计算音频包分布时要用音频采样率除以视频帧率得到每帧需要的采样帧数。48000 / 60 800 个采样帧每帧。如果每个音频包放 4 个采样帧那每帧需要 200 个包。这些包要均匀分布在消隐期里不能集中在一处。我通常写一个计数器在消隐期开始时按固定间隔触发音频包发送间隔根据可用时钟数和包数量算出来。提示音频包分布不均会导致接收端音频缓冲区欠载或溢出表现为爆音或断音。调试时可以用逻辑分析仪统计每帧音频包数量确认是否均匀。3.3 实操现场用逻辑分析仪抓 TMDS 波形验证光看代码不够得看实际波形。我用的是带 HDMI 协议解码的逻辑分析仪探头接在 TMDS 差分对的两根线上用差分探头抓取一段时间的数据。解码器能直接解析出视频周期、数据岛周期、控制周期还能解出音频包内容。第一次抓波形时发现数据岛周期里音频包的位置不对有的行消隐里没有音频包有的行里塞了好几个。对照规范才发现音频包应该优先放在场消隐期行消隐期放辅助包。我之前的实现把音频包随便放导致接收端有时来不及处理。调整后音频包集中放在场消隐期行消隐期只放必要的控制包问题解决。另一个发现是 TMDS 时钟通道的抖动。用示波器看时钟通道的眼图发现抖动有点大原因是 FPGA 的 PLL 配置不够优化。后来换了更稳定的时钟源并调整了 PLL 的带宽参数眼图明显改善。这提醒我TMDS 虽然协议层重要但物理层的信号质量同样是成败关键。4. 常见问题与排查技巧实录4.1 显示端黑屏或花屏的排查思路黑屏和花屏是 HDMI 调试中最常见的问题原因可能出在物理层、协议层或格式协商。我一般按这个顺序排查先看物理连接。线缆是否插紧线材质量是否够。劣质线缆在低分辨率能亮高分辨率就花屏。换根好线试试能排除一大半问题。再看时钟。用示波器测 TMDS 时钟通道是否有信号频率是否对。如果时钟没有说明发送端没工作或时钟通道配置错误。如果时钟有但频率不对检查像素时钟和 PLL 配置。然后看数据通道。用逻辑分析仪抓数据线看是否有 TMDS 编码后的信号。如果没有检查编码器是否使能。如果有但解码失败检查通道映射和编码逻辑。最后看格式协商。读 EDID确认显示端支持的分辨率和格式。如果发送端输出的格式显示端不支持就会黑屏。我遇到过发送端输出 YUV 4:2:2 但显示端只支持 RGB结果黑屏改成 RGB 就好了。注意排查时先降分辨率。720p 能亮说明物理层基本没问题问题在高分辨率相关的时序或带宽。720p 也不亮问题在更基础的配置。4.2 音频无声或爆音的定位方法音频问题比视频问题更难查因为音频是打包在数据岛里的看不见摸不着。我的排查步骤是先确认 Audio InfoFrame 是否正确。用逻辑分析仪解出 InfoFrame看采样率、位深、声道数是否和源端配置一致。如果 InfoFrame 写错接收端可能直接静音。再确认音频包是否在发送。抓数据岛周期看是否有音频采样包。如果没有检查音频包生成逻辑是否使能音频数据是否准备好。然后确认音频包分布是否均匀。统计每帧的音频包数量如果忽多忽少接收端缓冲区会出问题。调整发送间隔让每帧的包数量稳定。最后确认采样率匹配。源端输出 48 kHz接收端如果配置成 44.1 kHz声音会变调或爆音。检查两端的音频配置寄存器。我踩过的一个坑是音频位深。源端输出 24 位但打包时只取了高 16 位低 8 位丢了结果声音有量化噪声。后来改成完整 24 位打包噪声消失。这说明音频打包的位对齐也很重要不能想当然。4.3 常见问题速查表现象可能原因排查方法解决方向完全黑屏时钟无输出示波器测时钟通道检查 PLL 和时钟配置低分辨率正常高分辨率花屏线缆或走线阻抗问题换线、测眼图改善线材或 PCB 阻抗颜色错误红蓝互换通道映射错误检查 Data0/1/2 映射按规范调整映射画面发灰量化范围不匹配检查 RGB/YUV 范围设置统一为全范围或有限范围音频无声InfoFrame 错误解码 InfoFrame修正采样率和格式音频爆音音频包分布不均统计每帧包数量均匀分布音频包间歇黑屏热插拔检测异常测 HPD 信号检查 HPD 电路和 EDID4K 无法显示带宽不足或格式不支持读 EDID 确认能力降低分辨率或换格式这张表是我调试时总结的基本覆盖了八成以上的常见问题。实际排查时先定位是物理层还是协议层再往细里查效率会高很多。4.4 几个容易被忽略的实操心得第一个心得EDID 一定要认真读。EDID 是显示端的能力清单里面包含支持的分辨率、刷新率、色彩格式、音频格式等。很多问题其实是源端没按 EDID 来配置。我习惯在调试初期就把 EDID 完整解析出来打印成表格心里有数。第二个心得热插拔检测HPD不能忽视。HDMI 接口有一根 HPD 线显示端插上后拉高告诉源端“我在”。如果 HPD 电路有问题源端可能不输出。我遇到过 HPD 信号抖动导致间歇黑屏后来加了滤波电容才稳定。第三个心得TMDS 编码器的复位要同步。编码器、并串转换、时钟生成这几个模块的复位必须同步释放否则上电时可能出现几个时钟周期的错位导致接收端锁不定。我一般用一个全局复位同步器确保所有模块同时开始工作。第四个心得测试时准备几根不同长度和质量的线。短线能跑不代表长线能跑好线能跑不代表劣质线能跑。消费级产品要考虑最差情况所以测试要覆盖各种线材。5. 从协议到落地的几点个人体会把 HDMI 从协议文档变成能跑通的硬件中间隔着的不是知识是无数细节。TMDS 编码的 running disparity、音频包的均匀分布、通道映射的顺序、量化范围的一致性这些在规范里都有写但只有真正调过才知道哪个细节会要命。我最初以为差分信号只要接对正负就行后来发现阻抗、等长、参考层、过孔设计每一个都影响眼图。我最初以为音频就是塞进去就行后来发现分布不均会让接收端缓冲区崩溃。如果你也在做 HDMI 相关的开发我的建议是先把物理层调稳眼图张开、时钟干净再调协议层。协议层里先保证视频能出图再加音频最后调格式协商。每一步都用逻辑分析仪或示波器验证别靠猜。遇到问题先降分辨率、换线、读 EDID这三招能解决大部分疑难杂症。这个内容后续还可以往深里挖比如 HDMI 2.1 的 FRL 模式、DSC 压缩、eARC 音频回传都是独立的大话题。但把 1.4/2.0 这套 TMDS 体系吃透后面的新特性理解起来会顺很多因为底层思路是一脉相承的。