1. 刷新疑问

前面在将 lvgl 对接到屏幕驱动时可以知道 lvgl 可以支持局部刷新,所谓的局部刷新就是比如屏幕中显示了多个组件,比如有按钮,有标签,还有进度条,这时如果仅仅标签的内容发生变化那么 lvgl 只会将标签所在的屏幕位置内容重新刷新,所谓重新刷新就是将更新后的显存内容(内容即颜色数据)通过屏幕数据线重新传递给屏幕进行显示。

这时就会产生疑问,lvgl 并没有给用户提供通知刷新的函数接口,lvgl 又是怎么知道标签的内容被改变了呢,lvgl 又怎么知道需要刷新位置具体的坐标呢

2. lvgl 线程

lvgl 共有三个线程,其中主线程一个,和在主线程的 hal_init 函数中创建的另两个 sdl 线程。
主线程完成一系列初始化工作后,循环每 10ms 调用在 lv_init 函数中注册的三个任务,indev_proc_task(输入设备处理函数,procprocess 缩写),lv_refr_task(图形刷新任务,referrefresh 缩写),anim_task(动画任务),这三个任务中需要注意的是每 50ms 处理一次的输入处理 indev_proc_task 任务和每 30ms 处理一次的画面刷新 lv_refr_task 任务。

monitor_sdl_refr_thread 线程负责输出图像和鼠标键盘的输入处理,每次处理后 sleep 50ms。tick_thread 线程每 5ms 增加计时变量一次,用来为全局提供时间参考。

3. 输入检测

monitor_sdl_refr_thread 线程:当鼠标按下,记录鼠标位置数据。

主线程:在 indev_proc_task 中读取鼠标位置数据,和控件位置比较,得到控件指针,调用控件 signal_func 函数,此函数再调用 lv_btn_set_state(btn, LV_BTN_STATE_PR) 设置按钮状态为按下状态,此时画面并没有实际更新,可以看成是发出了画面更新请求。

lv_refr_task:任务处理收到的画面更新请求,实际上是修改了画面变量 tft_fb

monitor_sdl_refr_thread 线程:根据变量 tft_fb 的值更新画面。

4. 画面刷新

lv_refr_task(30ms调用一次)
	lv_refr_areas
		lv_refr_area_with_vdb
			lv_refr_area_part_vdb
				lv_vdb_flush
					lv_disp_flush(vdb_act->area.x1, vdb_act->area.y1, vdb_act->area.x2, vdb_act->area.y2, vdb_act->buf);
						active->driver.disp_flush(x1, y1, x2, y2, color_p);实现画面刷新
						

active->driver.disp_flush:在初始化的时候进行注册,如下:
    lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/
    lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/

    /*Set up the functions to access to your display*/
    disp_drv.disp_flush = ex_disp_flush;     

从上方程序中的层层调用中可以发现最终调用了 driver.disp_flush(x1, y1, x2, y2, color_p) 函数,该函数就是移植时我们对接给 lvgl 对接屏幕驱动的函数,到这里屏幕才真正的更新内容。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐