3. 屏幕刷新与撕裂:屏幕刷新率、垂直同步、撕裂现象成因分析

屏幕刷新这个话题,说白了就是显示系统里最基础也最容易被忽视的一环。我早年做第一块LCD驱动时,觉得只要把帧数据送出去就行了,结果画面一跑起来,那个撕裂感简直让人抓狂。后来才明白,刷新率、垂直同步、撕裂这三者之间,藏着嵌入式图形性能优化的核心秘密。

3.1 屏幕刷新率:显示系统的“心跳”

屏幕刷新率,就是显示器每秒重绘完整画面的次数,单位是Hz。60Hz意味着每秒刷新60次,每次间隔约16.67ms。这个参数决定了显示系统的时间基准。

我个人习惯把刷新率看作显示器的“心跳”。每次心跳,屏幕从左上角到右下角逐行扫描一遍。LCD虽然不像CRT那样真的用电子束扫描,但像素数据的更新逻辑仍然是逐行进行的。

关键认知:刷新率是硬件决定的固定节奏。你的MCU或MPU必须在每个刷新周期内完成帧缓冲区的更新,否则就会出问题。

常见的刷新率场景:

  • 60Hz:绝大多数嵌入式LCD的标准配置,周期16.67ms
  • 30Hz:低功耗场景,周期33.33ms,肉眼能感知到闪烁
  • 120Hz:高端工业或游戏屏,周期8.33ms,对渲染压力极大

3.2 垂直同步:让渲染跟上硬件的节奏

垂直同步(V-Sync)是一种同步机制。它的作用很简单:让GPU或CPU的帧提交动作,与屏幕的刷新周期对齐。

为什么需要同步?你想想看,如果屏幕正在扫描第300行,你突然把帧缓冲区的内容改了,那屏幕上半部分显示的是旧帧,下半部分显示的是新帧——这就是撕裂。

我的经验:在STM32F429上做LCD驱动时,我习惯用LTDC的垂直空白中断(VBlank ISR)来触发帧交换。这个中断正好落在屏幕扫描完最后一行的瞬间,是切换缓冲区的黄金窗口。

垂直同步的实现方式:

方式 原理 延迟 适用场景
硬件V-Sync 显示控制器硬件信号同步 低 高性能嵌入式
软件V-Sync 轮询或中断等待VBlank 中 通用MCU
双缓冲+V-Sync 后台缓冲区渲染,VBlank时交换 低 推荐方案

3.3 撕裂现象:不同步的代价

撕裂(Tearing)的本质,是帧缓冲区在屏幕扫描过程中被修改。屏幕上半部分读到了旧帧的数据,下半部分读到了新帧的数据,中间那条错位的分界线就是撕裂线。

为什么会这样?

  • 单缓冲模式下,CPU/GPU随时可以写入帧缓冲区
  • 屏幕控制器独立运行,按固定频率读取缓冲区
  • 两者没有握手协议,读写冲突必然发生

我曾经踩过的坑:在一个工业HMI项目中,我用单缓冲+高优先级任务直接写显存。结果操作员反映屏幕上的仪表指针经常“断裂”。我一开始以为是DMA传输问题,排查了两天才意识到是撕裂。加上V-Sync同步后,问题立刻消失。

撕裂的视觉表现:

  • 水平方向出现明显的错位分界线
  • 快速滚动的文字或图像出现“剪切”效果
  • 动画不连贯,有跳跃感

3.4 三者关系:一个时间轴上的博弈

刷新率、垂直同步、撕裂,这三者其实是在同一个时间轴上博弈。我画了一张图来展示它们的关系:

刷新率、垂直同步与撕裂关系图 刷新周期 1 (16.67ms) 刷新周期 2 (16.67ms) 刷新周期 3 (16.67ms) 刷新周期 4 (16.67ms) VB VB VB VB 无V-Sync:随时写入 撕裂! 有V-Sync:VBlank时写入 说明: • 无V-Sync时,CPU可在任意时刻写入帧缓冲区,容易在扫描过程中发生读写冲突,产生撕裂。 • 有V-Sync时,写入操作被限制在VBlank窗口内,保证屏幕扫描期间缓冲区内容稳定。

3.5 实际项目中的取舍

在实际嵌入式项目中,不是所有场景都需要垂直同步。我总结了几条经验:

  • 静态界面:不需要V-Sync,单缓冲即可,省内存省功耗
  • 动画/视频播放:必须用V-Sync+双缓冲,否则撕裂无法接受
  • 触摸交互:建议用V-Sync,但要注意帧率不能低于30fps,否则触摸响应延迟会很明显
  • 低功耗场景:可以关闭V-Sync,用软件定时器控制帧率,牺牲流畅度换续航

我的建议:如果你不确定要不要加V-Sync,先加上。在调试阶段用逻辑分析仪抓一下LTDC的VSYNC和帧缓冲区写信号,看看有没有重叠。有重叠就保留,没有重叠再考虑优化掉。

3.6 避坑指南:我曾经犯过的错

最后分享几个我实际踩过的坑,希望能帮你少走弯路:

  • 坑1:以为DMA传输完成就代表帧更新完成。实际上DMA只是把数据搬到了显存,屏幕控制器可能正在读那个区域。一定要等VBlank信号。
  • 坑2:在VBlank中断里做太多事情。VBlank窗口通常只有几百微秒,如果中断处理时间过长,会错过下一个刷新周期,导致帧率下降。
  • 坑3:双缓冲时忘记清空后台缓冲区。新帧数据只覆盖了部分区域,残留的旧帧数据会在切换后显示出来,造成“鬼影”。

嗯,屏幕刷新与撕裂这个话题,说深了可以写一本书。但核心就一句话:让帧缓冲区的写入,永远发生在屏幕不读它的时候。 理解了这句话,你就掌握了嵌入式显示系统同步的精髓。