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
lv_tick_task 相当于 LVGL 的心跳,可以用来了解动画和其他任务的经过时间,以 LV_TICK_PERIOD_MS 个毫秒为单位告知。
lv_task_handler
lv_task_handler 放在 while 循环中,每隔一段时间便会被调用,用来更新图形界面。lv_task_handler 在LVGL中是用于处理任务和事件的函数。
guiTask
这一部分的代码相当于LVGL的初始化,包括配置显示驱动、创建显示缓冲区、注册显示驱动器,并创建一个周期性定时器。可以不用过度关注这一部分的代码。
可视化界面设计器
关于 LVGL 的可视化界面设计器,可以有两种选择:GUI-Guider 或者 SquareLine Studio
相关介绍可以参考 这一篇