前言
最近项目需要买了一个ESP-WROVER-E模块,这个模块内置了一个4MB的PSRAM,对于需要大内存运行的场景非常友好。
在我的项目中用到了LVGL这个第三方图形库,下面就讲一下如何最大化地在LVGL中使用这个PSRAM。
教程
在lv_conf.h文件中,找到下面的代码。
/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/
#define LV_MEM_CUSTOM 1
#if LV_MEM_CUSTOM == 0
/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
#define LV_MEM_SIZE (48U * 1024U) /*[bytes]*/
/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
#define LV_MEM_ADR 0 /*0: unused*/
/*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/
#if LV_MEM_ADR == 0
#undef LV_MEM_POOL_INCLUDE
#undef LV_MEM_POOL_ALLOC
#endif
#else /*LV_MEM_CUSTOM*/
#define LV_MEM_CUSTOM_INCLUDE <stdlib.h> /*Header for the dynamic memory function*/
#define LV_MEM_CUSTOM_ALLOC malloc
#define LV_MEM_CUSTOM_FREE free
#define LV_MEM_CUSTOM_REALLOC realloc
#endif /*LV_MEM_CUSTOM*/
默认情况下LV_MEM_CUSTOM为0,这时LVGL会自己弄一个内存池进行管理,这个内存池是使用ESP32的SRAM,而ESP32能用的SRAM实际大小也就320KB。
如果ESP32上自带PSRAM的话,可以将LV_MEM_CUSTOM设为1,这时LVGL将使用stdlib.h头文件内的函数分配内存,而使用这些函数分配内存是可以充分使用到SRAM和PSRAM的内存的。
接下来修改与显示有关的代码。官方会提供3个显示刷新的方案——单缓冲10行刷新、双缓冲10行刷新和双缓冲全像素刷新。如果我们的ESP32上自带PSRAM,那么肯定尽可能选择刷新速度最快的双缓冲全像素刷新方式,但在用之前函数最好还是计算一下内存的占用,大一点的屏幕在该模式下要占满4MB的内存也不是不可能的。
void Display::init(void)
{
display_init();
// static lv_disp_draw_buf_t draw_buf_dsc_1;
// static lv_color_t buf_1[MY_DISP_HOR_RES * 10]; /*A buffer for 10 rows*/
// lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 10); /*Initialize the display buffer*/
// static lv_disp_draw_buf_t draw_buf_dsc_2;
// static lv_color_t buf_2_1[MY_DISP_HOR_RES * 10]; /*A buffer for 10 rows*/
// static lv_color_t buf_2_2[MY_DISP_HOR_RES * 10]; /*An other buffer for 10 rows*/
// lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 10); /*Initialize the display buffer*/
static lv_disp_draw_buf_t draw_buf_dsc_3;
// static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*A screen sized buffer*/
// static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*Another screen sized buffer*/
lv_color_t* buf_3_1 = (lv_color_t*) heap_caps_malloc(MY_DISP_HOR_RES * MY_DISP_VER_RES, MALLOC_CAP_SPIRAM);
lv_color_t* buf_3_2 = (lv_color_t*) heap_caps_malloc(MY_DISP_HOR_RES * MY_DISP_VER_RES, MALLOC_CAP_SPIRAM);
lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2, MY_DISP_VER_RES * MY_DISP_HOR_RES); /*Initialize the display buffer*/
static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
/*Set the resolution of the display*/
disp_drv.hor_res = MY_DISP_HOR_RES;
disp_drv.ver_res = MY_DISP_VER_RES;
/*Used to copy the buffer's content to the display*/
disp_drv.flush_cb = my_disp_flush;
disp_drv.full_refresh = 1;
/*Set a display buffer*/
disp_drv.draw_buf = &draw_buf_dsc_3;
/*Finally register the driver*/
lv_disp_drv_register(&disp_drv);
}
在开辟屏幕的2个缓冲区时,我并没有使用stdlib.h头文件中的malloc函数,而是使用esp_heap_caps.h头文件中的heap_caps_malloc函数,因为该函数可以决定内存空间开辟的方式,第二个参数填入MALLOC_CAP_SPIRAM,这样该空间会被强制开辟在PSRAM中。
如果我们用了双缓冲全像素刷新,记得在注册显示设备时加上下面的代码。
disp_drv.full_refresh = 1;
这样是告诉LVGL我们的程序可以进行全像素刷新。
接下来还可以进行一些额外的设置,我们可以在lv_conf.h文件找到下面的代码。
/*Default display refresh period. LVG will redraw changed areas with this period time*/
#define LV_DISP_DEF_REFR_PERIOD 20 /*[ms]*/
/*Input device read period in milliseconds*/
#define LV_INDEV_DEF_READ_PERIOD 10 /*[ms]*/
第一个设置的是屏幕的刷新频率,默认为30ms刷新一次,我设置到了20ms刷新一次,那么最高就可以有50fps的帧率。第二个是设置输入设备的采样频率,默认为20ms采样一次,我设置到了10ms,这样可以尽可能提高触摸的灵敏度。文章来源:https://www.toymoban.com/news/detail-481183.html
总结
可能有同学在设置了上面的参数后仍然发现屏幕好像还是卡卡的,这是因为以上都是在软件层面进行的优化,软件的优化是有限的,不如直接在硬件上进行优化。
就比如,我使用的屏幕虽然只有240X240的分辨率,但它使用的是SPI协议进行通信,相比起使用8080并口的显示屏,刷新速度肯定是大打折扣的;前者每次传输1bit,但后者每次可以传输8bit或16bit,这个差距是巨大的。
又比如,PSRAM虽然有4MB的空间,看上去很大,但它走的也是SPI协议;而我们平时用的SRAM或SDRAM都是使用好几个管脚进行寻址和传数据,速度上面没得比。但PSRAM的好处就是空间大,SDRAM、SRAM的空间一般只能做几百KB。文章来源地址https://www.toymoban.com/news/detail-481183.html
到了这里,关于【ESP32】Arduino+LVGL 如何使用PSRAM优化显示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!