赞
踩
LVGL官方文档:文档链接
LVGL入门教程:简约的入门笔记
本例程针对 lv_port_esp32 工程中的 main.c 代码进行了删减并添加了相应的注释(完整的工程移植见 上一篇 )。应用程序部分(对应 lv_application 函数)并不复杂,运行效果就是白底黑字显示“Hello world”。本文主要是针对代码框架进行浅浅分析,有任何问题烦请大家指正。
#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_freertos_hooks.h" #include "freertos/semphr.h" #include "esp_system.h" #include "driver/gpio.h" #include "lvgl/lvgl.h" #include "lvgl_helpers.h" /********************* * 宏定义 *********************/ #define LV_TICK_PERIOD_MS 1 /********************** * 静态函数原型 **********************/ static void lv_tick_task(void *arg); static void guiTask(void *pvParameter); static void lv_application(void); /********************** * 主函数 **********************/ void app_main() { xTaskCreatePinnedToCore(guiTask, "gui", 4096*2, NULL, 0, NULL, 1); } // 创建一个信号量以处理对lvgl的并发调用 SemaphoreHandle_t xGuiSemaphore; /********************** * guiTask **********************/ static void guiTask(void *pvParameter) { (void) pvParameter; // 创建一个互斥信号量 xGuiSemaphore = xSemaphoreCreateMutex(); // LVGL初始化 lv_init(); lvgl_driver_init(); // 初始化显示缓冲区 lv_color_t* buf1 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA); assert(buf1 != NULL); lv_color_t* buf2 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA); assert(buf2 != NULL); static lv_disp_buf_t disp_buf; uint32_t size_in_px = DISP_BUF_SIZE; lv_disp_buf_init(&disp_buf, buf1, buf2, size_in_px); // 配置和注册显示驱动器 lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.flush_cb = disp_driver_flush; #if defined CONFIG_DISPLAY_ORIENTATION_PORTRAIT || defined CONFIG_DISPLAY_ORIENTATION_PORTRAIT_INVERTED disp_drv.rotated = 1; #endif disp_drv.buffer = &disp_buf; lv_disp_drv_register(&disp_drv); // 创建周期性定时器 const esp_timer_create_args_t periodic_timer_args = { .callback = &lv_tick_task, .name = "periodic_gui" }; esp_timer_handle_t periodic_timer; ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer)); ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, LV_TICK_PERIOD_MS * 1000)); // LVGL应用程序 lv_application(); while (1) { vTaskDelay(pdMS_TO_TICKS(10)); // 如果获取到信号量,则更新图形界面 if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY)) { lv_task_handler(); xSemaphoreGive(xGuiSemaphore); } } // 当任务被删除或系统停止 free(buf1); free(buf2); vTaskDelete(NULL); } /********************** * LVGL应用程序 **********************/ static void lv_application(void) { /* 当使用单色显示器时,只在屏幕中心显示"Hello World"文本 */ /* 获取当前屏幕对象 */ lv_obj_t * scr = lv_disp_get_scr_act(NULL); /* 在当前屏幕上创建一个标签 */ lv_obj_t * label1 = lv_label_create(scr, NULL); /* 修改标签的文本 */ lv_label_set_text(label1, "Hello\nworld"); /* 将标签居中对齐 * NULL表示相对于父对象居中对齐 * 0, 0表示对齐后的x、y偏移量 */ lv_obj_align(label1, NULL, LV_ALIGN_CENTER, 0, 0); } static void lv_tick_task(void *arg) { (void) arg; lv_tick_inc(LV_TICK_PERIOD_MS); }
lv_tick_task 相当于 LVGL 的心跳,可以用来了解动画和其他任务的经过时间,以 LV_TICK_PERIOD_MS 个毫秒为单位告知。
lv_task_handler 放在 while 循环中,每隔一段时间便会被调用,用来更新图形界面。lv_task_handler 在LVGL中是用于处理任务和事件的函数。
这一部分的代码相当于LVGL的初始化,包括配置显示驱动、创建显示缓冲区、注册显示驱动器,并创建一个周期性定时器。可以不用过度关注这一部分的代码。
关于 LVGL 的可视化界面设计器,可以有两种选择:GUI-Guider 或者 SquareLine Studio
相关介绍可以参考 这一篇
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。