4. LTDC时序配置:同步信号、前后肩与时钟频率
屏幕花屏,十次有八次是时序配错了。
这话可能有点绝对,但在我这些年接触的TouchGFX项目里,LTDC时序配置确实是翻车重灾区。你想想看,MCU和LCD面板之间要握手,要同步,要告诉屏幕「我从哪一行开始画」「我画到哪一行了」「这一行结束了」。这些信息全靠几个信号线来传递。任何一个信号的时序对不上,画面就会错位、撕裂、甚至直接黑屏。
这一章,我们就来把这些信号彻底讲透。
4.1 LTDC同步信号:HSYNC和VSYNC
先说两个最核心的信号:HSYNC(行同步)和VSYNC(帧同步)。
HSYNC负责告诉屏幕:「新的一行要开始了」。VSYNC则负责告诉屏幕:「新的一帧要开始了」。你可以把VSYNC想象成翻书页的动作,HSYNC就是每一行文字的换行符。
这两个信号都是脉冲信号。平时保持高电平(或低电平,取决于配置),到了该同步的时候,拉低(或拉高)一个固定的脉冲宽度,然后再恢复。这个脉冲的宽度、位置、前后空闲时间,就是我们常说的时序参数。
关键概念:
- HSYNC:水平同步,每行一个脉冲
- VSYNC:垂直同步,每帧一个脉冲
- 同步脉冲宽度:信号保持有效电平的时间
- 前后肩:脉冲前后插入的空白周期
我刚开始做LCD驱动时,犯过一个低级错误——把HSYNC和VSYNC的极性搞反了。屏幕规格书写的是低电平有效,我配成了高电平有效。结果画面一直闪,查了两天才发现是这里的问题。嗯,从那以后我每次配时序都会先确认极性。
4.2 前后肩与同步脉冲
光有同步脉冲还不够。你想想看,屏幕收到HSYNC信号后,需要一点时间来「反应」——行驱动电路要稳定,像素时钟要对齐。所以,在真正的有效像素数据开始传输之前,需要插入一段空白周期。这就是前肩(HFP,Horizontal Front Porch)。
同样,一行数据传完之后,也需要一段空白让电路复位,准备接收下一行。这就是后肩(HBP,Horizontal Back Porch)。
垂直方向也一样,有VFP和VBP。
| 参数 | 全称 | 作用 |
|---|---|---|
| HFP | Horizontal Front Porch | 行同步脉冲后的空白像素周期 |
| HBP | Horizontal Back Porch | 行同步脉冲前的空白像素周期 |
| VFP | Vertical Front Porch | 帧同步脉冲后的空白行周期 |
| VBP | Vertical Back Porch | 帧同步脉冲前的空白行周期 |
| HSYNC | Horizontal Sync Pulse | 行同步脉冲宽度 |
| VSYNC | Vertical Sync Pulse | 帧同步脉冲宽度 |
这些参数从哪里来?从LCD面板的数据手册里来。每一块屏幕都会给出典型值和范围。我个人的习惯是:先用典型值,如果画面有偏移再微调。千万不要自己瞎猜,我曾经见过有人把HBP设成0,结果画面整体左移了半个屏幕。
小技巧:如果画面整体向右偏移,试着增加HBP;如果向左偏移,增加HFP。垂直方向同理。
4.3 时钟频率计算与匹配
时序参数配好了,时钟频率不对,照样花屏。
LTDC的像素时钟(Pixel Clock,简称PCLK)决定了每秒能传输多少个像素点。计算公式其实很简单:
PCLK = (H_Total) × (V_Total) × 帧率
其中:
H_Total = H_Active + HFP + HBP + HSYNC
V_Total = V_Active + VFP + VBP + VSYNC
举个例子。假设你的屏幕分辨率是800×480,帧率60fps,时序参数如下:
H_Active = 800
HFP = 40
HBP = 40
HSYNC = 48
H_Total = 800 + 40 + 40 + 48 = 928
V_Active = 480
VFP = 13
VBP = 29
VSYNC = 3
V_Total = 480 + 13 + 29 + 3 = 525
PCLK = 928 × 525 × 60 ≈ 29.2 MHz
算出来是29.2MHz。但你的MCU不一定能精确产生这个频率。比如STM32F429的LTDC时钟源来自PLL,分频系数是整数。你可能只能配到29.5MHz或者28.8MHz。这时候怎么办?
我的经验是:优先保证帧率稳定。稍微偏离一点目标帧率(比如59fps或61fps)通常看不出来,但时钟抖动或者分频不准导致的像素错位,一眼就能看出来。
注意:时钟频率不能超过LCD面板支持的最大值。很多廉价屏幕标称50MHz,实际跑到45MHz以上就开始丢像素了。我曾经在一个项目里把PCLK配到了48MHz,屏幕规格书说支持50MHz,结果画面顶部有一条彩色的噪点带。降回40MHz就正常了。所以,留点余量总是没错的。
4.4 时序配置的完整流程
说了这么多,我们来梳理一下实际操作步骤:
- 查手册:找到LCD面板的时序参数表,记下HFP、HBP、HSYNC、VFP、VBP、VSYNC的典型值
- 算总长:计算H_Total和V_Total
- 算时钟:根据目标帧率计算PCLK
- 配时钟树:在MCU的时钟配置里,找到最接近的PCLK频率
- 配寄存器:把时序参数写入LTDC的同步配置寄存器
- 验证:上电看画面,如果偏移或花屏,微调前后肩
下面这张图可以帮你理清整个时序配置的逻辑关系:
4.5 实战中的常见坑
最后,分享几个我在项目中踩过的坑:
- 坑一:忽略DE信号。有些屏幕用DE(Data Enable)信号代替HSYNC/VSYNC来指示有效数据区域。如果你配了同步信号但没配DE极性,画面可能完全不显示。
- 坑二:前后肩设得太小。有些工程师为了「压榨」带宽,把HFP和HBP设成最小值。结果屏幕内部电路来不及稳定,画面边缘出现重影。我建议至少留4-8个像素的余量。
- 坑三:时钟频率算错。记得有一次我把H_Total算成了H_Active + HFP + HBP,忘了加HSYNC的宽度。结果算出来的PCLK偏小,帧率只有50fps,画面明显卡顿。
- 坑四:分频系数选错。STM32的LTDC时钟来自PLL3R或者PLLSAI,分频系数是整数。如果你需要的PCLK是29.2MHz,但分频后只能得到29.8MHz,别硬上。稍微调一下帧率目标,让PCLK落在整数分频点上。
我的调试习惯:先用逻辑分析仪抓一下HSYNC和VSYNC的波形,确认脉冲宽度和周期对不对。这一步能帮你排除一半的时序问题。