LVGL部分刷新与整屏交换的冲突解析

发布时间:2026/6/26 0:15:36

LVGL部分刷新与整屏交换的冲突解析 原因说明LV_USE_PERF_MONITOR会在lv_layer_sys()上放一个 FPS 标签并周期性lv_label_set_text_fmt只让一小块区域变脏。你的disp_flush是这样工作的static void disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { rt_sem_take(_SemaphoreVsync, RT_WAITING_FOREVER); R_GLCDC_BufferChange(g_display0_ctrl, (uint8_t *) color_p, (display_frame_layer_t) DISPLAY_FRAME_LAYER_1); lv_disp_flush_ready(disp_drv); }R_GLCDC_BufferChange是把整屏显存基址切到color_p相当于“整帧缓冲交换”并没有按area做局部拷贝。在 LVGL 默认的部分刷新 双全屏缓冲下每次只重绘脏区缓冲区里其它像素可能是旧的或无效的硬件却整屏显示这块缓冲 → 就容易出现花屏/错位。性能监视器一开小区域刷新变多问题就更容易暴露。关闭监视器时刷新节奏、lv_timer_pause行为不同有时看起来“还能用”但根因仍是整指针交换 与 部分刷新 不匹配。LVGL 官方对“双满屏缓冲 只换地址”的说明就是要设disp_drv.full_refresh 1见lv_port_disp_template.c里 “Example 3”。修改void lv_port_disp_init(void) { _SemaphoreVsync rt_sem_create(lvgl_sem, 1, RT_IPC_FLAG_PRIO); if (RT_NULL _SemaphoreVsync) { rt_kprintf(lvgl semaphore create failed\r\n); RT_ASSERT(0); } #if LVGL_VERSION_MAJOR 9 /*Initialize disp_buf with the buffer(s). With only one buffer use NULL instead buf_2 */ lv_disp_draw_buf_init(disp_buf, fb_background[0][0], fb_background[1][0], sizeof(fb_background[0])); /*Basic initialization*/ lv_disp_drv_init(disp_drv); /*Set the resolution of the display*/ disp_drv.hor_res LV_HOR_RES_MAX; disp_drv.ver_res LV_VER_RES_MAX; /*Set a display buffer*/ disp_drv.draw_buf disp_buf; /* * GLCDC flush only switches the layer base address to a full framebuffer; it does not * merge partial areas. Partial refresh leaves non-dirty pixels stale in the back buffer, * which looks like corruption (often triggered by LV_USE_PERF_MONITOR updating a small label). * LVGL doc: two full-screen buffers address swap set full_refresh (see lv_port_disp_template). */ disp_drv.full_refresh 1; /*Used to copy the buffers content to the display*/ disp_drv.flush_cb disp_flush; /*Finally register the driver*/ lv_disp_drv_register(disp_drv); #else /*------------------------------------ * Create a display and set a flush_cb * -----------------------------------*/ lv_display_t *disp lv_display_create(LV_HOR_RES_MAX, LV_VER_RES_MAX); lv_display_set_flush_cb(disp, disp_flush); lv_display_set_flush_wait_cb(disp, vsync_wait_cb); lv_display_set_buffers(disp, fb_background[0][0], fb_background[1][0], sizeof(fb_background[0]), LV_DISPLAY_RENDER_MODE_DIRECT); #endif lvgl_init_flag 1; }在lv_port_disp.c里为 LVGL 8 路径增加了disp_drv.full_refresh 1保证每次刷新都会画满一整帧再交给 GLCDC与当前的 BufferChange 用法一致。代价任意脏区都会触发整屏重绘CPU 会高一些调试时开LV_USE_PERF_MONITOR一般可以接受正式发布可关掉监视器。若仍要部分刷新以省算力就需要改驱动在flush_cb里按area把像素写入“当前显示用”的那块显存或 DMA 局部更新而不能只靠切换整帧指针。

相关新闻