当前位置:   article > 正文

LVGL的使用

lvgl

目录

一. 什么是 lvgl

二. 效果

三. 移植前准备工作

1. 准备STM32工程

2. 下载LVGL源码

三. 开始移植

1. 添加lvgl源码到工程文件中

2. 在keil中添加.c文件和包含文件目录。

3. 修改代码

​编辑

4. 添加屏幕接口

5. 添加测试显示代码。

6. 添加触摸接口

7. 触摸按钮测试

四.GUI Guider的使用

1. 什么是GUI Guider

2. 软件使用

3. guiguider文件夹介绍

4.将代码整合到我们的工程

五. 参考链接


目录

一. 什么是 lvgl

二. 效果

三. 移植前准备工作

1、准备STM32工程

2.下载LVGL源码

三. 开始移植

1. 添加lvgl源码到工程文件中

2. 在keil中添加.c文件和包含文件目录。

3. 修改代码

​编辑

4. 添加屏幕接口

5. 添加测试显示代码。

6. 添加触摸接口

7. 触摸按钮测试

四.GUI Guider的使用

1. 什么是GUI Guider

2. 软件使用

3. guiguider文件夹介绍

4.将代码整合到我们的工程

五. 参考链接


一. 什么是 lvgl

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制作的界面:

三. 移植前准备工作

1. 准备STM32工程

正点原子触摸屏资料可以在下面链接下载:stm32f103精英开发板V1(停产) — 正点原子资料下载中心 1.0.0 文档 (openedv.com)

先准备所用到的屏幕的显示和触摸(有触摸功能的屏幕)的工程。我这里用的是正点原子的F103的精英开发板,用到工程是配套的触摸例程(如果你的屏幕没有触摸功能那只需要屏幕的显示例程),用到的只是里面的颜色填充函数和触摸扫描函数。

更改工程名字为touch (养成好习惯,改成英文名,防止各种坑)

不一定要用这个工程,只需要一个屏幕,能显示能触控就行,lvgl用到的屏幕接口只有一个:

  1. /**
  2. * @brief 在指定区域内填充指定颜色块
  3. * @param sx sy ex ey (sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)
  4. * @param color 要填充的颜色
  5. */
  6. void LCD_Color_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color)

对于触摸识别,只需要有一个当前触摸的x、y坐标,有一个触摸按下的标志。当然具体触摸怎么写再看后面的讲解。

  1. if(tp_dev.sta&0x80)//tp_dev.sta为触摸按下的标记,有触摸的时候最高位标记为1,满足if的条件
  2. {
  3. last_x = tp_dev.x[0];//tp_dev.x[0]为触摸芯片读取的x坐标
  4. last_y = tp_dev.y[0];//tp_dev.y[0]为触摸芯片读取的y坐标
  5. data->point.x = last_x;//data->point.x为lvgl内部使用
  6. data->point.y = last_y;
  7. data->state = LV_INDEV_STATE_PR;//给lvgl标记按下的状态
  8. }
  9. else
  10. {
  11. data->point.x = last_x;
  12. data->point.y = last_y;
  13. data->state = LV_INDEV_STATE_REL
  14. }

还要准备一个周期为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警告。到此,我们的工程准备完毕,这是准备好的工程,点击直接下载,本工程就是在正点原子触摸屏实验的基础上加了个定时器中断。

下载成功后,屏幕能显示,并且支持触摸

2. 下载LVGL源码

打开Gitee,直接搜索lvgl。

选择合适的版本,尽量选择v8.0.2以前的版本,因为后我会用到NXP的GUI设计软件,这个软件只支持到v8.0.2。 

我这里选择的是v8.0.2,然后下载压缩包。 

三. 开始移植

1. 添加lvgl源码到工程文件中

把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删了,改完之后的样子

2. 在keil中添加.c文件和包含文件目录。

把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 或更新的编译器,否则编译是会报错的。

3. 修改代码

我们先给lvgl提供心跳让他能够“动”起来:先在timer.c里添加“lvgl.h”头文件,再在定时器中断里调用 lv_tick_inc(1);

  1. //定时器3中断服务函数
  2. void TIM3_IRQHandler(void)
  3. {
  4. if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
  5. {
  6. //LED1=!LED1;//DS1翻转
  7. TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
  8. lv_tick_inc(1);//lvgl 1ms的心跳
  9. }
  10. }

编译一下会发现有很多错误,不急我们慢慢修改。

双击第一条错误提示,

然后跳转到"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编译会报错

4. 添加屏幕接口

在lv_port_disp.c文件的顶部包含自己的lcd.h,用于调用lcd相关的接口

根据实际情况,在lv_port_disp.c文件中给disp_drv.hor_res和disp_drv.ver_res两个参数赋值,可以是lcd初始化之后获取的,也可以是固定的

 在disp_flush函数中,注释原来的for循环,把自己的LCD填充颜色的函数放进去

  1. static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
  2. {
  3. /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
  4. // int32_t x;
  5. // int32_t y;
  6. // for(y = area->y1; y <= area->y2; y++) {
  7. // for(x = area->x1; x <= area->x2; x++) {
  8. // /*Put a pixel to the display. For example:*/
  9. // /*put_px(x, y, *color_p)*/
  10. // color_p++;
  11. // }
  12. // }
  13. LCD_Color_Fill(area->x1,area->y1,area->x2,area->y2,(u16*)color_p);
  14. /*IMPORTANT!!!
  15. *Inform the graphics library that you are ready with the flushing*/
  16. lv_disp_flush_ready(disp_drv);
  17. }

到此我们的移植工作一准备完成,接下来就是添加测试代码。

5. 添加测试显示代码。

我们现在 main.c 源文件下添加一些要用到的头文件和一些初始化函数。删除原来的一些测试代码

添加测试代码,在lvgl-8.0.2\examples\widgets\led路径中打开lv_example_led_1.c文件,复制lv_example_led_1函数放在main.c文件中。
代码如下:

  1. void lv_example_led_1(void)
  2. {
  3. /*Create a LED and switch it OFF*/
  4. lv_obj_t * led1 = lv_led_create(lv_scr_act());
  5. lv_obj_align(led1, LV_ALIGN_CENTER, -80, 0);
  6. lv_led_off(led1);
  7. /*Copy the previous LED and set a brightness*/
  8. lv_obj_t * led2 = lv_led_create(lv_scr_act());
  9. lv_obj_align(led2, LV_ALIGN_CENTER, 0, 0);
  10. lv_led_set_brightness(led2, 150);
  11. lv_led_set_color(led2, lv_palette_main(LV_PALETTE_RED));
  12. /*Copy the previous LED and switch it ON*/
  13. lv_obj_t * led3 = lv_led_create(lv_scr_act());
  14. lv_obj_align(led3, LV_ALIGN_CENTER, 80, 0);
  15. lv_led_on(led3);
  16. }

然后调用。

到这里就能实现屏幕的显示了。

显示效果:

6. 添加触摸接口

先在 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是用来获取被触摸位置的坐标,我们只需要吧触摸驱动中读取的坐标放到这就行了,参数是两个指针,所以直接赋值操作。

  1. static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
  2. {
  3. static lv_coord_t last_x = 0;
  4. static lv_coord_t last_y = 0;
  5. if(touchpad_is_pressed()) {//判断是否有触摸操作
  6. touchpad_get_xy(&last_x, &last_y);//读取触摸的坐标
  7. data->state = LV_INDEV_STATE_PR;//设置被触摸状态
  8. } else {
  9. data->state = LV_INDEV_STATE_REL;//清除被触摸状态
  10. }
  11. /*Set the last pressed coordinates*/
  12. data->point.x = last_x;
  13. data->point.y = last_y;
  14. }
  15. /*Return true is the touchpad is pressed*/
  16. static bool touchpad_is_pressed(void)
  17. {
  18. /*Your code comes here*/
  19. if(tp_dev.sta&TP_PRES_DOWN)
  20. {
  21. return true;
  22. }
  23. else
  24. {
  25. return false;
  26. }
  27. }
  28. /*Get the x and y coordinates if the touchpad is pressed*/
  29. static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
  30. {
  31. /*Your code comes here*/
  32. (*x) = tp_dev.x[0];
  33. (*y) = tp_dev.y[0];
  34. //原代码
  35. // (*x) = 0;
  36. // (*y) = 0;
  37. }

在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添加代码。

  1. /**
  2. * @file lv_demo_keypad_encoder.c
  3. *
  4. */
  5. /*********************
  6. * INCLUDES
  7. *********************/
  8. #include "lv_demo_keypad_encoder.h"
  9. #include "lvgl.h"
  10. #if 1
  11. static void selectors_create(lv_obj_t * parent);
  12. static void text_input_create(lv_obj_t * parent);
  13. static void msgbox_create(void);
  14. static void msgbox_event_cb(lv_event_t * e);
  15. static void ta_event_cb(lv_event_t * e);
  16. static lv_group_t* g;
  17. static lv_obj_t * tv;
  18. static lv_obj_t * t1;
  19. static lv_obj_t * t2;
  20. void lv_demo_keypad_encoder(void)
  21. {
  22. g = lv_group_create();
  23. lv_group_set_default(g);
  24. lv_indev_t* cur_drv = NULL;
  25. for (;;) {
  26. cur_drv = lv_indev_get_next(cur_drv);
  27. if (!cur_drv) {
  28. break;
  29. }
  30. if (cur_drv->driver->type == LV_INDEV_TYPE_KEYPAD) {
  31. lv_indev_set_group(cur_drv, g);
  32. }
  33. if (cur_drv->driver->type == LV_INDEV_TYPE_ENCODER) {
  34. lv_indev_set_group(cur_drv, g);
  35. }
  36. }
  37. tv = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, LV_DPI_DEF / 3);
  38. t1 = lv_tabview_add_tab(tv, "Selectors");
  39. t2 = lv_tabview_add_tab(tv, "Text input");
  40. selectors_create(t1);
  41. text_input_create(t2);
  42. msgbox_create();
  43. }
  44. /**********************
  45. * STATIC FUNCTIONS
  46. **********************/
  47. static void selectors_create(lv_obj_t * parent)
  48. {
  49. lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
  50. lv_obj_set_flex_align(parent, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
  51. lv_obj_t * obj;
  52. obj = lv_table_create(parent);
  53. lv_table_set_cell_value(obj, 0, 0, "00");
  54. lv_table_set_cell_value(obj, 0, 1, "01");
  55. lv_table_set_cell_value(obj, 1, 0, "10");
  56. lv_table_set_cell_value(obj, 1, 1, "11");
  57. lv_table_set_cell_value(obj, 2, 0, "20");
  58. lv_table_set_cell_value(obj, 2, 1, "21");
  59. lv_table_set_cell_value(obj, 3, 0, "30");
  60. lv_table_set_cell_value(obj, 3, 1, "31");
  61. lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
  62. obj = lv_calendar_create(parent);
  63. lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
  64. obj = lv_btnmatrix_create(parent);
  65. lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
  66. obj = lv_checkbox_create(parent);
  67. lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
  68. obj = lv_slider_create(parent);
  69. lv_slider_set_range(obj, 0, 10);
  70. lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
  71. obj = lv_switch_create(parent);
  72. lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
  73. obj = lv_spinbox_create(parent);
  74. lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
  75. obj = lv_dropdown_create(parent);
  76. lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
  77. obj = lv_roller_create(parent);
  78. lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
  79. lv_obj_t * list = lv_list_create(parent);
  80. lv_obj_update_layout(list);
  81. if(lv_obj_get_height(list) > lv_obj_get_content_height(parent)) {
  82. lv_obj_set_height(list, lv_obj_get_content_height(parent));
  83. }
  84. lv_list_add_btn(list, LV_SYMBOL_OK, "Apply");
  85. lv_list_add_btn(list, LV_SYMBOL_CLOSE, "Close");
  86. lv_list_add_btn(list, LV_SYMBOL_EYE_OPEN, "Show");
  87. lv_list_add_btn(list, LV_SYMBOL_EYE_CLOSE, "Hide");
  88. lv_list_add_btn(list, LV_SYMBOL_TRASH, "Delete");
  89. lv_list_add_btn(list, LV_SYMBOL_COPY, "Copy");
  90. lv_list_add_btn(list, LV_SYMBOL_PASTE, "Paste");
  91. }
  92. static void text_input_create(lv_obj_t * parent)
  93. {
  94. lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
  95. lv_obj_t * ta1 = lv_textarea_create(parent);
  96. lv_obj_set_width(ta1, LV_PCT(100));
  97. lv_textarea_set_one_line(ta1, true);
  98. lv_textarea_set_placeholder_text(ta1, "Click with an encoder to show a keyboard");
  99. lv_obj_t * ta2 = lv_textarea_create(parent);
  100. lv_obj_set_width(ta2, LV_PCT(100));
  101. lv_textarea_set_one_line(ta2, true);
  102. lv_textarea_set_placeholder_text(ta2, "Type something");
  103. lv_obj_t *kb = lv_keyboard_create(lv_scr_act());
  104. lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
  105. lv_obj_add_event_cb(ta1, ta_event_cb, LV_EVENT_ALL, kb);
  106. lv_obj_add_event_cb(ta2, ta_event_cb, LV_EVENT_ALL, kb);
  107. }
  108. static void msgbox_create(void)
  109. {
  110. static const char * btns[] = {"Ok", "Cancel", ""};
  111. lv_obj_t * mbox = lv_msgbox_create(NULL, "Hi", "Welcome to the keyboard and encoder demo", btns, false);
  112. lv_obj_add_event_cb(mbox, msgbox_event_cb, LV_EVENT_ALL, NULL);
  113. lv_group_focus_obj(lv_msgbox_get_btns(mbox));
  114. lv_obj_add_state(lv_msgbox_get_btns(mbox), LV_STATE_FOCUS_KEY);
  115. #if LV_EX_MOUSEWHEEL
  116. lv_group_set_editing(g, true);
  117. #endif
  118. lv_group_focus_freeze(g, true);
  119. lv_obj_align(mbox, LV_ALIGN_CENTER, 0, 0);
  120. lv_obj_t * bg = lv_obj_get_parent(mbox);
  121. lv_obj_set_style_bg_opa(bg, LV_OPA_70, 0);
  122. lv_obj_set_style_bg_color(bg, lv_palette_main(LV_PALETTE_GREY), 0);
  123. }
  124. static void msgbox_event_cb(lv_event_t * e)
  125. {
  126. lv_event_code_t code = lv_event_get_code(e);
  127. lv_obj_t * msgbox = lv_event_get_current_target(e);
  128. if(code == LV_EVENT_VALUE_CHANGED) {
  129. const char * txt = lv_msgbox_get_active_btn_text(msgbox);
  130. if(txt) {
  131. lv_msgbox_close(msgbox);
  132. lv_group_focus_freeze(g, false);
  133. lv_group_focus_obj(lv_obj_get_child(t1, 0));
  134. lv_obj_scroll_to(t1, 0, 0, LV_ANIM_OFF);
  135. }
  136. }
  137. }
  138. static void ta_event_cb(lv_event_t * e)
  139. {
  140. lv_indev_t * indev = lv_indev_get_act();
  141. if(indev == NULL) return;
  142. lv_indev_type_t indev_type = lv_indev_get_type(indev);
  143. lv_event_code_t code = lv_event_get_code(e);
  144. lv_obj_t * ta = lv_event_get_target(e);
  145. lv_obj_t * kb = lv_event_get_user_data(e);
  146. if(code == LV_EVENT_CLICKED && indev_type == LV_INDEV_TYPE_ENCODER) {
  147. lv_keyboard_set_textarea(kb, ta);
  148. lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN);
  149. lv_group_focus_obj(kb);
  150. lv_group_set_editing(lv_obj_get_group(kb), kb);
  151. lv_obj_set_height(tv, LV_VER_RES / 2);
  152. lv_obj_align(kb, LV_ALIGN_BOTTOM_MID, 0, 0);
  153. }
  154. if(code == LV_EVENT_READY || code == LV_EVENT_CANCEL) {
  155. lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
  156. lv_obj_set_height(tv, LV_VER_RES);
  157. }
  158. }
  159. #endif

为lv_demo_keypad_encoder.h添加代码。

  1. /**
  2. * @file lv_demo_keypad_encoder.h
  3. *
  4. */
  5. #ifndef LV_DEMO_KEYPAD_ENCODER_H
  6. #define LV_DEMO_KEYPAD_ENCODER_H
  7. #ifdef __cplusplus
  8. extern "C" {
  9. #endif
  10. /*********************
  11. * INCLUDES
  12. *********************/
  13. /*********************
  14. * DEFINES
  15. *********************/
  16. /**********************
  17. * TYPEDEFS
  18. **********************/
  19. /**********************
  20. * GLOBAL PROTOTYPES
  21. **********************/
  22. void lv_demo_keypad_encoder(void);
  23. /**********************
  24. * MACROS
  25. **********************/
  26. #ifdef __cplusplus
  27. } /* extern "C" */
  28. #endif
  29. #endif /*LV_DEMO_KEYPAD_ENCODER_H*/

在main.c源文件下添加头文件

#include "lv_demo_keypad_encoder.h"

注释原来的测试代码调用新代码

编译下载,就可以在板子上看到我们的例程了。并且触摸也没有问题。

7. 触摸按钮测试

触摸驱动相关内容在上文已经成功移植,所以我们只用写主函数中按钮的显示就行。

  1. static void btn_event_cb(lv_event_t *e)
  2. {
  3. lv_event_code_t code = lv_event_get_code(e);
  4. lv_obj_t *btn = lv_event_get_target(e);
  5. if(code == LV_EVENT_CLICKED)
  6. {
  7. static uint8_t cnt = 0;
  8. cnt++;
  9. lv_obj_t *label = lv_obj_get_child(btn,0);
  10. lv_label_set_text_fmt(label, "Butten: %d", cnt);
  11. }
  12. }
  13. // 在main函数中调用 才能出现效果
  14. void lv_example_get_started_1(void)
  15. {
  16. lv_obj_t * btn = lv_btn_create(lv_scr_act());
  17. lv_obj_set_pos(btn, 10,10);
  18. lv_obj_set_size(btn, 120,50);
  19. lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL);
  20. lv_obj_t *label = lv_label_create(btn);
  21. lv_label_set_text(label, "Button");
  22. lv_obj_center(label);
  23. }

并且在main函数添加lv_example_get_started_1()运行就行

如果一切正常,屏幕上会显示如下,每次点击都会自动加1

四.GUI Guider的使用

1. 什么是GUI Guider

什么是 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

2. 软件使用

对guiguider的操作十分简单,主要步骤如下所述:

1️⃣ 在左侧菜单栏寻找想用的组件

2️⃣ 将左侧菜单栏组件拖入中间的模拟器窗口,并调整组件在模拟器窗口的相对位置

3️⃣ 调整右侧的组件属性进行修改,最终得到想要的效果

4️⃣ 点击运行按钮,生成c语言文件

3. guiguider文件夹介绍

文件夹及响应特性如下所示:

  1. custom :用户编写的代码,不会被guiguider所覆盖,可以在此文件中编写用户自己的代码
  2. generated :guiduider所自动生成的代码,会被覆盖,所以最好不要修改此文件夹下的代码
  3. imporrt :导入的文件,如导入的图片或者字体等
  4. lib :关于基础平台的一些文件,如x86文件夹
  5. lvgl :lvgl的源码
  6. lvgl-simulator :模拟器相关内容,显示了一些程序运行的框架,也包含一些接口的使用(如触摸屏等),也不会被工程编译覆盖
  7. temp :与nxp相关的文件,暂时用不到

4.将代码整合到我们的工程

打开我们刚才的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)icon-default.png?t=N7T8https://gitee.com/didiao-hhh/the-use-of-lvgl

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/884986
推荐阅读
相关标签
  

闽ICP备14008679号