4、显示时序与时钟:Pixel Clock计算、显示时序参数、RK时钟树配置
显示驱动里,时序和时钟是绕不开的硬骨头。我刚开始接触这块时,总觉得不就是让屏幕亮起来嘛,至于搞这么复杂?后来被一块MIPI屏折腾了三天,才发现时序不对,屏幕就是死活不亮。嗯,今天咱们就把这块彻底讲透。
4.1 显示时序到底是个啥?
说白了,显示时序就是告诉屏幕:什么时候该扫哪一行,什么时候该换下一行,什么时候该从头再来。你想想看,屏幕上的像素点是一个个刷新的,总得有个规矩吧?
我习惯把显示时序拆成三个维度:
- 行时序(Horizontal Timing):从左到右扫完一行
- 帧时序(Vertical Timing):从上到下扫完一帧
- 像素时钟(Pixel Clock):决定每个像素点刷新的速度
每个维度里,又包含几个关键参数:
| 参数 | 含义 | 常见坑点 |
|---|---|---|
| HBP (Horizontal Back Porch) | 行同步后的消隐区 | 太小会导致图像左移 |
| HFP (Horizontal Front Porch) | 行同步前的消隐区 | 太小会导致图像右移 |
| HSYNC | 行同步脉冲宽度 | 不同屏幕要求差异很大 |
| VBP / VFP / VSYNC | 垂直方向对应参数 | 影响图像上下偏移 |
⚠️ 我曾经踩过的坑: 有个项目用了块非标屏,规格书里HBP写的是88个像素时钟周期,我按常规设了48,结果图像整体左移了大概20个像素。查了两天才发现是消隐区没配对。所以拿到新屏,第一件事就是对着规格书把每个参数核对一遍。
4.2 Pixel Clock怎么算?
Pixel Clock,也叫点时钟,是显示时序的“心跳”。它决定了每秒能刷多少个像素点。
计算公式其实很简单:
Pixel Clock = (H_Total) × (V_Total) × Refresh_Rate
其中:
- H_Total = H_Active + HBP + HFP + HSYNC
- V_Total = V_Active + VBP + VFP + VSYNC
举个例子,一块1080p的屏,60Hz刷新率:
H_Active = 1920
HBP = 148, HFP = 88, HSYNC = 44
H_Total = 1920 + 148 + 88 + 44 = 2200
V_Active = 1080
VBP = 36, VFP = 4, VSYNC = 5
V_Total = 1080 + 36 + 4 + 5 = 1125
Pixel Clock = 2200 × 1125 × 60 = 148.5 MHz
💡 我个人习惯: 算出来的Pixel Clock最好留5%~10%的余量。比如算出来148.5MHz,我会先试试能不能跑到155MHz。万一后面要调刷新率或者加特效,不至于重新配时钟树。
4.3 RK时钟树配置实战
瑞芯微的时钟树,说白了就是一条链路:从PLL出来,经过分频、选通,最终送到各个显示模块。我画了个简化的流程:
PLL (比如24MHz晶振倍频)
→ 分频器 (得到目标频率)
→ 时钟门控 (开关控制)
→ VOP (Video Output Processor)
→ DSI/HDMI/eDP 等接口
在RK平台上,配置时钟树主要操作这几个寄存器:
- CRU (Clock & Reset Unit):核心时钟管理单元
- VOP_DCLK:显示像素时钟
- ACLK / HCLK:总线时钟,影响DMA传输速度
我拿RK3568举个例子,配置一个1080p@60的MIPI屏:
// 1. 先配PLL,得到合适的VCO频率
// 比如用24MHz晶振,倍频到594MHz
// 2. 分频得到Pixel Clock
// 594MHz / 4 = 148.5MHz
// 3. 配置VOP时钟源选择
writel(CLK_SEL_VOP0_DCLK_SRC_PLL, &cru->clksel_con[XX]);
// 4. 设置分频系数
writel(DIV_VOP0_DCLK(4), &cru->clksel_con[XX]);
// 5. 使能时钟
writel(CLK_EN_VOP0_DCLK, &cru->clk_en);
🔑 关键点: 时钟树配置的顺序很重要。我建议先配PLL,再配分频,最后使能时钟。如果顺序反了,可能会产生毛刺,导致屏幕闪一下或者直接黑屏。
4.4 避坑指南:我遇到过的时钟问题
做显示驱动这些年,时钟这块我栽过不少跟头。挑几个典型的说说:
- 时钟频率不够:有次用了一块4K屏,算出来Pixel Clock要594MHz。结果RK3399的VOP最高只能跑到500MHz。最后只能降分辨率或者降刷新率。
- 时钟抖动太大:MIPI DSI对时钟抖动很敏感。我遇到过屏幕偶尔闪一下,查了半天发现是PLL配置的环路带宽不对,导致时钟抖动超标。
- 时钟域同步问题:VOP和DSI是两个时钟域,中间需要做异步FIFO。有次FIFO深度设小了,高分辨率下直接溢出,图像撕裂。
⚠️ 我曾经犯过的错: 有个项目为了省功耗,把ACLK降到了200MHz。结果发现DMA传输跟不上,屏幕刷新到一半就卡住了。后来才明白,总线时钟不能只看显示需求,还得考虑内存带宽。ACLK至少要保证DMA能在1帧时间内把数据搬完。
4.5 调试技巧:怎么验证时序对不对?
配完时钟和时序,怎么知道对不对?我一般用这几招:
- 看示波器:直接量HSYNC和VSYNC的波形,看频率对不对,占空比是否稳定
- 读寄存器:RK平台有CLK_DUMP功能,可以打印出当前时钟树的状态
- 跑测试图:用彩条、网格图,看图像有没有偏移、撕裂、闪烁
嗯,说到测试图,我习惯在驱动里内置一个纯色填充函数。调试时先让屏幕显示纯红、纯绿、纯蓝,确认颜色没问题了,再上复杂图像。这样能快速定位问题是出在时序上还是数据通路上。
最后说一句,显示时序和时钟配置,说白了就是“算清楚、配准确、验证透”。别嫌麻烦,这块搞定了,后面调图像质量、调性能就顺风顺水了。