重要步骤

在LVGL移植文档https://docs.lvgl.io/8.3/porting/project.html中, 总共有5个重要步骤:

  1. 调用lv_init() :lvgl的初始化核心
  2. 初始化我们自己的屏幕驱动相关,I2C,SPI,ST7789,CST816T等
  3. 调用lv_port_disp_init()(负责显示部分) 和 lv_port_indev_init()(负责输入部分)
  4. 调用lv_tick_inc(x) :这个是负责维持lvgl核心库的心跳
  5. 调用lv_timer_handler(): 负责lvgl中的相关任务

前面1,2,3个步骤都是与初始化相关,我们把它们写在启动任务中

  1. static void start_task() {
  2. taskENTER_CRITICAL();
  3. lv_init();
  4. lv_port_disp_init();
  5. lv_port_indev_init();
  6. vTaskDelete(start_handler);
  7. taskEXIT_CRITICAL();
  8. }

lv_tick_inc(x)

我们需要维持lvgl自身的心跳,以便让它能够处理它自身内部的任务,例如动画的渲染,长按单击事件的判断等等, 我们将这个函数放到FreeRTOS的调用函数中
例如,我们在main.c文件中定义如下名称函数:

  1. void vApplicationTickHook( void ){
  2. lv_tick_inc(1);
  3. }

注意,定义了这个函数,我们还需要打开它对应的宏,在FreeRTOSConfig.h文件中第57行

  1. #define configUSE_TICK_HOOK 1

lv_timer_handler()

lvgl中的所有的任务处理都在这个函数里,lvgl是线程不安全的,这个函数同时只能有一个线程调用它,保险起见我们需要给它的调用加一把锁

声明一把锁

  1. SemaphoreHandle_t xMutex;

初始化这把锁

  1. xMutex = xSemaphoreCreateMutex();

创建一个任务

  1. xTaskCreate(lvgl_timer_task, "lvgl_timer_task", 1024, NULL, 4, NULL);

编写任务的内容

  1. void lvgl_timer_task(void * pvParameters)
  2. {
  3. xMutex = xSemaphoreCreateMutex();
  4. lv_obj_t * btn2 = lv_btn_create(lv_scr_act());
  5. lv_obj_set_size(btn2,100,100);
  6. lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 0);
  7. lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
  8. lv_obj_t * label2 = lv_label_create(btn2);
  9. lv_label_set_text(label2, "Toggle");
  10. lv_obj_center(label2);
  11. while(1)
  12. {
  13. if(pdTRUE == xSemaphoreTake(xMutex,portMAX_DELAY))
  14. {
  15. lv_timer_handler();
  16. xSemaphoreGive(xMutex);
  17. }
  18. vTaskDelay(pdMS_TO_TICKS(1));
  19. }
  20. }

创建刷新的任务

  1. static void lvgl_refresh_task() {
  2. lv_obj_t * label = lv_label_create(lv_scr_act());
  3. lv_label_set_text(label, "count:");
  4. lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_BLUE), 0);
  5. lv_obj_set_pos(label,10,10);
  6. int count = 0;
  7. while(1) {
  8. lv_label_set_text_fmt(label,"count:%d",count);
  9. count++;
  10. vTaskDelay(pdMS_TO_TICKS(1000));
  11. printf("task1 \r\n");
  12. }
  13. }

完整示例代码

  1. #include "gd32f4xx.h"
  2. #include "systick.h"
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include "main.h"
  6. #include "bsp_usart.h"
  7. #include "FreeRTOS.h"
  8. #include "task.h"
  9. #include "lvgl.h"
  10. #include "lv_port_disp.h"
  11. #include "lv_port_indev.h"
  12. #include "i2c.h"
  13. #include "st7789.h"
  14. #include "semphr.h"
  15. static TaskHandle_t start_handler;
  16. static SemaphoreHandle_t xMutex;
  17. void Usart0_recv(uint8_t *data, uint32_t len) {
  18. printf("Usart0_recv:%s \r\n",data);
  19. }
  20. static void lvgl_refresh_task() {
  21. lv_obj_t * label = lv_label_create(lv_scr_act());
  22. lv_label_set_text(label, "count:");
  23. lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_BLUE), 0);
  24. lv_obj_set_pos(label,10,10);
  25. int count = 0;
  26. while(1) {
  27. lv_label_set_text_fmt(label,"count:%d",count);
  28. count++;
  29. vTaskDelay(pdMS_TO_TICKS(1000));
  30. printf("task1 \r\n");
  31. }
  32. }
  33. void lvgl_timer_task(void * pvParameters)
  34. {
  35. xMutex = xSemaphoreCreateMutex();
  36. lv_obj_t * btn2 = lv_btn_create(lv_scr_act());
  37. lv_obj_set_size(btn2,100,100);
  38. lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 0);
  39. lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
  40. lv_obj_t * label2 = lv_label_create(btn2);
  41. lv_label_set_text(label2, "Toggle");
  42. lv_obj_center(label2);
  43. printf("lcd_refresh_tas\r\n");
  44. while(1)
  45. {
  46. if(pdTRUE == xSemaphoreTake(xMutex,portMAX_DELAY))
  47. {
  48. lv_timer_handler();
  49. xSemaphoreGive(xMutex);
  50. }
  51. vTaskDelay(pdMS_TO_TICKS(1));
  52. }
  53. }
  54. static void start_task() {
  55. taskENTER_CRITICAL();
  56. bsp_usart_dma_init(115200);
  57. printf("start123\r\n");
  58. I2C_init();
  59. lv_init();
  60. lv_port_disp_init();
  61. lv_port_indev_init();
  62. xTaskCreate(lvgl_timer_task, "lvgl_timer_task", 1024, NULL, 4, NULL);
  63. xTaskCreate(lvgl_refresh_task, "lvgl_refresh_task", 256, NULL, 4, NULL);
  64. vTaskDelete(start_handler);
  65. taskEXIT_CRITICAL();
  66. }
  67. int main(void)
  68. {
  69. nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
  70. systick_config();
  71. xTaskCreate(start_task, "start_task", 512, NULL, 1, &start_handler);
  72. vTaskStartScheduler();
  73. while(1) {
  74. }
  75. }
  76. void vApplicationTickHook( void ){
  77. lv_tick_inc(1);
  78. }