1、双缓冲基础概念:屏幕刷新率、撕裂效应与单缓冲的痛点
各位同学好,我是老吴。做嵌入式UI这么多年,我踩过最多的坑,就是显示缓冲区的配置问题。很多开发者一上来就开双缓冲,但连为什么要用双缓冲都说不清楚。今天这一章,我们先打好基础。
说白了,双缓冲不是什么高深技术。它就是一块「后台画板」。你在这块画板上画完,再整块翻到屏幕上。就这么简单。但为什么需要它?这得从屏幕的刷新机制说起。
1.1 屏幕刷新率——你的屏幕在「闪」
屏幕刷新率,单位是 Hz。60Hz 就是一秒闪 60 次,每次闪叫一帧。每次闪的时候,屏幕从左上角到右下角,一行一行地把像素刷出来。
嗯,这里要注意:屏幕不是瞬间刷完的。它需要时间。比如 60Hz 的屏幕,一帧大约 16.67ms。在这 16.67ms 里,屏幕正在「画」这一帧。如果你在它画到一半的时候,往显存里写了新数据——好戏就来了。
核心概念:刷新率决定了屏幕更新一帧的速度。刷新率越高,人眼感觉越流畅。但高刷新率对 MCU 的带宽要求也更高。
| 刷新率 | 每帧时间 | 常见场景 |
|---|---|---|
| 30 Hz | 33.33 ms | 低功耗手表、电子价签 |
| 60 Hz | 16.67 ms | 大部分嵌入式屏幕 |
| 120 Hz | 8.33 ms | 高端 HMI、游戏屏 |
我个人习惯,在项目初期先确认屏幕的刷新率。因为这会直接影响你选 MCU 的 RAM 大小和 DMA 带宽。你想想看,如果 MCU 刷一帧要 20ms,屏幕刷新率却是 60Hz,那必然掉帧。
1.2 撕裂效应——屏幕「劈叉」了
撕裂效应,英文叫 tearing。你肯定见过:屏幕滚动时,画面上下错位,像被撕开了一样。为什么会这样?
我举个例子。你在写一个动画,每 10ms 更新一次画面。屏幕每 16.67ms 刷新一次。假设屏幕刚刷到一半,你往显存里写入了新数据。屏幕下半部分读到的,是新一帧的数据;上半部分还是旧数据。结果就是——上半张脸在笑,下半张脸在哭。
避坑指南:我曾经在一个工业 HMI 项目里,因为没处理撕裂,客户投诉说屏幕「花屏」。排查了两天才发现,不是硬件坏了,是缓冲区竞争导致的撕裂。从那以后,我所有项目都强制加双缓冲或垂直同步。
撕裂的严重程度取决于两个因素:
- 写入速度:你往显存写数据越快,撕裂的「裂缝」越窄,但出现频率更高。
- 刷新周期:屏幕刷新率越低,每帧时间越长,撕裂窗口越大。
说白了,单缓冲就是一块显存,CPU 和屏幕控制器同时读写它。不打架才怪。
1.3 单缓冲的痛点——为什么它不够用
单缓冲,就是整个系统只有一块帧缓冲区。CPU 往里面画,屏幕从里面读。听起来简单,但问题一堆。
痛点一:撕裂
上面已经讲了。只要 CPU 写入和屏幕读取不同步,撕裂就必然出现。除非你保证 CPU 在屏幕的消隐区间(VBlank)内写完。但现实是,你的动画逻辑、触摸响应、网络通信,哪个能保证准时写完?
痛点二:闪烁
闪烁和撕裂不一样。闪烁是因为你清空了显存,但还没画完新内容。屏幕读到了「半成品」——一块空白或乱码。下一帧你又画完了,显示正常。再下一帧又清空……人眼看到的就是一闪一闪。
我记得早期做单片机游戏机时,用单缓冲画小球。每次更新前先清屏,再画球。结果球在屏幕上「抖」得厉害。后来加了双缓冲,世界清净了。
痛点三:性能瓶颈
单缓冲下,CPU 必须等屏幕刷完才能写下一帧。否则就会撕裂。这意味着你的帧率被屏幕刷新率锁死了。你想跑 30fps?屏幕是 60Hz,你只能跑 60fps 或 30fps,中间值很难稳定。
小技巧:如果你实在资源紧张只能用单缓冲,可以尝试在 VBlank 中断里更新显存。但前提是你的绘制时间必须小于 VBlank 时间。对于 60Hz 屏幕,VBlank 大约 1-2ms。你确定你的 LVGL 绘制能在 1ms 内完成?
1.4 一张图看懂:单缓冲 vs 双缓冲
下面这张 SVG 图,我画了单缓冲和双缓冲的核心流程对比。你看一眼就明白了。
1.5 什么时候必须上双缓冲?
不是所有场景都需要双缓冲。我列几个判断标准:
- 有动画:只要 UI 里有滑动、旋转、渐变,单缓冲基本扛不住。
- 有触摸交互:用户手指滑动时,画面必须实时响应。撕裂会让人感觉「卡顿」。
- 屏幕分辨率高:320x240 以上,单缓冲的撕裂窗口就很大了。
- MCU 性能弱:越弱的 MCU,绘制时间越长,越容易和屏幕刷新撞车。
我的经验:在 STM32F429 + 480x272 屏幕的项目里,单缓冲下 LVGL 跑动画,撕裂率大约 30%。就是每三帧就有一帧撕裂。用户肉眼可见。换成双缓冲后,撕裂率直接降到 0%。代价是多占用了 480×272×2 = 261KB 的 RAM。值不值?我觉得值。
1.6 本章小结
这一章我们聊了三件事:
- 屏幕刷新率决定了每帧的时间窗口。
- 撕裂效应是读写竞争的结果,单缓冲无法避免。
- 单缓冲的痛点:撕裂、闪烁、性能瓶颈。
双缓冲不是银弹,但它解决了 90% 的显示问题。下一章,我会带你手把手配置 LVGL 的双缓冲驱动。到时候你会看到,代码其实没几行,但背后的原理,就是今天讲的这些。
嗯,先消化一下。有问题随时在群里问我。