Edit online

LVGL 整体流程

../images/key_process1.png
1. 整体流程

LVGL 框架的运行都是基于 LVGL 中定义的”Timer”定时器,系统需要给 LVGL 一个“心跳”, LVGL 才能正常的运转起来,两个关键的函数:

  • lv_tick_get(), 获取以 ms 为单位的 tick 时间

  • lv_timer_handler(),在 while 循环中的基于定时器的任务处理,函数 handler 会调用 lv_timer_handler, lv_tick_get 决定了 handler 基于定时器的任务处理的时间的准确性

其中在文件 c 中的 lv_tick_get 的实现代码如下:
uint32_t lv_tick_get(void)
{
#if LV_TICK_CUSTOM == 0

    /*If `lv_tick_inc` is called from an interrupt while `sys_time` is read
    *the result might be corrupted.
    *This loop detects if `lv_tick_inc` was called while reading `sys_time`.
    *If `tick_irq_flag` was cleared in `lv_tick_inc` try to read again
    *until `tick_irq_flag` remains `1`.*/
    uint32_t result;
    do {
        tick_irq_flag = 1;
        result        = sys_time;
    } while(!tick_irq_flag); /*Continue until see a non interrupted cycle*/

    return result;
#else
    return LV_TICK_CUSTOM_SYS_TIME_EXPR;
#endif
}
在头文件 h 中定义了上述函数中的 LV_TICK_CUSTOM_SYS_TIME_EXPR
#define LV_TICK_CUSTOM 1
#define LV_TICK_CUSTOM_INCLUDE LV_RTTHREAD_INCLUDE
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (rt_tick_get_millisecond())    /*Expression evaluating to current system time in ms*/
创建 LVGL 线程的代码如下所示:
static void lvgl_thread_entry(void *parameter)
{
#if LV_USE_LOG
    lv_log_register_print_cb(lv_rt_log);
#endif /* LV_USE_LOG */
    lv_init();
    lv_port_disp_init();
    lv_port_indev_init();
    lv_user_gui_init();

    /* handle the tasks of LVGL */
    while(1)
    {
        lv_task_handler();
        rt_thread_mdelay(SLEEP_PERIOD);
    }
}

int lvgl_thread_init(void)
{
    rt_err_t err;

    err = rt_thread_init(&lvgl_thread, "LVGL", lvgl_thread_entry, RT_NULL,
        &lvgl_thread_stack[0], sizeof(lvgl_thread_stack), LPKG_LVGL_THREAD_PRIO, 0);
    if(err != RT_EOK)
    {
        LOG_E("Failed to create LVGL thread");
        return -1;
    }
    rt_thread_startup(&lvgl_thread);

    return 0;
}

用户只需要实现三个函数 lv_port_disp_init()、lv_port_indev_init()、lv_user_gui_init():

  • 其中在函数 lv_port_disp_init()中实现显示接口的对接以及硬件 2D 加速的对接

  • 在函数 lv_port_indev_init()中实现触摸屏的对接

  • 在函数 lv_user_gui_init()中适配不同 UI 界面的初始化