Linux 环境中使用 LVGL

原文:https://www.cnblogs.com/jzcn/p/17011647.html

之前有记录过在 esp32 中使用 LVGL 的笔记,需要的小伙伴可以了解一下,esp-idf 移植 lvgl8.3.3
我之前整理的学习资料:https://www.cnblogs.com/jzcn/p/16647106.html

一、准备材料

开发板:一块 linux 的开发板 或 linux 的虚拟机
lvgl:8.3.3
系统:ubuntu 18.04

注意:在 linux 环境下使用 lvgl 就相对比较简单了,这里记录了两个方式。

二、方式一

因为 linux 环境下,官方已经帮我们创建好了项目,所以只需要直接拉取就好了。
仓库地址:https://github.com/lvgl/lv_port_linux_frame_buffer

  1. git 命令

      git clone --recursive https://github.com/lvgl/lv_port_linux_frame_buffer.git
      # 如果拉取不下来,可以使用下面的加速地址,我也不知道是否会失效
      https://github.moeyy.xyz/https://github.com/lvgl/lv_port_linux_frame_buffer.git
       

    注意:拉取的时候已经要加 --recursive,否则项目中的子工程拉不下来,如果拉取时忘记加 --recursive 参数,可以在拉取完成是使用 git submodule update --init --recursive 命令更新一下即可。

  2. 工程目录
    拉取完成后,工程目录如下所示:

  3. 编译工程
    直接使用 make 命令编译即可,完成后如下图所示:会直接生成可执行文件,如下图所示:

    注意: 发现可执行文件后,基本就完成了,直接运行即可,./demo ,毫无疑问基本会运行失败,结果如下图所示:

  4. 修改显示驱动
    这里的显示驱动都是使用的 Framebuffer 缓冲区,我之间有个简单的笔记使用,不了解的小伙伴,可以看我之前的笔记,Linux Framebuffer 实验,知道自己的缓冲区设备后,就可以直接在文件 lv_drv_conf.h 中进行修改,不过多数情况下都是 /dev/fb0 可以不用修改,如下图所示:

  5. 修改鼠标或触摸驱动
    在修改鼠标或触摸驱动时,需要借助 evtest 工具,找到自己设备的输入事件。

    • 安装 evtset 工具

        sudo apt-get install evtest
    • 使用命令 sudo evtest 找到对应的事件编号,如下图所示:

    找到鼠标事件后,直接在 lv_drv_conf.h 文件中,更改对应的事件编号即可,如下图所示:

  6. 运行测试
    完成驱动修改后,重新编译测试,因为使用的是 Framebuffer 缓冲区,所以在 ubuntu 缓冲区中使用是,需要关闭图形显示后,才是正常使用 Framebuffer ,命令如下

      # 关闭图形显示
      systemctl set-default multi-user.target
      reboot
       
      # 打开图形显示
      systemctl set-default graphical.target
      reboot

    关闭图形显示后,测试结果如下图所示:

三、方式二

上面我们已经完成了,在 ubuntu 中测试 LVGL 操作还是比较简单的,现在我们开始尝试手动创建工程,并将编译后生成的.o文件放到指定目录下,然后更改编译工具,使其在arm开发板中进行使用。

注意: 在创建过程中,有什么问题可以直接参考上面的工程,可以解决我们过程中遇到的问题

  1. 下载 LVGL

  2. 创建工程目录
    这里我就不详细说明了,直接上图,只要文件目录如图所示一样即可,路径图下图所示:

  3. 将 lvgl 移动到 lib 文件下,并删除多余的文件,如下图所示:

    注意:其中的 lv_conf.h 文件是直接将 lv_conf_template.h 拷贝后进行重命名的,完成后将文件中的 #if 0 改为 #if 1

  4. 将 lvgl 目录下的 demos 文件拷贝到 lib 文件下,如下图所示:

    注意:这里为了 demos 使用中减少问题,我直接拷贝了 lvgl 文件下的 demos 并重命名为 lv_demos

  5. 将 lv_drivers 拷贝到 lib 文件下,并删除多余的文件,如下图所示:

    注意:其中 lv_drv_conf.h 文件是拷贝 lv_drv_conf_template.h 文件重命名后得到的,完成后将文件中的 #if 0 改为 #if 1

  6. 将 lvgl 目录下的 examples 文件拷贝到 lib 文件下,如下图所示:

  7. 在 application 文件下创建 main.c 文件,内容如下:

      #include "lvgl.h"
      #include "../lib/lv_demos/lv_demos.h"
      #include "../lib/lv_drivers/display/fbdev.h"
      #include "../lib/lv_drivers/indev/evdev.h"
      #include <unistd.h>
      #include <pthread.h>
      #include <time.h>
      #include <sys/time.h>
       
      #define DISP_BUF_SIZE (128 * 1024)
       
      int main(void)
      {
      /*LittlevGL init*/
      lv_init();
       
      /*Linux frame buffer device init*/
      fbdev_init();
       
      /*A small buffer for LittlevGL to draw the screen's content*/
      static lv_color_t buf[DISP_BUF_SIZE];
       
      /*Initialize a descriptor for the buffer*/
      static lv_disp_draw_buf_t disp_buf;
      lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);
       
      /*Initialize and register a display driver*/
      static lv_disp_drv_t disp_drv;
      lv_disp_drv_init(&disp_drv);
      disp_drv.draw_buf = &disp_buf;
      disp_drv.flush_cb = fbdev_flush;
      disp_drv.hor_res = 800;
      disp_drv.ver_res = 480;
      lv_disp_drv_register(&disp_drv);
       
      evdev_init();
      static lv_indev_drv_t indev_drv_1;
      lv_indev_drv_init(&indev_drv_1); /*Basic initialization*/
      indev_drv_1.type = LV_INDEV_TYPE_POINTER;
       
      /*This function will be called periodically (by the library) to get the mouse position and state*/
      indev_drv_1.read_cb = evdev_read;
      lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);
       
       
      /*Set a cursor for the mouse*/
      LV_IMG_DECLARE(mouse_cursor_icon)
      lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); /*Create an image object for the cursor */
      lv_img_set_src(cursor_obj, &mouse_cursor_icon); /*Set the image source*/
      lv_indev_set_cursor(mouse_indev, cursor_obj); /*Connect the image object to the driver*/
       
       
      /*Create a Demo*/
      lv_demo_widgets();
       
      /*Handle LitlevGL tasks (tickless mode)*/
      while(1) {
      lv_timer_handler();
      usleep(5000);
      }
       
      return 0;
      }
       
      /*Set in lv_conf.h as `LV_TICK_CUSTOM_SYS_TIME_EXPR`*/
      uint32_t custom_tick_get(void)
      {
      static uint64_t start_ms = 0;
      if(start_ms == 0) {
      struct timeval tv_start;
      gettimeofday(&tv_start, NULL);
      start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
      }
       
      struct timeval tv_now;
      gettimeofday(&tv_now, NULL);
      uint64_t now_ms;
      now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;
       
      uint32_t time_ms = now_ms - start_ms;
      return time_ms;
      }
       
  8. 拷贝鼠标文件 mouse_cursor_icon.c
    将方式一中获取到的鼠标文件拷贝到 application 文件下

  9. 在 lib 目录下创建 lib.mk 文件,内容如下:

      ##################################### lvgl库 #####################################
      # 文件路径
      LVGL_DIR ?= $(PROJECT_PATH)/lib
       
      # 所需的宏定义
      CFLAGS += -DLV_CONF_INCLUDE_SIMPLE
      CFLAGS += -DLV_LVGL_H_INCLUDE_SIMPLE
      # lvgl库
      LVGL_DIR_NAME ?= lvgl
       
      # 所需头文件的路径
      CFLAGS += -I$(LVGL_DIR)/lvgl
       
      # 收集需要编译的源文件
      include $(LVGL_DIR)/lv_demos/lv_demos.mk
      include $(LVGL_DIR)/lv_examples/lv_examples.mk
      include $(LVGL_DIR)/lv_drivers/lv_drivers.mk
      include $(LVGL_DIR)/$(LVGL_DIR_NAME)/lvgl.mk
  10. 在主目录下创建 Makefile 文件,内容如下:

      #
      # Makefile
      # 编译的.o文件和.c文件在同一路径下
      #
       
      $(info "start...")
      # 可执行文件名
      PROJECT_NAME = lvgl_app
       
      ##################################### 项目路径 #####################################
      PROJECT_PATH ?= ${shell pwd}
      OBJ_DIR := $(PROJECT_PATH)/build
       
      ##################################### 设置编译器,默认使用GCC #####################################
      CC = arm-linux-gnueabihf-gcc
      CC ?= gcc
       
      ##################################### 所需头文件的路径 #####################################
      # lv_conf.h
      CFLAGS += -I$(PROJECT_PATH)/lib/lvgl
      # lv_drv_conf.h
      CFLAGS += -I$(PROJECT_PATH)/lib/lv_drivers
       
      ##################################### 编译和链接参数 #####################################
      CFLAGS ?= -O3 -g0 -Wall -Wshadow -Wundef -Wmissing-prototypes -Wno-discarded-qualifiers -Wextra -Wno-unused-function \
      -Wno-error=strict-prototypes -Wpointer-arith -fno-strict-aliasing -Wno-error=cpp -Wuninitialized -Wmaybe-uninitialized \
      -Wno-unused-parameter -Wno-missing-field-initializers -Wtype-limits -Wsizeof-pointer-memaccess -Wno-format-nonliteral \
      -Wno-cast-qual -Wunreachable-code -Wno-switch-default -Wreturn-type -Wmultichar -Wformat-security -Wno-ignored-qualifiers \
      -Wno-error=pedantic -Wno-sign-compare -Wno-error=missing-prototypes -Wdouble-promotion -Wclobbered -Wdeprecated -Wempty-body \
      -Wshift-negative-value -Wstack-usage=2048 -Wno-unused-value
       
      LDFLAGS ?= -lm
       
      ##################################### 收集需要编译的源文件 #####################################
      CSRCS += $(PROJECT_PATH)/application/main.c
      CSRCS += $(PROJECT_PATH)/application/mouse_cursor_icon.c
      include $(PROJECT_PATH)/lib/lib.mk
       
       
      ##################################### 将文件名替换为.o文件 #####################################
      AOBJS = $(ASRCS:.S=.o)
      COBJS = $(CSRCS:.c=.o)
      # CXX_SOURCES = $(foreach dir,$(CSRCS), $(wildcard $(dir)/*.c))
      # CXX_OBJCTS = $(patsubst %.c, $(OBJ_DIR)/%.o, $(CSRCS))
       
      all: default
       
      %.o: %.c
      @$(CC) $(CFLAGS) -c $< -o $@
      #@echo "CC $<"
       
      default: $(COBJS)
      $(CC) -o $(PROJECT_NAME) $(COBJS) $(AOBJS) $(LDFLAGS)
       
      clean:
      rm -f $(PROJECT_NAME) $(COBJS) $(AOBJS)
       

注意: 到此工程文件已经创建好了,接下来只需要解决我们工程放置文件路径导致的问题即可,目录结构如下图所示:

  1. 修改 lib/lv_demos/lv_demos.mk 文件内容如下:

      CSRCS += $(shell find -L $(LVGL_DIR)/lv_demos -name "*.c")
  2. 修改 lib/lv_examples/lv_examples.mk 文件,内容如下:

      CSRCS += $(shell find -L $(LVGL_DIR)/lv_examples -name \*.c)
  3. 修改 lib/lvgl/lvgl.mk

  4. 启动相应的功

    • USE_FBDEV:在文件 lv_drv_conf.h 中
    • USE_EVDEV:在文件 lv_drv_conf.h 中
    • LV_USE_DEMO_WIDGETS:在文件 lv_conf.h,主要作用是启动相应的案例
  5. 在编译的过程中会有 lvgl.h 头文件的引用错误。如下所示:

      #include "../../../lvgl.h"

    这是因为我们移动路径导致的,所以只需要将所以文件引用改为 #include "lvgl.h" 即可

注意:到此我们自己在 Linux 环境下创建的 LVGL 工程就已经完成了,这里自己创建 lvgl 的目的主要是方便版本的选择,可以根据自己的需要选择相应的 LVGL 版本。

四、指定 .o 文件的存放路径

上面的工程中会发现编译生成的.o文件和.c文件是在同一路径下的,那么在实际开发中有不方便之处,所以将.o文件指定到build文件下,操作比较简单,只需要将 Makefile 文件进行更改即可,如下所示:

Makefile 文件

  #
  # Makefile
  # 编译的.o文件和.c文件在同一路径下
  #
   
  $(info "start...")
  # 可执行文件名
  PROJECT_NAME = lvgl_app
   
  ##################################### 项目路径 #####################################
  PROJECT_PATH ?= ${shell pwd}
  OBJ_DIR := $(PROJECT_PATH)/build
   
  ##################################### 设置编译器,默认使用GCC #####################################
  CC = arm-linux-gnueabihf-gcc
  CC ?= gcc
   
  ##################################### 所需头文件的路径 #####################################
  # lv_conf.h
  CFLAGS += -I$(PROJECT_PATH)/lib/lvgl
  # lv_drv_conf.h
  CFLAGS += -I$(PROJECT_PATH)/lib/lv_drivers
   
  ##################################### 编译和链接参数 #####################################
  CFLAGS ?= -O3 -g0 -Wall -Wshadow -Wundef -Wmissing-prototypes -Wno-discarded-qualifiers -Wextra -Wno-unused-function \
  -Wno-error=strict-prototypes -Wpointer-arith -fno-strict-aliasing -Wno-error=cpp -Wuninitialized -Wmaybe-uninitialized \
  -Wno-unused-parameter -Wno-missing-field-initializers -Wtype-limits -Wsizeof-pointer-memaccess -Wno-format-nonliteral \
  -Wno-cast-qual -Wunreachable-code -Wno-switch-default -Wreturn-type -Wmultichar -Wformat-security -Wno-ignored-qualifiers \
  -Wno-error=pedantic -Wno-sign-compare -Wno-error=missing-prototypes -Wdouble-promotion -Wclobbered -Wdeprecated -Wempty-body \
  -Wshift-negative-value -Wstack-usage=2048 -Wno-unused-value
   
  LDFLAGS ?= -lm
   
  ##################################### 收集需要编译的源文件 #####################################
  CSRCS += $(PROJECT_PATH)/application/main.c
  CSRCS += $(PROJECT_PATH)/application/mouse_cursor_icon.c
  include $(PROJECT_PATH)/lib/lib.mk
   
   
  ##################################### 将文件名替换为.o文件 #####################################
  CXX_OBJCTS = $(patsubst %.c, $(OBJ_DIR)/%.o, $(notdir $(CSRCS)))
  SOURSE_DIR = $(dir $(CSRCS))
   
  vpath %.c $(SOURSE_DIR)
   
  $(OBJ_DIR)/%.o: %.c
  @$(CC) $(CFLAGS) -c $< -o $@
  #@echo "CC $<"
   
  all: $(CXX_OBJCTS)
  @$(CC) -o $(PROJECT_NAME) $(CXX_OBJCTS) $(LDFLAGS)
   
  clean:
  @rm -f $(PROJECT_NAME) $(CXX_OBJCTS)
   

笔记到此结束,有写得不好的地方望各位大佬指出

本文来自博客园,作者:浇筑菜鸟,转载请注明原文链接:https://www.cnblogs.com/jzcn/p/17011647.html

如本博客的内容侵犯了你的权益,请与以下地址联系,本人获知后,马上删除。同时本人深表歉意,并致以崇高的谢意! cn_jiaozhu@qq.com

posted @ 2024-01-14 17:39  MaxBruce  阅读(1098)  评论(0编辑  收藏  举报