当前位置: 首页 > news >正文

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 buffer's 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 局部更新),而不能只靠切换整帧指针。

http://www.jsqmd.com/news/785841/

相关文章:

  • 1.中断的优先级
  • 研发管理工具怎么选?主流工具功能对比、适用场景与选型建议
  • 基于SpringBoot+Vue的求职招聘小程序
  • 有没有能辅助生成论文框架、自动推荐文献的智能写作软件?
  • 实测taotoken在多模型切换时的延迟与稳定性表现
  • 实测Taotoken聚合接口在不同时段的响应延迟表现
  • 【审计专栏】【财务领域】第八十八篇 货币效应和货币沉淀和货币的呼吸吐纳 01
  • 第二十一届全国大学生智能车竞赛---疯狂电路组技术手册
  • 多智能体协作模式:串行、并行与混合编排实战
  • CANN/cannbot-skills torch_npu接口列表
  • 机制驱动合成数据:基于多尺度模拟生成生物医学时间序列数据
  • Day59tofixed方法
  • SETI统计建模:点过程与选择偏差如何修正地外文明搜寻
  • 2025届最火的AI学术助手推荐榜单
  • 车规级芯片缺料怎么办?深智微华润微授权代理提供元器件一站式配单与停产替代
  • ClawShield实战:构建个人数据防护盾的模块化方案
  • Mermaid Live Editor完全指南:如何用代码快速创建专业图表
  • 一分钱不花!2026每月省20小时省300块的录音文件转文字工具,算完不用真亏大了
  • 对比自行搭建代理与使用Taotoken直连服务的稳定性体感
  • 2026年事业单位/公务员备考神器大横评:AI助力“铁饭碗“梦
  • Hunyuan3 NPU推理优化进度
  • MySQL 核心考点全解:ACID、引擎对比、SQL 执行流程
  • 汽车零部件清洁度检测系统:西恩士满足ISO16232/VDA19双标准 - 工业设备研究社
  • 【审计专栏】【社会科学】【管理科学】第一百篇 人的需求来源01
  • React:useState 函数式更新、useContext 全解析、useReducer 深度解析
  • CANN/cann-learning-hub:vLLM-Ascend推理优化
  • 可解释AI在恶意软件分析中的应用:从黑盒到白盒的实战指南
  • AI能否提升企业生产率?英国微观数据实证研究揭示真相
  • CANN/catlass带步长批量矩阵乘法TLA示例
  • 如何高效使用AssetStudio:Unity资源提取与转换的完整指南