LVGL 屏幕颜色不对?先查 LV_COLOR_16_SWAP,别猜通道交换
写蓝显绿、写青显蓝、饱和度还低——看似「红绿蓝通道互换」,真相是 RGB565 字节序错位。一次印象深刻的误判复盘。
现象
ESP32-S3 + ILI9342C(320×240,4 线 SPI),LVGL 8 画的 UI:
- 代码写
#5BA8E0(蓝)→ 屏幕显示淡绿 - 代码写
#2EE6C8(青绿)→ 屏幕显示天蓝 - 而且饱和度普遍偏低,颜色发灰
第一反应:面板 RGB 通道顺序不对(ILI 系列确实有 RGB/BGR 面板之分),于是写了个交换宏把绿蓝通道对调。
对了一半,换一组颜色就穿帮。
为什么通道交换解释不通
字节序错位会造成伪通道交换的假象:RGB565 一个像素占两个字节,SPI 线上的字节序和 LVGL 内存里不一致时,每像素两字节错位、R/G/B 的位被打散重组——看起来既像通道互换,又像掉饱和度。
穷举 6 种通道排列,每一种都能「部分解释」观察到的颜色,但拿 8 个观察点对拍,没有一种排列能全中。
真相
sdkconfig 里:
CONFIG_LV_COLOR_16_SWAP=y # 正确(SPI 面板应如此)
CONFIG_LV_COLOR_16_SWAP=0 # 当时被静默改成了这个
LV_COLOR_16_SWAP=0 时,LVGL 存的 RGB565 字与 SPI 线上要求的字节序不匹配 → 全部颜色错位。改回 y,颜色立刻全对,根本不需要任何通道交换。
教训
- SPI 面板 + LVGL 8 颜色不对,第一条命令查
sdkconfig里的LV_COLOR_16_SWAP(sdkconfig.old能看出它有没有被改过),再谈通道交换 - 判断「屏幕变换是不是恒等」要用多种色相交叉验证(红/绿/蓝/灰各来一个),全中才敢下结论;单一颜色对上就开改,大概率是在拟合错误模型
- 交换宏别删,保持恒等(
#define UI_SWAP_GB(h) (h))——万一以后真换到 BGR 面板,改一处就行 - 把
CONFIG_LV_COLOR_16_SWAP=y钉进sdkconfig.defaults,防止它被静默改回去