重要步骤
在LVGL移植文档https://docs.lvgl.io/8.3/porting/project.html中, 总共有5个重要步骤:
- 调用lv_init() :lvgl的初始化核心
- 初始化我们自己的屏幕驱动相关,I2C,SPI,ST7789,CST816T等
- 调用lv_port_disp_init()(负责显示部分) 和 lv_port_indev_init()(负责输入部分)
- 调用lv_tick_inc(x) :这个是负责维持lvgl核心库的心跳
- 调用lv_timer_handler(): 负责lvgl中的相关任务
前面1,2,3个步骤都是与初始化相关,我们把它们写在启动任务中
static void start_task() {taskENTER_CRITICAL();lv_init();lv_port_disp_init();lv_port_indev_init();vTaskDelete(start_handler);taskEXIT_CRITICAL();}
lv_tick_inc(x)
我们需要维持lvgl自身的心跳,以便让它能够处理它自身内部的任务,例如动画的渲染,长按单击事件的判断等等, 我们将这个函数放到FreeRTOS的调用函数中
例如,我们在main.c文件中定义如下名称函数:
void vApplicationTickHook( void ){lv_tick_inc(1);}
注意,定义了这个函数,我们还需要打开它对应的宏,在FreeRTOSConfig.h文件中第57行
#define configUSE_TICK_HOOK 1
lv_timer_handler()
lvgl中的所有的任务处理都在这个函数里,lvgl是线程不安全的,这个函数同时只能有一个线程调用它,保险起见我们需要给它的调用加一把锁
声明一把锁
SemaphoreHandle_t xMutex;
初始化这把锁
xMutex = xSemaphoreCreateMutex();
创建一个任务
xTaskCreate(lvgl_timer_task, "lvgl_timer_task", 1024, NULL, 4, NULL);
编写任务的内容
void lvgl_timer_task(void * pvParameters){xMutex = xSemaphoreCreateMutex();lv_obj_t * btn2 = lv_btn_create(lv_scr_act());lv_obj_set_size(btn2,100,100);lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 0);lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);lv_obj_t * label2 = lv_label_create(btn2);lv_label_set_text(label2, "Toggle");lv_obj_center(label2);while(1){if(pdTRUE == xSemaphoreTake(xMutex,portMAX_DELAY)){lv_timer_handler();xSemaphoreGive(xMutex);}vTaskDelay(pdMS_TO_TICKS(1));}}
创建刷新的任务
static void lvgl_refresh_task() {lv_obj_t * label = lv_label_create(lv_scr_act());lv_label_set_text(label, "count:");lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_BLUE), 0);lv_obj_set_pos(label,10,10);int count = 0;while(1) {lv_label_set_text_fmt(label,"count:%d",count);count++;vTaskDelay(pdMS_TO_TICKS(1000));printf("task1 \r\n");}}
完整示例代码
#include "gd32f4xx.h"#include "systick.h"#include <stdio.h>#include <string.h>#include "main.h"#include "bsp_usart.h"#include "FreeRTOS.h"#include "task.h"#include "lvgl.h"#include "lv_port_disp.h"#include "lv_port_indev.h"#include "i2c.h"#include "st7789.h"#include "semphr.h"static TaskHandle_t start_handler;static SemaphoreHandle_t xMutex;void Usart0_recv(uint8_t *data, uint32_t len) {printf("Usart0_recv:%s \r\n",data);}static void lvgl_refresh_task() {lv_obj_t * label = lv_label_create(lv_scr_act());lv_label_set_text(label, "count:");lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_BLUE), 0);lv_obj_set_pos(label,10,10);int count = 0;while(1) {lv_label_set_text_fmt(label,"count:%d",count);count++;vTaskDelay(pdMS_TO_TICKS(1000));printf("task1 \r\n");}}void lvgl_timer_task(void * pvParameters){xMutex = xSemaphoreCreateMutex();lv_obj_t * btn2 = lv_btn_create(lv_scr_act());lv_obj_set_size(btn2,100,100);lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 0);lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);lv_obj_t * label2 = lv_label_create(btn2);lv_label_set_text(label2, "Toggle");lv_obj_center(label2);printf("lcd_refresh_tas\r\n");while(1){if(pdTRUE == xSemaphoreTake(xMutex,portMAX_DELAY)){lv_timer_handler();xSemaphoreGive(xMutex);}vTaskDelay(pdMS_TO_TICKS(1));}}static void start_task() {taskENTER_CRITICAL();bsp_usart_dma_init(115200);printf("start123\r\n");I2C_init();lv_init();lv_port_disp_init();lv_port_indev_init();xTaskCreate(lvgl_timer_task, "lvgl_timer_task", 1024, NULL, 4, NULL);xTaskCreate(lvgl_refresh_task, "lvgl_refresh_task", 256, NULL, 4, NULL);vTaskDelete(start_handler);taskEXIT_CRITICAL();}int main(void){nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);systick_config();xTaskCreate(start_task, "start_task", 512, NULL, 1, &start_handler);vTaskStartScheduler();while(1) {}}void vApplicationTickHook( void ){lv_tick_inc(1);}
