1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 【ESP32】Arduino+LVGL 如何使用PSRAM优化显示

【ESP32】Arduino+LVGL 如何使用PSRAM优化显示

时间:2022-03-19 14:57:16

相关推荐

【ESP32】Arduino+LVGL 如何使用PSRAM优化显示

前言

最近项目需要买了一个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,这样可以尽可能提高触摸的灵敏度。

总结

可能有同学在设置了上面的参数后仍然发现屏幕好像还是卡卡的,这是因为以上都是在软件层面进行的优化,软件的优化是有限的,不如直接在硬件上进行优化。

就比如,我使用的屏幕虽然只有240X240的分辨率,但它使用的是SPI协议进行通信,相比起使用8080并口的显示屏,刷新速度肯定是大打折扣的;前者每次传输1bit,但后者每次可以传输8bit或16bit,这个差距是巨大的。

又比如,PSRAM虽然有4MB的空间,看上去很大,但它走的也是SPI协议;而我们平时用的SRAM或SDRAM都是使用好几个管脚进行寻址和传数据,速度上面没得比。但PSRAM的好处就是空间大,SDRAM、SRAM的空间一般只能做几百KB。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。