ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

HDMI接口原理全解析:TMDS编码、差分信号与音视频传输机制

HDMI接口原理全解析:TMDS编码、差分信号与音视频传输机制 HDMI 这个接口大多数人每天都在用但真正把它内部的数据流讲清楚的人并不多。很多人以为 HDMI 就是一根高清线插上就有画面有声音可一旦遇到花屏、闪屏、外接显示器没信号、颜色发灰这类问题就完全不知道从哪下手。我自己在调试 FPGA 视频通路和嵌入式显示方案的时候被 HDMI 的时序和色彩格式反复折磨过很多次后来才慢慢把它的底层逻辑理顺视频走的是三对差分信号音频是 PCM 级无压缩数据打包在数据包里靠协议采样还原而色彩空间上它同时支持 RGB 和 YUV 两种格式。这篇内容就是把这些年踩过的坑和理清的原理一次性讲透适合做嵌入式视频、FPGA 图像通路、显示器调试以及想搞懂 HDMI 到底怎么工作的朋友参考。不管你是刚接触 TMDS 的新手还是已经能跑通通路但说不清细节的老手应该都能从里面找到点有用的东西。1. 从一根线到三对差分HDMI 物理层的真实面目1.1 为什么 HDMI 要用差分信号而不是单端信号先问一个最基础但很多人答不上来的问题HDMI 为什么不用一根线传一个信号非要搞成三对差分这背后其实是高速信号传输的必然选择。HDMI 1.4 的 TMDS 时钟最高跑到 340MHz每个时钟周期传 10bit单通道速率就是 3.4Gbps三通道加起来超过 10Gbps。这个速率下如果用单端信号参考地一旦有噪声接收端根本分不清是 0 还是 1。差分信号的核心优势在于共模抑制。一对差分线传的是幅度相等、极性相反的两个信号接收端只看两者的差值。外界干扰同时耦合到两根线上做差之后就被抵消掉了。这就好比两个人抬一根扁担路上颠簸对两个人是同时作用的扁担两端的相对高度差基本不变。HDMI 的 TMDS 就是靠这个机制在几 Gbps 的速率下还能保持眼图张开。具体到接口定义标准 HDMI Type-A 有 19 个引脚其中真正传高速数据的是四对差分线差分对引脚作用TMDS Data07/9传输蓝色分量及控制信号TMDS Data14/6传输绿色分量及控制信号TMDS Data21/3传输红色分量及控制信号TMDS Clock10/12传输像素时钟注意这里有个容易搞混的点Data0/1/2 并不是严格对应 R/G/B而是在不同编码阶段承载不同内容。在视频数据周期里Data2 承载 R、Data1 承载 G、Data0 承载 B但在控制周期里它们传的是 HSYNC、VSYNC、CTL0~3 这些控制位。这个分时复用的设计是理解 HDMI 的关键后面讲编码的时候会再展开。1.2 三对数据线加一对时钟线的工作节奏HDMI 的传输节奏由 TMDS Clock 决定。每个时钟周期三对数据线各传一个 10bit 的 TMDS 字符合起来就是 30bit 的并行数据。接收端用时钟去采样这三路数据恢复出原始的像素信息。这里要强调一个实操中经常被忽略的细节TMDS Clock 的频率等于像素时钟而不是比特率。比如 1080p60 的像素时钟是 148.5MHz那么 TMDS Clock 就是 148.5MHz而每对数据线的比特率是 148.5MHz × 10 1.485Gbps。很多人第一次算的时候会把时钟和比特率搞混导致配置 PLL 的时候参数算错画面直接出不来。我在用 FPGA 做 HDMI 输出的时候第一步永远是先把像素时钟算准。以 720p60 为例CEA-861 标准规定的像素时钟是 74.25MHz那么TMDS Clock 74.25MHz单通道比特率 742.5Mbps三通道总带宽 2.2275Gbps这个带宽要能覆盖视频加音频加控制信息的全部开销。如果算出来带宽不够就会出现音频断续或者画面撕裂。所以选 FPGA 或者视频处理芯片的时候一定要先确认它的 TMDS 发送器能跑到多高的速率别等到板子打回来才发现跑不动。1.3 差分对的布线为什么这么讲究差分信号虽然抗干扰强但对 PCB 布线有硬性要求。我见过太多因为布线不当导致 HDMI 出不了图的案例这里把几个关键点列出来等长匹配一对差分线内两根线的长度差要控制在 5mil 以内否则两根线上的信号到达时间不一致差值信号就会失真。三对数据线之间也要尽量等长一般要求控制在 50mil 以内。阻抗控制HDMI 差分线的特征阻抗要求 100Ω这需要根据叠层和线宽线距精确计算。阻抗不匹配会导致反射眼图闭合。远离干扰源差分对要远离电源、晶振、开关电源这些噪声源至少保持 3 倍线宽的间距。参考地完整差分线下方要有完整的地平面不能有跨分割的情况否则回流路径被打断共模噪声会急剧上升。提示如果你画的板子 HDMI 时好时坏先别怀疑芯片拿示波器量一下差分对的眼图十有八九是布线或者阻抗的问题。2. TMDS 编码8bit 到 10bit 到底发生了什么2.1 为什么非要编码直接传不行吗原始像素数据是 8bit 的为什么 TMDS 要把它编码成 10bit 再传多出来的 2bit 不是浪费带宽吗这个问题想通了TMDS 就理解一半了。直接传 8bit 数据有两个致命问题。第一是直流平衡如果连续传很多个 0 或者很多个 1信号的平均电平就会偏离中心接收端的耦合电容会积累电荷导致判决阈值漂移。第二是跳变不足如果数据长时间不变接收端就没法从数据里恢复时钟因为 TMDS 是源同步的时钟是单独传的但数据本身也需要足够的跳变来维持信号完整性。TMDS 编码用 8bit 变 10bit 解决了这两个问题。编码后的 10bit 字符有两个特性一是直流平衡任意时刻 1 和 0 的数量差不超过 1二是跳变丰富保证接收端有足够的边沿。多出来的 2bit 就是用来做这个平衡和跳变的代价换来的是几 Gbps 下稳定的传输。2.2 编码算法的两个阶段TMDS 编码分两个阶段我尽量用大白话讲清楚。第一阶段是最小化跳变。对输入的 8bit 数据根据其中 1 的个数决定是否做异或或者异或非运算。如果 1 的个数大于 4就用 XNOR否则用 XOR。这样做的目的是让相邻 bit 之间的跳变尽量少降低功耗和 EMI。这一步会输出一个 9bit 的中间结果其中第 9bit 是标志位告诉接收端用的是 XOR 还是 XNOR。第二阶段是直流平衡。根据前面统计的 1 的个数和当前的运行不一致度running disparity决定是否对 9bit 结果取反最终输出 10bit。运行不一致度是一个累积值记录到目前为止传出去的 1 比 0 多多少或者少多少。编码器会尽量让这个值在 0 附近摆动保证长期来看直流是平衡的。用伪代码表示大概是这样def tmds_encode(data8, disparity_in): # 第一阶段最小化跳变 ones bin(data8).count(1) if ones 4 or (ones 4 and data8 1 0): q_m data8 ^ (data8 1) # 简化示意 use_xnor True else: q_m data8 ^ (data8 1) use_xnor False # 第二阶段直流平衡 # 根据 disparity_in 和 q_m 中 1 的个数决定是否取反 # 最终输出 10bit return encoded_10bit, disparity_out实际工程中不会自己写这个编码器FPGA 厂商都会提供 TMDS 编码 IP或者用 SelectIO 里的硬核。但理解这个流程在调试的时候能帮你判断问题出在哪一环。2.3 控制周期和数据周期的切换前面提到 Data0/1/2 是分时复用的这里展开讲。TMDS 的传输分两种周期控制周期传 HSYNC、VSYNC、CTL0~CTL3 这些控制信号。控制周期用固定的 10bit 编码比如 CTL00、CTL10 对应 10b1101010100 这样的固定码字。数据周期传实际的像素数据用上面讲的 8bit 到 10bit 编码。视频的有效像素区域传数据周期消隐区域传控制周期。接收端通过检测特定的码字序列来判断当前是控制周期还是数据周期从而正确解析。这个机制保证了视频时序的同步也是为什么 HDMI 能自动识别分辨率和刷新率的原因。注意控制周期的固定码字是 HDMI 协议规定的不能随便改。如果你自己写发送逻辑控制周期的编码必须严格按标准来否则接收端识别不了直接黑屏。3. 音频为什么能塞进视频数据流里3.1 PCM 音频的本质采样点加时间戳HDMI 的音频是 PCM 级的也就是无压缩的原始采样数据。这一点很多人有误解以为 HDMI 传的音频是压缩过的其实不是。PCM 就是把模拟声音波形按固定时间间隔采样每个采样点用固定位数量化直接传这些采样值。举个例子48kHz 采样率、16bit 位深的立体声每秒产生 48000 × 2 × 16 1.536Mbit 的数据。这些数据本身没有压缩就是原始采样点。HDMI 要做的是把这些采样点打包成数据包插入到视频数据的消隐期里传输。为什么能插进去因为视频的消隐期本来就有大量空闲带宽。以 1080p60 为例有效像素只占每行的一部分剩下的消隐区足够塞下音频包。HDMI 协议规定了音频包的结构包括包头、采样数据、校验信息等。3.2 音频采样率靠协议规定不靠时钟线这是 HDMI 音频最容易被误解的地方。HDMI 没有单独的音频时钟线音频采样率是靠协议约定的。发送端在音频包的信息帧里声明当前用的采样率比如 48kHz接收端根据这个声明去还原音频时钟。具体来说接收端会用视频的像素时钟作为参考通过一个分数分频器比如 N/M 分频生成音频主时钟再分频得到采样时钟。这个 N 和 M 的值就是协议里规定的对应不同的采样率。比如 48kHz 对应的 N 和 M 是特定值44.1kHz 又是另一组值。这个设计的好处是不用额外传时钟线坏处是一旦 N/M 配置错了音频就会变调或者断续。我在调试的时候遇到过一次音频播放速度不对查了半天发现是接收端芯片的音频 N/M 参数没配对改过来就正常了。采样率典型 N/M 配置说明32kHz4096/6272常用于广播44.1kHz6272/8918CD 标准48kHz6144/6144影视标准96kHz12288/6144高解析音频192kHz24576/6144极高解析提示如果你做的设备音频和视频不同步先检查音频 N/M 参数再看音频包插入的位置对不对。这两个地方出问题的概率最高。3.3 音频包在数据流里的位置音频包不是随便插的它有固定的插入位置。HDMI 协议规定音频包要在数据岛的特定位置传输数据岛位于视频消隐期。发送端要在每个视频帧的消隐期里安排音频包的传输保证音频数据的连续性。这里有个实操经验音频包的插入频率和视频帧率有关。如果视频帧率是 60Hz那么每秒有 60 次插入机会。每次插入能传的音频采样数有限所以高采样率多声道的音频需要更密集的插入或者更大的包。设计的时候要算清楚带宽别让音频包挤占了控制信息的空间。4. RGB 和 YUV两种色彩格式的取舍4.1 RGB 和 YUV 的本质区别HDMI 支持 RGB 和 YUV 两种色彩格式这不是随便定的背后有深刻的历史和工程原因。RGB 是最直观的格式每个像素用红绿蓝三个分量表示三个分量地位平等。显示器最终显示的就是 RGB所以 RGB 格式的信号到显示器基本不用转换延迟最低。YUV 则是把亮度Y和色度U、V分开。这个设计的依据是人眼对亮度敏感、对色度不敏感。既然对色度不敏感就可以少传色度信息从而节省带宽。YUV420 就是每四个像素共享一组色度色度数据量只有亮度的四分之一。格式分量带宽典型场景RGBR/G/B 各 8bit高显示器、PCYUV444Y/U/V 各 8bit与 RGB 相同专业视频YUV422Y 全采样U/V 减半中视频采集YUV420Y 全采样U/V 四分之一低视频压缩、播放4.2 HDMI 里 RGB 和 YUV 怎么选HDMI 传输的时候RGB 和 YUV 都可以用具体用哪个取决于源端和显示端的协商。一般来说PC 接显示器默认用 RGB因为显示器原生就是 RGB转换最少。播放器接电视常用 YUV因为视频内容本身多是 YUV 编码的直接传 YUV 省一次转换。专业视频设备根据工作流选后期制作多用 RGB广播多用 YUV。这里有个坑如果源端输出 YUV显示端却按 RGB 解析颜色就会完全错乱通常表现为偏绿或者偏紫。我在调试的时候就遇到过源端配置成了 YUV422接收端默认 RGB画面整个发绿改成一致就正常了。4.3 色彩空间转换的注意事项RGB 和 YUV 之间的转换不是简单的线性变换涉及到色彩空间标准BT.601、BT.709、BT.2020和量化范围Limited Range 16-235、Full Range 0-255。这些参数不匹配画面就会发灰或者过曝。BT.601标清时代的标准现在主要用于 480i/576i。BT.709高清标准1080p 及以下用这个。BT.20204K/8K 时代的标准色域更广。量化范围也很关键。Limited Range 把 16 当黑、235 当白Full Range 把 0 当黑、255 当白。如果源端用 Limited Range显示端按 Full Range 解析黑色就会变成深灰白色变成浅灰整个画面发灰。反之则会过曝暗部细节全丢。注意调试 HDMI 颜色问题时先确认色彩空间标准和量化范围是否匹配这两个参数不匹配是最常见的颜色异常原因。5. 时序流程从像素到差分信号的完整链路5.1 视频时序的基本参数HDMI 的视频时序遵循 CEA-861 标准核心参数包括HActive一行有效像素数比如 1920。HBlank行消隐像素数比如 280。HTotal一行总像素数HActive HBlank 2200。VActive一帧有效行数比如 1080。VBlank帧消隐行数比如 45。VTotal一帧总行数VActive VBlank 1125。像素时钟 HTotal × VTotal × 帧率。以 1080p60 为例2200 × 1125 × 60 148.5MHz正好对上前面说的像素时钟。这些参数不是随便定的CEA-861 对每种分辨率都有明确规定。自己设计时序的时候HBlank 和 VBlank 不能太小否则音频包和控制信息没地方放也不能太大否则浪费带宽。5.2 从像素到 TMDS 字符的转换流程一个像素从进入 HDMI 发送器到变成差分信号要经过这些步骤像素数据准备从帧缓冲或者图像源取出像素数据可能是 RGB 也可能是 YUV。色彩空间转换如果需要把 RGB 转成 YUV 或者反过来。TMDS 编码每个 8bit 分量编码成 10bit TMDS 字符。并串转换10bit 并行数据转成串行比特流。差分驱动串行比特流变成差分信号输出。这个流程里TMDS 编码和并串转换是硬件自动完成的一般不用管。但色彩空间转换和时序生成需要自己配置这两块也是最容易出问题的地方。5.3 消隐期的控制信息和音频包插入消隐期不是空闲的要传控制信息和音频包。控制信息包括 HSYNC、VSYNC、CTL0~3音频包按协议插入。发送端要在正确的时间点切换控制周期和数据周期接收端才能正确解析。具体来说每行的消隐期开始后先传控制周期然后传数据岛包含音频包和其他辅助信息最后回到控制周期等待下一行有效像素。这个节奏必须严格按时序来早一点晚一点都可能导致接收端解析错误。我在 FPGA 上实现的时候用一个状态机来管理这个流程HActive 期间传数据周期HBlank 期间传控制周期和数据岛。状态机的状态切换由像素计数器和行计数器驱动确保每个周期都在正确的时间点。6. 调试 HDMI 时最容易踩的几个坑6.1 画面出不来先查时钟再查编码HDMI 不出图是最常见的问题排查顺序很重要。我的经验是先量 TMDS Clock用示波器看时钟有没有输出频率对不对。时钟没有后面全白搭。再量差分对看三对数据线有没有信号眼图张不张开。如果眼图闭合多半是布线或者阻抗问题。查 HPD 信号HPDHot Plug Detect是接收端告诉发送端我准备好了的信号。HPD 不对发送端不会输出。查 DDC 通信EDID 读取失败也会导致不出图因为发送端不知道接收端支持什么分辨率。这个顺序能帮你快速定位问题在哪一层别一上来就怀疑芯片坏了。6.2 画面闪烁或者花屏时序和带宽问题画面闪烁或者花屏通常是时序参数不对或者带宽不够。检查这几个地方像素时钟是否准确时钟偏差会导致时序错乱。HBlank/VBlank 是否足够太小会导致数据挤在一起。TMDS 速率是否超限超过发送器能力会导致数据丢失。差分对是否等长不等长会导致采样错误。我遇到过一次花屏查了半天发现是 HBlank 设小了音频包没地方放挤占了视频数据。把 HBlank 加大就正常了。6.3 颜色不对色彩空间和量化范围颜色不对分几种情况整体偏色多半是 RGB/YUV 格式不匹配。发灰或者过曝量化范围不匹配。颜色偏差色彩空间标准不匹配。排查的时候先确认源端和显示端的格式声明是否一致再看量化范围和色彩空间标准。这三个参数任意一个不匹配颜色都会出问题。6.4 音频异常N/M 参数和包插入音频异常表现为无声、断续、变调。排查顺序查 N/M 参数采样率对应的 N/M 值是否正确。查音频包插入位置是否在数据岛的指定位置。查音频格式声明信息帧里的采样率、位深、声道数是否正确。查带宽音频包是否挤占了视频数据。音频问题比视频问题更难查因为涉及的因素更多。我的建议是先用标准测试设备验证确认是源端问题还是接收端问题再针对性排查。7. 一些实战中的经验补充7.1 用 Python 辅助验证色彩数据调试色彩问题的时候我经常用 Python 读图片的 RGB 值来对照。比如用 PIL 库读一张纯色图片看每个像素的 RGB 值再和 HDMI 输出的实际颜色对比能快速判断是色彩空间转换错了还是量化范围错了。from PIL import Image img Image.open(test.png) pixel img.getpixel((100, 100)) print(fRGB: {pixel}) # 如果 HDMI 输出偏绿对比源图和实际输出的 RGB 差异这个方法虽然简单但在定位颜色问题时特别有效。源图的 RGB 值是已知的HDMI 输出的颜色如果和源图对不上就能确定是转换环节出了问题。7.2 FPGA 方案里的 VDMA 和 HDMI 配合用 MicroBlaze 或者 Zynq 做 HDMI 输出的时候VDMAVideo Direct Memory Access是常用的数据搬运模块。VDMA 从 DDR 里读帧数据通过 AXI Stream 送给 HDMI 发送 IP。这个链路里最容易出问题的是VDMA 配置帧缓存地址、 stride、帧数要配对。AXI Stream 位宽要和 HDMI IP 的输入位宽匹配。时钟域VDMA 和 HDMI IP 可能在不同时钟域要加异步 FIFO。我在 Zynq 上跑 1080p 输出的时候VDMA 的 stride 设错了画面出现斜条纹。改成正确的行字节数就正常了。这个参数很容易被忽略但错了画面一定不对。7.3 多路 HDMI 输入输出的芯片选型做多路 HDMI 切换的时候芯片选型要考虑输入路数4 路输入 1 路输出的芯片要确认是否支持无缝切换。分辨率支持最高支持到 4K 还是 1080p。HDCP 支持如果涉及受保护内容要确认 HDCP 版本。控制接口I2C 还是 SPI和主控是否匹配。选型的时候别只看参数表一定要拿开发板实测。有些芯片参数写得好实际跑起来发热严重或者切换有黑屏这些只有实测才知道。7.4 笔记本外接 HDMI 没画面的常见原因笔记本外接显示器没画面不一定是线的问题。常见原因包括输出模式没切换有些笔记本需要手动切换显示模式。分辨率不匹配笔记本输出的分辨率显示器不支持。线材质量劣质线材跑不了高带宽。接口松动HDMI 接口容易松动重新插拔试试。排查的时候先用另一根线或者另一台显示器交叉验证能快速定位是笔记本、线材还是显示器的问题。HDMI 这套协议看起来复杂但拆开来看就是物理层、编码层、协议层三块。物理层保证信号能传过去编码层保证数据能正确恢复协议层保证视频音频控制信息能协调工作。把这三层理顺了再遇到问题就知道从哪查起。我自己从最开始的一头雾水到现在能独立调试通路靠的就是反复踩坑加对照标准文档。希望这些经验能帮你少走点弯路。
返回列表