ESP32S3的LVGL配置参数解释、动画播放优化(更新中)
一、menuconfig相关参数
1. ESP PSRAM
1. SPI RAM access method 三种访问模式
- 一般情况选择
malloc()
模式就行
如何选择?
模式 | 适用场景 | 是否需要改代码 | 碎片化风险 |
---|---|---|---|
malloc() 完全集成 | 通用应用,代码无需区分内存来源 | 否 | 高 |
heap_caps_malloc() 半集成 | 需区分内部 RAM 和 PSRAM 的场景 | 是 | 低 |
直接内存映射(.bss) | 实时系统、静态分配大缓冲区 | 是 | 无 |
1. Make RAM allocatable using malloc() as well(完全集成模式)
- KCONFIG 值:
SPIRAM_USE_MALLOC
- 行为:
- 将 PSRAM 完全集成到系统的堆(heap) 中,与内部 RAM 统一管理。
- 标准
malloc()
可以直接分配 PSRAM 内存,无需特殊函数。 - 系统会自动在内部 RAM 和 PSRAM 之间分配内存(优先使用内部 RAM,不足时使用 PSRAM)。
- 优点:
- 对开发者最透明,无需修改代码即可使用 PSRAM。
- 适合需要大量动态内存但不想手动管理内存来源的应用。
- 缺点:
- 如果频繁分配/释放小内存,可能引发 PSRAM 碎片化(PSRAM 的分配速度比内部 RAM 慢)。
2. Integrate RAM into memory map as .bss(仅作为未管理内存区域)
- KCONFIG 值:
SPIRAM_USE_MEMMAP
- 行为:
- PSRAM 仅作为 未管理的连续内存区域 出现在 CPU 的内存映射中(地址范围
0x3C000000~0x3FFFFFFF
)。 - 无法通过
malloc()
直接分配,需通过指针直接访问(如volatile uint8_t *psram = (uint8_t *)0x3C000000;
)。 - 通常用于静态分配(如全局数组)或手动管理内存。
- PSRAM 仅作为 未管理的连续内存区域 出现在 CPU 的内存映射中(地址范围
- 优点:
- 无堆管理开销,适合对性能或实时性要求高的场景。
- 缺点:
- 需开发者手动管理内存,易出错。
3. Make RAM allocatable using heap_caps_malloc() only(半集成模式)
- KCONFIG 值:
SPIRAM_USE_CAPS_ALLOC
- 行为:
- PSRAM 被集成到堆中,但 仅能通过
heap_caps_malloc(MALLOC_CAP_SPIRAM, size)
显式分配。 - 标准
malloc()
不会使用 PSRAM。
- PSRAM 被集成到堆中,但 仅能通过
- 优点:
- 精确控制哪些内存分配在 PSRAM(如大缓冲区),避免碎片化。
- 内部 RAM 留给高频访问的数据。
- 缺点:
- 需修改代码,显式调用
heap_caps_malloc
。
- 需修改代码,显式调用
2. Maximum malloc() size, in bytes, to always put in internal memory
- 在选择
Make RAM allocatable using malloc() as well
选项时出现 - 该选项用于 强制小内存分配始终使用内部 RAM,避免因频繁的小内存分配占用 SPI PSRAM(速度较慢),从而提高性能并减少 PSRAM 的碎片化。
- 默认值:
16384
(16KB) - 含义:
- 任何小于或等于该值的
malloc()
请求,强制分配在内部 RAM。 - 超过该值的内存请求,才会尝试使用 SPI PSRAM。
- 任何小于或等于该值的
2. LVGL configuration
1. Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI).
-
解决 SPI 或其他 8-bit 接口显示屏 的颜色格式兼容性问题,显示屏颜色异常(如红蓝通道反色)
-
RGB565 颜色格式:
在 RGB565 模式下,一个像素占 2 字节(16位),格式为:RRRRR GGGGGG BBBBB (高位 -> 低位)
通常存储为 大端序(Big-Endian),即:
- 第1字节(高字节):
RRRRRGGG
- 第2字节(低字节):
GGGGBBBB
- 第1字节(高字节):
-
问题背景:
某些 8-bit 接口的显示屏(如 SPI 屏)在接收 RGB565 数据时,会按 字节顺序逐字节处理。如果显示屏硬件或驱动芯片预期的是 小端序(Little-Endian)(即低字节在前),直接发送大端序数据会导致颜色错误。 -
解决方案:
启用Swap the 2 bytes of RGB565 color
后,LVGL 会在发送颜色数据前 交换高低字节,确保显示屏接收到的顺序正确。
2. If true use custom malloc/free, otherwise use the built-in lv_mem_alloc() and lv_mem_free()
-
LVGL 使用内置的 lv_mem_alloc() 和 lv_mem_free() 管理动态内存(如对象创建、样式分配等)。这些函数基于 LVGL 自己的内存池或系统的 malloc()/free()(取决于配置)。
-
Kconfig 名称:
LV_USE_CUSTOM_MALLOC
-
作用:
控制是否启用自定义内存函数。true
(启用):LVGL 将调用你提供的malloc
/free
函数。false
(禁用,默认):使用 LVGL 内置的lv_mem_alloc()
和lv_mem_free()
。
3. Header to include for the custom memory function
- 当上面选择使用自定义内存函数时,显示此选项
- Kconfig 名称:
LV_CUSTOM_MALLOC_INCLUDE
- 作用:
指定包含自定义内存函数声明的头文件路径。- 例如:
"stdlib.h"
- 例如:
4. Number of the memory buffer
-
默认值:
16
-
临时缓冲区用途:
LVGL 在渲染(如绘制图形、处理图像、文本布局等)时,需要一些短期使用的内存缓冲区。例如:- 存储抗锯齿(anti-aliasing)的临时像素数据。
- 处理图像解码(如 PNG、JPG)时的中间结果。
- 文本绘制时的字形缓存。
-
缓冲区数量:
LV_MEM_BUF_MAX_NUM
定义了系统可以同时存在的最大缓冲区数量。如果实际需求超过此值,LVGL 会输出错误日志(如"No more memory buffers available"
)。 -
需要增加的情况
场景 | 建议值 | 原因 |
---|---|---|
复杂 UI(多图层/多动画) | 32~64 | 渲染过程中需要更多临时缓冲区 |
高频动态刷新(如视频播放) | 24~48 | 避免因缓冲区不足导致卡顿 |
大量图像解码(如幻灯片) | 32+ | 图像处理需要额外缓冲区 |
- 需要减少的情况
场景 | 建议值 | 原因 |
---|---|---|
极简 UI(仅文本/简单图形) | 8~12 | 节省内存 |
无动态渲染(静态界面) | 4~8 | 几乎无需临时缓冲区 |
5. Default image cache size. 0 to disable caching. 图片缓存加速
- 当你在 UI 中重复使用相同的图片(例如 icon、背景、按钮状态图片),如果缓存开启并命中,那么LVGL 会直接从缓存拿已经解码好的数据。
-
内置图像格式(RAW、C array、bmp):这些解码几乎是零成本(直接 memcpy 或简单读取),所以缓存意义不大。
-
复杂格式(PNG、JPG、自定义解码器):解码开销大,缓存可以显著减少重复解码的 CPU 占用,提升流畅度。代价是 额外占用 RAM(尤其是 PSRAM) 来存放解码后的图像。
-
优点:
- 如果用 PNG/JPG 并且图片会重复显示(菜单图标、背景等),缓存能避免反复解码,提升 FPS,减少卡顿。
- 在动画场景(比如切换页面)中,缓存能减少帧延迟。
-
缺点:
- 每张缓存图片会占用 width × height × color_depth/8 字节的 RAM(或 PSRAM)。
- 如果缓存数量设大(比如 3~5),且图片是全屏大图,内存压力会非常大。
- ESP32S3 内部 RAM 很有限(~512KB 可用),即使开了 8MB PSRAM,缓存大图也会影响性能(PSRAM 访问延迟比内部 RAM 高)。
-
如果只用 BMP / 内置 RAW → 配置为
0
(禁用缓存)。 -
如果用 PNG / JPG / 压缩格式 → 建议配置为
1
~3
,根据可用 RAM 调整。
6. LVGL 文件系统驱动
LVGL 允许注册自定义的文件系统驱动,使其能够访问外部存储(如 SD 卡、SPIFFS、FATFS 等)。
-
File system on top of stdio API
- stdio 驱动:使用标准 C 库(fopen, fread, fclose 等)访问文件。
- 盘符(Drive Letter):LVGL 使用单个大写字母(如 ‘A’、‘S’)来标识不同的存储设备
-
Set the working directory
/spiffs
-
0 to cache this number of bytes in lv_fs_read()
307200
读取的缓存大小,大文件或高频读取则需要更大的空间
- 使用lv函数读取文件的例子
lv_fs_file_t f;lv_fs_res_t res;res = lv_fs_open(&f, "S:/112.gif", LV_FS_MODE_RD);if (res == LV_FS_RES_OK){ESP_LOGI("TEST", "File system driver working!");// 获取文件大小uint32_t size;lv_fs_seek(&f, 0, LV_FS_SEEK_END);lv_fs_tell(&f, &size);lv_fs_seek(&f, 0, LV_FS_SEEK_SET);ESP_LOGI("TEST", "File size: %d bytes", (int)size);lv_fs_close(&f);}else{ESP_LOGE("TEST", "File system driver failed (error: %d)", res);}