赞
踩
目录
目录
https://lvgl.ioLVGL的官网:https://lvgl.io
LVGL全称Light and Versatile Graphics Library,轻量级通用图形库。
LVGL是一个开源的ui图形库,能跑在各种单片机上(树莓派、荔枝派也行)。支持按钮,触摸,编码器旋钮,鼠标等输入设备。支持高级图形效果,动画、反锯齿、透明度等。LVGL的界面非常精美,可以在官网的先感受一下他的强大,这是它demo的链接。
lvgl对处理器的要求很低,具体可参考下方lvgl官方文档: Layouts — LVGL documentation
使用分辨率480*800的屏幕,触摸是电容屏,处理器stm32f103zet6,板子是正待原子的精英版,用的都是FSMC总线。
下图竖屏模式下 keypad_encoder 的DEMO:
横屏模式下,使用GGUI Guider制作的界面:
正点原子触摸屏资料可以在下面链接下载:stm32f103精英开发板V1(停产) — 正点原子资料下载中心 1.0.0 文档 (openedv.com)
先准备所用到的屏幕的显示和触摸(有触摸功能的屏幕)的工程。我这里用的是正点原子的F103的精英开发板,用到工程是配套的触摸例程(如果你的屏幕没有触摸功能那只需要屏幕的显示例程),用到的只是里面的颜色填充函数和触摸扫描函数。
更改工程名字为touch (养成好习惯,改成英文名,防止各种坑)
不一定要用这个工程,只需要一个屏幕,能显示能触控就行,lvgl用到的屏幕接口只有一个:
- /**
- * @brief 在指定区域内填充指定颜色块
- * @param sx sy ex ey (sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)
- * @param color 要填充的颜色
- */
- void LCD_Color_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color)
对于触摸识别,只需要有一个当前触摸的x、y坐标,有一个触摸按下的标志。当然具体触摸怎么写再看后面的讲解。
- if(tp_dev.sta&0x80)//tp_dev.sta为触摸按下的标记,有触摸的时候最高位标记为1,满足if的条件
- {
- last_x = tp_dev.x[0];//tp_dev.x[0]为触摸芯片读取的x坐标
- last_y = tp_dev.y[0];//tp_dev.y[0]为触摸芯片读取的y坐标
- data->point.x = last_x;//data->point.x为lvgl内部使用
- data->point.y = last_y;
- data->state = LV_INDEV_STATE_PR;//给lvgl标记按下的状态
- }
- else
- {
- data->point.x = last_x;
- data->point.y = last_y;
- data->state = LV_INDEV_STATE_REL
- }
还要准备一个周期为1ms的定时器中断,给LVGL提供心跳,我这里直接用的是例程中的定时器中断实验例程。
以上三点是lvgl最基本的需求。
添加定时器,选择HARDWARE分组,点击Add Files…添加.c文件
点击Add添加。
添加定时器标准库,选择FWLib分组,点击Add Files…添加.c文件
点击Add添加。然后点击OK。
在touch项目根目录下新建GUI和GUI_APP两个文件夹,GUI 目录是用来存放跟 littleVGL 库相关的所有文件的,而 GUI_APP 是用来放我们自己的GUI 应用代码的。
接着我们打开 Keil 工程,点击 图标,打开分组管理面板,在 Groups 栏下新建 GUISRC 、GUIPORTING和GUI_APP 3个分组,GUISRC存放lvgl的源码,GUIPORTING存放lvgl的接口API,GUI_APP存放自己的GUI代码。
编译成功,0错误0警告。到此,我们的工程准备完毕,这是准备好的工程,点击直接下载,本工程就是在正点原子触摸屏实验的基础上加了个定时器中断。
下载成功后,屏幕能显示,并且支持触摸
打开Gitee,直接搜索lvgl。
选择合适的版本,尽量选择v8.0.2以前的版本,因为后我会用到NXP的GUI设计软件,这个软件只支持到v8.0.2。
我这里选择的是v8.0.2,然后下载压缩包。
把lvgl-8.0.2\src文件夹直接复制到新建的GUI文件夹里,这个src里面就是源码
把lvgl-8.0.2\examples\porting文件夹复制到新建的GUI文件夹里,这是移植用的接口
把lvgl-8.0.2目录下的lvgl.h、lv_conf_template.h、LICENCE.txt、README.md一共4个文件复制到新建的GUI文件夹里,后面两个可以不用,不影响移植。
搬运好了代码,我们得给文件改个名字,不然文件内部包含的头文件名字不一致把touch\lvgl目录下的lv_conf_template.h文件名字改成lv_conf.h
把touch\GUI\porting目录下所有文件名字的_template删了,改完之后的样子
把touch\GUI\src路径下的所有.c文件都添加到GUISRC分组,你没有听错,是所有.c文件,包括所有子目录,可以结合Ctrl+A快捷键全选之后再点击添加,提高效率。(这里添加的时候很容易出错,一定要细心),GUISRC组一共133个.c文件(一个一个数的)
把touch\GUI\porting路径下的所有.c文件都添加到GUIPORTING分组
包含文件目录,这里补充一下,如果前面添加定时器时忘记包含文件目录了,这里可以补上。
接着我们需要做 2 个比较重要的小操作,加大项目的栈空间到 2KB 和使能 C99 编译器功能,打开 Core 分组下的.s 启动文件,修改 Stack_Size 的值到 2KB(0x00000800),如Stack_Size EQU 0x00000800 所示,然后点击图标,打开面板之后,切换到 C/C++面板,选 中 C99 Mode 复选框即可,因为 littleVGL 要求 C99 或更新的编译器,否则编译是会报错的。
我们先给lvgl提供心跳让他能够“动”起来:先在timer.c里添加“lvgl.h”头文件,再在定时器中断里调用 lv_tick_inc(1);
- //定时器3中断服务函数
- void TIM3_IRQHandler(void)
- {
- if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
- {
- //LED1=!LED1;//DS1翻转
- TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
- lv_tick_inc(1);//lvgl 1ms的心跳
- }
-
- }
编译一下会发现有很多错误,不急我们慢慢修改。
双击第一条错误提示,
然后跳转到"lv_conf.h"头文件 把最上面的 #if 0 改为 #if 1
同样的,把lv_port_disp.c、lv_port_disp.h、lv_port_indev.c、lv_port_indev.h四个文件的#if 0 都改成#if 1 ,这四个文件包含的头文件名字还需修改,具体看下图。这四个文件中的两个.h文件中,路径为#include "lvgl/lvgl.h"改成#include “lvgl.h”。
随带在lv_port_disp.h文件下添加初始化函数:void lv_port_disp_init(void);
随带在lv_port_indev.h文件下添加初始化函数:void lv_port_indev_init(void);
lv_port_disp.c
lv_port_disp.h
lv_port_indev.c、lv_port_indev.h,和上面类似的操作。
我们再次编译一下,还有几条错误,我继续点击第一条错误提示。发现是 lv_port_disp.c 源文件里的几个宏定义没有定义,我们在 “lv_conf.h”头文件下定义一下。
在lv_conf.h中定义好屏幕的水平像素和垂直像素大小,顺手把LV_COLOR_DEPTH 改成16位(根据实际情况改,如果屏幕是32位色就不用改)
把lv_port_disp.c的里面的example 2 和3都注释了,只留example1,点击编译,编译通过,警告不用管,大多是因为定义了函数但是没有使用而报警告,不影响。
点击全部保存,我们先把keil关闭,在touch目录下,对lvgl文件夹点右键-属性,把只读的选项取消勾选,应用于子文件夹和文件,避免keil重复编译,不然每次点击编译,所有文件都编译一遍,等一万年。
打开keil,为了不让keil每次都把所有代码编译一遍,在设置-Output选项中,不要勾选Create Batch File 创建批处理文件,在设置-Target选项中,不要勾选 使用交叉模块优化,也不要勾选 use Micro LIB,因为LVGL有个二维码的控件使用Micro LIB编译会报错
在lv_port_disp.c文件的顶部包含自己的lcd.h,用于调用lcd相关的接口
根据实际情况,在lv_port_disp.c文件中给disp_drv.hor_res和disp_drv.ver_res两个参数赋值,可以是lcd初始化之后获取的,也可以是固定的
在disp_flush函数中,注释原来的for循环,把自己的LCD填充颜色的函数放进去
- static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
- {
- /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
-
- // int32_t x;
- // int32_t y;
- // for(y = area->y1; y <= area->y2; y++) {
- // for(x = area->x1; x <= area->x2; x++) {
- // /*Put a pixel to the display. For example:*/
- // /*put_px(x, y, *color_p)*/
- // color_p++;
- // }
- // }
- LCD_Color_Fill(area->x1,area->y1,area->x2,area->y2,(u16*)color_p);
- /*IMPORTANT!!!
- *Inform the graphics library that you are ready with the flushing*/
- lv_disp_flush_ready(disp_drv);
- }
到此我们的移植工作一准备完成,接下来就是添加测试代码。
我们现在 main.c 源文件下添加一些要用到的头文件和一些初始化函数。删除原来的一些测试代码
添加测试代码,在lvgl-8.0.2\examples\widgets\led路径中打开lv_example_led_1.c文件,复制lv_example_led_1函数放在main.c文件中。
代码如下:
- void lv_example_led_1(void)
- {
- /*Create a LED and switch it OFF*/
- lv_obj_t * led1 = lv_led_create(lv_scr_act());
- lv_obj_align(led1, LV_ALIGN_CENTER, -80, 0);
- lv_led_off(led1);
-
- /*Copy the previous LED and set a brightness*/
- lv_obj_t * led2 = lv_led_create(lv_scr_act());
- lv_obj_align(led2, LV_ALIGN_CENTER, 0, 0);
- lv_led_set_brightness(led2, 150);
- lv_led_set_color(led2, lv_palette_main(LV_PALETTE_RED));
-
- /*Copy the previous LED and switch it ON*/
- lv_obj_t * led3 = lv_led_create(lv_scr_act());
- lv_obj_align(led3, LV_ALIGN_CENTER, 80, 0);
- lv_led_on(led3);
- }
然后调用。
到这里就能实现屏幕的显示了。
显示效果:
先在 lv_port_indev.c 源文件下添加自己的触摸工程头文件"touch.h",用于调用touch相关的接口和变量。
修改lv_port_indev_init 函数
修改lv_port_indev.c 源文件下的touchpad_read,touchpad_is_pressed,touchpad_get_xy 函数。
touchpad_is_pressed是用来检测是否有触摸操作的。touchpad_get_xy是用来获取被触摸位置的坐标,我们只需要吧触摸驱动中读取的坐标放到这就行了,参数是两个指针,所以直接赋值操作。
- static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
- {
- static lv_coord_t last_x = 0;
- static lv_coord_t last_y = 0;
-
- if(touchpad_is_pressed()) {//判断是否有触摸操作
- touchpad_get_xy(&last_x, &last_y);//读取触摸的坐标
- data->state = LV_INDEV_STATE_PR;//设置被触摸状态
- } else {
- data->state = LV_INDEV_STATE_REL;//清除被触摸状态
- }
-
- /*Set the last pressed coordinates*/
- data->point.x = last_x;
- data->point.y = last_y;
- }
-
- /*Return true is the touchpad is pressed*/
- static bool touchpad_is_pressed(void)
- {
- /*Your code comes here*/
- if(tp_dev.sta&TP_PRES_DOWN)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- /*Get the x and y coordinates if the touchpad is pressed*/
- static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
- {
- /*Your code comes here*/
- (*x) = tp_dev.x[0];
- (*y) = tp_dev.y[0];
-
- //原代码
- // (*x) = 0;
- // (*y) = 0;
- }
在main.c源文件下的while(1)里添加触摸扫描函数:
在touch\GUIAPP目录下新建一个文件夹demos,在keil中新建两个文件保存到demos文件夹中,分别命名为lv_demo_keypad_encoder.c和lv_demo_keypad_encoder.h,然后再GUIAPP分组中添加lv_demo_keypad_encoder.c,包含文件目录。
为lv_demo_keypad_encoder.c添加代码。
- /**
- * @file lv_demo_keypad_encoder.c
- *
- */
- /*********************
- * INCLUDES
- *********************/
- #include "lv_demo_keypad_encoder.h"
- #include "lvgl.h"
- #if 1
-
- static void selectors_create(lv_obj_t * parent);
- static void text_input_create(lv_obj_t * parent);
- static void msgbox_create(void);
-
- static void msgbox_event_cb(lv_event_t * e);
- static void ta_event_cb(lv_event_t * e);
-
- static lv_group_t* g;
- static lv_obj_t * tv;
- static lv_obj_t * t1;
- static lv_obj_t * t2;
-
- void lv_demo_keypad_encoder(void)
- {
- g = lv_group_create();
- lv_group_set_default(g);
-
- lv_indev_t* cur_drv = NULL;
- for (;;) {
- cur_drv = lv_indev_get_next(cur_drv);
- if (!cur_drv) {
- break;
- }
-
- if (cur_drv->driver->type == LV_INDEV_TYPE_KEYPAD) {
- lv_indev_set_group(cur_drv, g);
- }
-
- if (cur_drv->driver->type == LV_INDEV_TYPE_ENCODER) {
- lv_indev_set_group(cur_drv, g);
- }
- }
-
- tv = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, LV_DPI_DEF / 3);
-
- t1 = lv_tabview_add_tab(tv, "Selectors");
- t2 = lv_tabview_add_tab(tv, "Text input");
-
- selectors_create(t1);
- text_input_create(t2);
-
- msgbox_create();
- }
-
- /**********************
- * STATIC FUNCTIONS
- **********************/
- static void selectors_create(lv_obj_t * parent)
- {
- lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
- lv_obj_set_flex_align(parent, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
-
- lv_obj_t * obj;
-
- obj = lv_table_create(parent);
- lv_table_set_cell_value(obj, 0, 0, "00");
- lv_table_set_cell_value(obj, 0, 1, "01");
- lv_table_set_cell_value(obj, 1, 0, "10");
- lv_table_set_cell_value(obj, 1, 1, "11");
- lv_table_set_cell_value(obj, 2, 0, "20");
- lv_table_set_cell_value(obj, 2, 1, "21");
- lv_table_set_cell_value(obj, 3, 0, "30");
- lv_table_set_cell_value(obj, 3, 1, "31");
- lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
-
- obj = lv_calendar_create(parent);
- lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
-
- obj = lv_btnmatrix_create(parent);
- lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
-
- obj = lv_checkbox_create(parent);
- lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
-
- obj = lv_slider_create(parent);
- lv_slider_set_range(obj, 0, 10);
- lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
-
- obj = lv_switch_create(parent);
- lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
-
- obj = lv_spinbox_create(parent);
- lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
-
- obj = lv_dropdown_create(parent);
- lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
-
- obj = lv_roller_create(parent);
- lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
-
- lv_obj_t * list = lv_list_create(parent);
- lv_obj_update_layout(list);
- if(lv_obj_get_height(list) > lv_obj_get_content_height(parent)) {
- lv_obj_set_height(list, lv_obj_get_content_height(parent));
- }
-
- lv_list_add_btn(list, LV_SYMBOL_OK, "Apply");
- lv_list_add_btn(list, LV_SYMBOL_CLOSE, "Close");
- lv_list_add_btn(list, LV_SYMBOL_EYE_OPEN, "Show");
- lv_list_add_btn(list, LV_SYMBOL_EYE_CLOSE, "Hide");
- lv_list_add_btn(list, LV_SYMBOL_TRASH, "Delete");
- lv_list_add_btn(list, LV_SYMBOL_COPY, "Copy");
- lv_list_add_btn(list, LV_SYMBOL_PASTE, "Paste");
- }
-
- static void text_input_create(lv_obj_t * parent)
- {
- lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
-
- lv_obj_t * ta1 = lv_textarea_create(parent);
- lv_obj_set_width(ta1, LV_PCT(100));
- lv_textarea_set_one_line(ta1, true);
- lv_textarea_set_placeholder_text(ta1, "Click with an encoder to show a keyboard");
-
- lv_obj_t * ta2 = lv_textarea_create(parent);
- lv_obj_set_width(ta2, LV_PCT(100));
- lv_textarea_set_one_line(ta2, true);
- lv_textarea_set_placeholder_text(ta2, "Type something");
-
- lv_obj_t *kb = lv_keyboard_create(lv_scr_act());
- lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
-
- lv_obj_add_event_cb(ta1, ta_event_cb, LV_EVENT_ALL, kb);
- lv_obj_add_event_cb(ta2, ta_event_cb, LV_EVENT_ALL, kb);
- }
-
- static void msgbox_create(void)
- {
- static const char * btns[] = {"Ok", "Cancel", ""};
- lv_obj_t * mbox = lv_msgbox_create(NULL, "Hi", "Welcome to the keyboard and encoder demo", btns, false);
- lv_obj_add_event_cb(mbox, msgbox_event_cb, LV_EVENT_ALL, NULL);
- lv_group_focus_obj(lv_msgbox_get_btns(mbox));
- lv_obj_add_state(lv_msgbox_get_btns(mbox), LV_STATE_FOCUS_KEY);
- #if LV_EX_MOUSEWHEEL
- lv_group_set_editing(g, true);
- #endif
- lv_group_focus_freeze(g, true);
-
- lv_obj_align(mbox, LV_ALIGN_CENTER, 0, 0);
-
- lv_obj_t * bg = lv_obj_get_parent(mbox);
- lv_obj_set_style_bg_opa(bg, LV_OPA_70, 0);
- lv_obj_set_style_bg_color(bg, lv_palette_main(LV_PALETTE_GREY), 0);
- }
-
- static void msgbox_event_cb(lv_event_t * e)
- {
- lv_event_code_t code = lv_event_get_code(e);
- lv_obj_t * msgbox = lv_event_get_current_target(e);
-
- if(code == LV_EVENT_VALUE_CHANGED) {
- const char * txt = lv_msgbox_get_active_btn_text(msgbox);
- if(txt) {
- lv_msgbox_close(msgbox);
- lv_group_focus_freeze(g, false);
- lv_group_focus_obj(lv_obj_get_child(t1, 0));
- lv_obj_scroll_to(t1, 0, 0, LV_ANIM_OFF);
-
- }
- }
- }
-
- static void ta_event_cb(lv_event_t * e)
- {
- lv_indev_t * indev = lv_indev_get_act();
- if(indev == NULL) return;
- lv_indev_type_t indev_type = lv_indev_get_type(indev);
-
- lv_event_code_t code = lv_event_get_code(e);
- lv_obj_t * ta = lv_event_get_target(e);
- lv_obj_t * kb = lv_event_get_user_data(e);
-
- if(code == LV_EVENT_CLICKED && indev_type == LV_INDEV_TYPE_ENCODER) {
- lv_keyboard_set_textarea(kb, ta);
- lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN);
- lv_group_focus_obj(kb);
- lv_group_set_editing(lv_obj_get_group(kb), kb);
- lv_obj_set_height(tv, LV_VER_RES / 2);
- lv_obj_align(kb, LV_ALIGN_BOTTOM_MID, 0, 0);
- }
-
- if(code == LV_EVENT_READY || code == LV_EVENT_CANCEL) {
- lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
- lv_obj_set_height(tv, LV_VER_RES);
- }
- }
-
- #endif
-
-
为lv_demo_keypad_encoder.h添加代码。
- /**
- * @file lv_demo_keypad_encoder.h
- *
- */
- #ifndef LV_DEMO_KEYPAD_ENCODER_H
- #define LV_DEMO_KEYPAD_ENCODER_H
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- /*********************
- * INCLUDES
- *********************/
- /*********************
- * DEFINES
- *********************/
- /**********************
- * TYPEDEFS
- **********************/
- /**********************
- * GLOBAL PROTOTYPES
- **********************/
- void lv_demo_keypad_encoder(void);
-
- /**********************
- * MACROS
- **********************/
- #ifdef __cplusplus
- } /* extern "C" */
- #endif
-
- #endif /*LV_DEMO_KEYPAD_ENCODER_H*/
-
-
在main.c源文件下添加头文件
#include "lv_demo_keypad_encoder.h"
注释原来的测试代码调用新代码
编译下载,就可以在板子上看到我们的例程了。并且触摸也没有问题。
触摸驱动相关内容在上文已经成功移植,所以我们只用写主函数中按钮的显示就行。
- static void btn_event_cb(lv_event_t *e)
- {
- lv_event_code_t code = lv_event_get_code(e);
- lv_obj_t *btn = lv_event_get_target(e);
-
- if(code == LV_EVENT_CLICKED)
- {
- static uint8_t cnt = 0;
- cnt++;
-
- lv_obj_t *label = lv_obj_get_child(btn,0);
- lv_label_set_text_fmt(label, "Butten: %d", cnt);
- }
- }
-
- // 在main函数中调用 才能出现效果
- void lv_example_get_started_1(void)
- {
- lv_obj_t * btn = lv_btn_create(lv_scr_act());
- lv_obj_set_pos(btn, 10,10);
- lv_obj_set_size(btn, 120,50);
- lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL);
-
- lv_obj_t *label = lv_label_create(btn);
- lv_label_set_text(label, "Button");
- lv_obj_center(label);
- }
并且在main函数添加lv_example_get_started_1()运行就行
如果一切正常,屏幕上会显示如下,每次点击都会自动加1
什么是 GUI-Guider? GUI Guider 是恩智浦为 LVGL 开发了一个上位机GUI 设计工具,可以通过拖放控件的方式设计 LVGL GUI 页面,加速 GUI 的设计。 设计完成的 GUI 页面可以在 PC 上仿真运行,预览自己设计的UI界面。确认设计完毕之后可以生成 C 代码,再整合到 MCU 项目中。
软件下载地址:https://www.nxp.com.cn/
打开网址搜索GUI Guider选择适合自己的系统的版本。下载安装。
或者直接打开下方链接:
(2). GUI Guider | NXP Semiconductors
对guiguider的操作十分简单,主要步骤如下所述:
1️⃣ 在左侧菜单栏寻找想用的组件
2️⃣ 将左侧菜单栏组件拖入中间的模拟器窗口,并调整组件在模拟器窗口的相对位置
3️⃣ 调整右侧的组件属性进行修改,最终得到想要的效果
4️⃣ 点击运行按钮,生成c语言文件
文件夹及响应特性如下所示:
- custom :用户编写的代码,不会被guiguider所覆盖,可以在此文件中编写用户自己的代码
-
- generated :guiduider所自动生成的代码,会被覆盖,所以最好不要修改此文件夹下的代码
-
- imporrt :导入的文件,如导入的图片或者字体等
-
- lib :关于基础平台的一些文件,如x86文件夹
-
- lvgl :lvgl的源码
-
- lvgl-simulator :模拟器相关内容,显示了一些程序运行的框架,也包含一些接口的使用(如触摸屏等),也不会被工程编译覆盖
-
- temp :与nxp相关的文件,暂时用不到
打开我们刚才的GUI工程目录,下面有一个 generated 文件夹,该文件夹就是我们所需要的,将generated整个文件夹复制到我们的STM32工程中的GUIAPP目录下。
接着打开keil工程在keil工程添加相关的.c源文件和.h头文件路径。
添加.c文件
包含文件路径
然后编译,可能会报错,双击第一条错误提示
接着继续修改其他类似错误。再次编译可能会提示找不到 “lv_font.h” 头文件,记得我们之前在LVGL源码是遇到有这个,所以我们这里把GUI/src路径下的font文件夹路径包含进来。
再次编译,会提示找不到"custom.h"头文件,这里我们把它注释掉。最后编译通过。有时候到这一步会有 error: #8: missing closing quote 这样的错误提示,
解决办法就是:在KEIL中Options for Target ‘Flash’ -> C/C++ -> Misc Controls添加“–locale=english”。
然后再main.c 源文件中添加相关的头文件和代码。
编译下载到板子上,可以看到程序运行屏幕显示我们自己设计的UI界面。
效果如下:
1. STM32移植LVGL(LittleVGL)-CSDN博客
2. STM32移植LVGL8.0.2超详细的保姆级教程附移植好的工程文件_..\..\middlewares\lvgl\lv_hal_disp.c(573): warning-CSDN博客
3. LVGL8.1笔记2–触摸移植(2022-0603)_lvgl鼠标移植-CSDN博客
4. GUI Guider设计UI界面移植到STM32_stm32 gui-CSDN博客
5. GUI Guider与lvgl联合仿真(结合stm32实验进行演示,含触摸屏实验计数器与计算器)_lvgl guier-CSDN博客
6. https://wlink.blog.csdn.net/article/details/114088455
7. lvgl库下载或者GUI Guider在官网下载不了,可以打开我的giteee下载,并且里面也分享了相关程序,和执行视频。
王锦/lvgl的使用 (gitee.com)https://gitee.com/didiao-hhh/the-use-of-lvgl
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。