之前有记录过在 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)

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

Linux 环境中使用 LVGL的更多相关文章

  1. Linux环境中Openfire安装指南

    Linux环境中Openfire安装指南 安装环境: 安装软件:Openfire 4_1_0 http://download.igniterealtime.org/openfire/openfire_ ...

  2. 理解 Linux 网络栈(2):非虚拟化Linux 环境中的 Segmentation Offloading 技术

    本系列文章总结 Linux 网络栈,包括: (1)Linux 网络协议栈总结 (2)非虚拟化Linux环境中的网络分段卸载技术 GSO/TSO/UFO/LRO/GRO (3)QEMU/KVM + Vx ...

  3. [软件测试]Linux环境中简单清爽的Google Test (GTest)测试环境搭建(初级使用)

    本文将介绍单元测试工具google test(GTEST)在linux操作系统中测试环境的搭建方法.本文属于google test使用的基础教程.在linux中使用google test之前,需要对如 ...

  4. linux环境中通过/dev/urandom设备产生随机密码

    需求说明: 今天在调试SVN的时候,需要创建用户的随机密码,想了下,在linux环境中是否能够生成呢,就搜索了下, 然后结合看到的帖子,分析一个可以生成密码的命令,在此记录下. 操作过程: 1.通过/ ...

  5. linux环境中,多个命令之间,通过&& ||执行,命令之间执行的逻辑是什么?

    需求描述: 最近在写一个脚本的时候,要判断一个文件是否存在,有怎么样,没有就创建,这个时候 看到了一个test 结合 || 或者 &&的写法,就查看了下资料记录下是怎么个玩法. 操作过 ...

  6. Linux环境中Qt程序的手工发布

    Linux环境中Qt程序的手工发布

  7. linux环境中通过useradd命令,创建用户的时候指定用户的base-dir

    需求说明: 今天一个同事,问了一个这样的问题,在linux环境中,创建用户的时候,默认的是在/home目录下创建一个与用户名相同的家目录, 如何能够将这个/home更换成一个其他的,比如/opt/ap ...

  8. linux环境中安装ftp服务

    需求说明: 今天项目中有一个新的需求,需要在linux环境中搭建一个ftp服务,在此记录下. 操作过程: 1.通过yum的方式安装ftp服务对应的软件包 [root@testvm01 ~]# yum ...

  9. linux环境中,查看域名的DNS信息?

    需求说明: 今天在linux主机上,要查询一个域名是在哪个DNS上进行解析的,这个域名下面还有哪些的地址 操作过程: 1.linux环境中通过nslookup命令来进行查看 [deployer@CBS ...

  10. linux环境中,两个不同网段的机器互通

    linux环境中,两个不同网段的机器互通   人评论3690人阅读2019-11-18 14:50:21   环境如下:   host1 单网卡 eth0 172.24.100.15/16   hos ...

随机推荐

  1. siteServer CMS知识点

    1.结构说明 (1)     网站目录说明: a. 一个SitesServer后台只能建立一个主站,但可以建立多个子站,主站目录就是项目的根目录: b. 而子站的目录呢?是在主站目录下建立相应名称的目 ...

  2. 【Java8新特性】- Stream流

    Java8新特性 - Stream流的应用 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! ...

  3. Oracle导出和导入

    导出 exp exp 用户名/密码@实例名 file=导出的dmp文件存放路径 l og=导出日志存放路径 exp hr/123456@orcl file= C:\Users\Administrato ...

  4. SpringBoot(五) - Java8 新特性

    1.Lambda表达式 Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).使用它可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风 ...

  5. spring-boot-maven-plugin报红问题

    spring-boot-maven-plugin报红的原因是因为缺少Spring-Boot的版本号, 版本号可在pom.xml中找到,找到Spring-Boot的版本号后一定不要忘记点击maven的刷 ...

  6. 6.channels 配置websocket

      Django默认不支持websockey,需要Django支持的话需要安装第三方组件 django channels 是django支持websocket的一个模块.   1.安装 pip3 in ...

  7. ES集群检查常用命令

    一.集群检查常用命令 查询集群状态命令: curl -XGET "http://ip:port/_cluster/health?pretty" 查询Es全局状态: curl -XG ...

  8. OpenMP 入门

    OpenMP 入门 简介 OpenMP 一个非常易用的共享内存的并行编程框架,它提供了一些非常简单易用的API,让编程人员从复杂的并发编程当中释放出来,专注于具体功能的实现.openmp 主要是通过编 ...

  9. Codeforces Round #831 (Div. 1 + Div. 2) A-E

    比赛链接 A 题解 知识点:数学. \(2\) 特判加 \(7\),其他加 \(3\) 直接偶数. 时间复杂度 \(O(1)\) 空间复杂度 \(O(1)\) 代码 #include <bits ...

  10. C#使用GDI+同时绘制图像和ROI在picturebox上

    Bitmap bmp; /// <summary> /// 绘制图像 /// </summary> /// <param name="g">Gr ...