4、刷新模式选择:对比 LV_COLOR_DEPTH 与 LV_COLOR_16_SWAP 对刷新速度的影响

颜色深度这个配置,很多人一开始就随便选一个。我见过不少项目,明明硬件支持 16 位色,却因为默认配置走了弯路。说白了,LV_COLOR_DEPTH 和 LV_COLOR_16_SWAP 这两个宏,直接决定了每一帧数据量的大小,也决定了你的动画能不能跑满 60fps。

4.1 颜色深度到底影响什么?

先看一个最直观的公式:

每帧数据量(字节) = 屏幕宽度 × 屏幕高度 × (LV_COLOR_DEPTH / 8)

举个例子。一块 480×272 的屏幕:

  • LV_COLOR_DEPTH = 32:每帧 480 × 272 × 4 = 522,240 字节 ≈ 510 KB
  • LV_COLOR_DEPTH = 16:每帧 480 × 272 × 2 = 261,120 字节 ≈ 255 KB
  • LV_COLOR_DEPTH = 8:每帧 480 × 272 × 1 = 130,560 字节 ≈ 127 KB

数据量差了一倍甚至四倍。你想想看,同样的 SPI 总线或者 RGB 接口,传输 510 KB 和 255 KB 的时间能一样吗?

核心结论:颜色深度每降低一半,刷新带宽需求就降低一半。如果你的硬件接口带宽有限,降低色深是最直接的提速手段。

4.2 LV_COLOR_16_SWAP 是个什么鬼?

这个宏我一开始也觉得很迷惑。它只对 16 位色有效。16 位色通常用 RGB565 格式,也就是高 5 位是 R,中间 6 位是 G,低 5 位是 B。但有些 LCD 控制器或者 MCU 的硬件 SPI 接口,要求字节序是 小端 的。

举个例子:一个像素的颜色是 0xABCD(RGB565)。

  • 不开启 SWAP:发送顺序是 0xAB → 0xCD
  • 开启 SWAP:发送顺序是 0xCD → 0xAB

这个交换是在 LVGL 内部完成的,不需要你手动处理。但问题来了——它会影响刷新速度吗?

我的经验:LV_COLOR_16_SWAP 本身不增加数据量,它只是交换两个字节的顺序。在 CPU 层面,这个操作几乎不花时间。真正影响速度的是你的 LCD 驱动是否原生支持 RGB565 小端序。如果硬件不支持,你开了 SWAP,LVGL 每帧都要做一次字节交换,虽然单次开销很小,但帧率高了以后,累计开销还是能感知到的。

4.3 不同组合下的性能实测对比

我在一个 STM32F429 平台上做过测试,屏幕是 480×272,使用 LTDC 接口 + 双缓冲。结果如下:

配置组合 每帧数据量 实测刷新率 CPU 占用率
LV_COLOR_DEPTH=32 510 KB 42 fps 78%
LV_COLOR_DEPTH=16, SWAP=0 255 KB 58 fps 45%
LV_COLOR_DEPTH=16, SWAP=1 255 KB 56 fps 48%
LV_COLOR_DEPTH=8 127 KB 62 fps 32%

看到没?从 32 位降到 16 位,帧率直接从 42 跳到了 58,提升非常明显。而 SWAP 开启与否,只差了 2 fps,基本可以忽略。

注意:如果你的 LCD 控制器硬件不支持 RGB565 小端序,而你又不开启 SWAP,画面颜色会完全错乱。我曾经在这个坑里浪费了半天——画面显示出来全是紫色和绿色条纹,最后发现是字节序没对上。

4.4 如何选择?我的建议

  1. 优先用 16 位色:大部分嵌入式屏幕本身就只有 16 位色深,用 32 位纯属浪费带宽。除非你需要显示照片级图片或者做颜色渐变要求很高的 UI。
  2. 检查 LCD 数据手册:看它要求的像素数据格式是 RGB565 大端还是小端。如果是小端,就开启 LV_COLOR_16_SWAP;如果是大端,就不开。
  3. 8 位色慎用:虽然帧率最高,但颜色断层非常明显。只适合低端屏幕或者对颜色不敏感的应用,比如工业控制面板的简单文字界面。
  4. 32 位色只在必要时用:比如你的 UI 有大量半透明效果、阴影、渐变,或者你用了 LVGL 的 lv_opa 混合功能。否则,别给自己找麻烦。

4.5 配置示例

在 lv_conf.h 中,你只需要关注这两行:

/* 颜色深度:16 位 */
#define LV_COLOR_DEPTH 16

/* 字节序交换:根据 LCD 硬件决定 */
#define LV_COLOR_16_SWAP 1

嗯,就这么简单。但很多人就是在这里翻车。我建议你拿到新屏幕后,先做一个纯色填充测试,看看颜色对不对。如果红色变成了蓝色,绿色变成了紫色,那大概率就是 SWAP 没配对。

4.6 一张图看懂选择逻辑

下面这张图是我自己总结的决策流程,你可以直接拿来用:

颜色深度与 SWAP 选择决策流程图 颜色深度与 SWAP 选择决策流程 开始配置颜色 是否需要半透明/阴影/渐变? 是 使用 LV_COLOR_DEPTH=32 否 颜色质量要求高? 是 使用 LV_COLOR_DEPTH=16 否 使用 LV_COLOR_DEPTH=8 LCD 需要小端序? 是 开启 LV_COLOR_16_SWAP 否 不开启 SWAP 配置完成,测试颜色正确性

4.7 避坑指南

  • 不要盲目追求 32 位色:我见过有人用 32 位色跑一个只有文字和矩形的界面,帧率只有 30fps,降到 16 位后直接到 60fps。UI 效果几乎看不出区别。
  • SWAP 不是性能瓶颈:如果你发现开了 SWAP 后帧率下降明显,那大概率不是 SWAP 本身的问题,而是你的 LCD 驱动在字节交换时做了额外的内存拷贝。检查驱动代码,别冤枉 LVGL。
  • 8 位色下不要用抗锯齿:LVGL 的抗锯齿在 8 位色下会使用抖动算法,效果很差,而且额外消耗 CPU。如果你必须用 8 位色,关掉 LV_ANTIALIAS。