前言
- 上篇博客整合了lvgl到项目中,采用的是自己编写源码的方式,实现了个简单的界面。
- 实际过程中一般情况开发界面都借助设计工具,这里使用的是gui guider来进行示例记录
项目结构(生成代码路径依然放到项目路径下)
CMakeLists配置(改为引用LVGL的源码)
file(GLOB_RECURSE EmWinSrcEmWin/Source/*.cEmWin/Resource/*.c
)file(GLOB_RECURSE LVGL_SRCLVGL/Code/*.c
)set(LVGL_INCLVGL/Code/customLVGL/Code/generatedLVGL/Code/generated/guider_fontsLVGL/Code/generated/guider_customer_fonts)target_sources(${PROJECT_NAME}.elfPRIVATE${LVGL_SRC})target_include_directories(${PROJECT_NAME}.elfPUBLIC${LVGL_INC}
)
LVGL任务线程调整
/** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2024-4-20 shchl first version*/
#include "includes.h"
#include "lv_api_map.h"#if 1#define APP_TASK_GUI_LVGL_PRIO 15
#define APP_TASK_GUI_LVGL_STK_SIZE 4096/*
*******************************************************************************************************
* 外部引入变量
*******************************************************************************************************
*//*
*******************************************************************************************************
* 变量
*******************************************************************************************************
*/
TX_THREAD gui_lvgl_thread;
VOID *gui_thread_stack_area;
/*
*********************************************************************************************************
* 静态全局变量
*********************************************************************************************************
*//*
*********************************************************************************************************
* 函数声明
*********************************************************************************************************
*/
static VOID gui_lvgl_thread_entry(ULONG input);/*
*********************************************************************************************************
* 外部函数
*********************************************************************************************************
*/
/*** @brief cpu 状态任务* @param first_thread 第一个启动的任务线程首地址*/
int tx_task_gui_lvgl_create() {UINT status;gui_thread_stack_area = app_malloc(APP_TASK_GUI_LVGL_STK_SIZE);if(!gui_thread_stack_area){tx_printf("app malloc error\r\n");return -1;}status = tx_thread_create(&gui_lvgl_thread, /* 任务控制块地址 */"gui lvgl thread", /* 任务名 */gui_lvgl_thread_entry, /* 启动任务函数地址 */0, /* 传递给任务的参数 */gui_thread_stack_area, /* 堆栈基地址 */APP_TASK_GUI_LVGL_STK_SIZE, /* 堆栈空间大小 */APP_TASK_GUI_LVGL_PRIO, /* 任务优先级*/APP_TASK_GUI_LVGL_PRIO, /* 任务抢占阀值 */TX_NO_TIME_SLICE, /* 不开启时间片 */TX_AUTO_START); /* 创建后立即启动 */if (status) {tx_printf("create error:%d\r\n",status);}return TX_SUCCESS;
}TX_THREAD_EXPORT(tx_task_gui_lvgl_create);/*
*********************************************************************************************************
* 内部函数
*********************************************************************************************************
*/
#include "gui_guider.h"
#include "events_init.h"
lv_ui guider_ui;static VOID gui_lvgl_thread_entry(ULONG input) {setup_ui(&guider_ui);events_init(&guider_ui);while (1) {lv_task_handler();tx_thread_sleep(5);}}#endif
测试界面
通过软件添加3个事件
代码事件中添加日志
将移动代码的获取新值的回调函数替换成自己的(原有的基础上加个输出)
/** Copyright 2024 NXP* SPDX-License-Identifier: MIT* The auto-generated can only be used on NXP devices*/#include "events_init.h"
#include <stdio.h>
#include "lvgl.h"void events_init(lv_ui *ui) {
}int32_t lv_anim_path_ease_in2(const lv_anim_t *a);static void screen_1_btn_1_event_handler(lv_event_t *e) {lv_event_code_t code = lv_event_get_code(e);lv_anim_t screen_1_led_1_anim_x;lv_anim_t screen_1_led_1_anim_y;switch (code) {case LV_EVENT_CLICKED: {lv_obj_set_style_bg_color(guider_ui.screen_1_spangroup_1, lv_color_make(0xd2, 0x1e, 0x1e), LV_PART_MAIN);lv_obj_set_pos(guider_ui.screen_1_led_1, 0, 0);//Write animation: screen_1_led_1move in x directionlv_anim_init(&screen_1_led_1_anim_x);lv_anim_set_var(&screen_1_led_1_anim_x, guider_ui.screen_1_led_1);lv_anim_set_time(&screen_1_led_1_anim_x, 10000);lv_anim_set_exec_cb(&screen_1_led_1_anim_x, (lv_anim_exec_xcb_t) lv_obj_set_x);lv_anim_set_values(&screen_1_led_1_anim_x, lv_obj_get_x(guider_ui.screen_1_led_1), 0);lv_anim_set_path_cb(&screen_1_led_1_anim_x, &lv_anim_path_ease_in2);lv_anim_start(&screen_1_led_1_anim_x);//Write animation: screen_1_led_1move in y directionlv_anim_init(&screen_1_led_1_anim_y);lv_anim_set_var(&screen_1_led_1_anim_y, guider_ui.screen_1_led_1);lv_anim_set_time(&screen_1_led_1_anim_y, 10000);lv_anim_set_exec_cb(&screen_1_led_1_anim_y, (lv_anim_exec_xcb_t) lv_obj_set_y);lv_anim_set_values(&screen_1_led_1_anim_y, lv_obj_get_y(guider_ui.screen_1_led_1), 0);lv_anim_set_path_cb(&screen_1_led_1_anim_y, &lv_anim_path_ease_in2);lv_anim_start(&screen_1_led_1_anim_y);logInfo("screen_1_btn_1_event_handler");}break;default:break;}
}static void screen_1_btn_2_event_handler(lv_event_t *e) {lv_event_code_t code = lv_event_get_code(e);lv_anim_t screen_1_led_1_anim_x;lv_anim_t screen_1_led_1_anim_y;switch (code) {case LV_EVENT_CLICKED: {lv_obj_set_pos(guider_ui.screen_1_led_1, 0, 0);//Write animation: screen_1_led_1move in x directionlv_anim_init(&screen_1_led_1_anim_x);lv_anim_set_var(&screen_1_led_1_anim_x, guider_ui.screen_1_led_1);lv_anim_set_time(&screen_1_led_1_anim_x, 10000);lv_anim_set_exec_cb(&screen_1_led_1_anim_x, (lv_anim_exec_xcb_t) lv_obj_set_x);lv_anim_set_values(&screen_1_led_1_anim_x, lv_obj_get_x(guider_ui.screen_1_led_1), 320);lv_anim_set_path_cb(&screen_1_led_1_anim_x, &lv_anim_path_ease_in2);lv_anim_start(&screen_1_led_1_anim_x);//Write animation: screen_1_led_1move in y directionlv_anim_init(&screen_1_led_1_anim_y);lv_anim_set_var(&screen_1_led_1_anim_y, guider_ui.screen_1_led_1);lv_anim_set_time(&screen_1_led_1_anim_y, 10000);lv_anim_set_exec_cb(&screen_1_led_1_anim_y, (lv_anim_exec_xcb_t) lv_obj_set_y);lv_anim_set_values(&screen_1_led_1_anim_y, lv_obj_get_y(guider_ui.screen_1_led_1), 480);lv_anim_set_path_cb(&screen_1_led_1_anim_y, &lv_anim_path_ease_in2);lv_anim_start(&screen_1_led_1_anim_y);tx_printf("screen_1_btn_2_event_handler\r\n");}break;default:break;}
}// 自定义 lv_anim_path_ease_in
int32_t lv_anim_path_ease_in2(const lv_anim_t *a) {static int cnt = 0;if (cnt > 20) { // 刷新20次,打印一次,方便调试lv_coord_t x = lv_obj_get_x(guider_ui.screen_1_led_1);lv_coord_t y = lv_obj_get_y(guider_ui.screen_1_led_1);logInfo("(x,y)-->(%d,%d)", x, y);cnt = 0;} else {cnt += 1;}/*Calculate the current step*/uint32_t t = lv_map(a->act_time, 0, a->time, 0, LV_BEZIER_VAL_MAX);int32_t step = lv_bezier3(t, 0, 50, 100, LV_BEZIER_VAL_MAX);int32_t new_value;new_value = step * (a->end_value - a->start_value);new_value = new_value >> LV_BEZIER_VAL_SHIFT;new_value += a->start_value;return new_value;
}void events_init_screen_1(lv_ui *ui) {lv_obj_add_event_cb(ui->screen_1_btn_1, screen_1_btn_1_event_handler, LV_EVENT_ALL, NULL);lv_obj_add_event_cb(ui->screen_1_btn_2, screen_1_btn_2_event_handler, LV_EVENT_ALL, NULL);
}
总结
- gui guider 基本上不做太复杂的逻辑设计,够用了。