马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
LVGL(Light and Versatile Graphics Library)是轻量开源嵌入式图形库,提供丰富控件,只需少量内存与算力,就能在资源受限的硬件上做出体面的界面。本文记录把 LVGL 移植到嵌入式 Linux 的完整过程:准备源码、搭工程、改 lv_conf.h 与 lv_drv_conf.h、重写 main.c 注册显示与输入驱动、改 Makefile,最后交叉编译烧板。
一、环境准备
- 编程环境:Windows 11 + VS Code
- 编译环境:Ubuntu 18.04 交叉编译
- 测试平台:正点原子 i.MX6ULL
- 显示屏:5 寸 RGB 800×480
到 LVGL 的 GitHub 主页分别下载三个仓库:lvgl、lv_drivers、lv_port_linux_frame_buffer。这里采用已发布版本:lvgl v8.3.11、lv_drivers v8.3.0。lv_port_linux_frame_buffer 是官方提供的 Linux framebuffer 移植模板,等于半套现成工程,省事很多。
二、创建工程目录
- 新建 lvgl_demo 文件夹。
- 把 lvgl、lv_drivers 复制进去。
- 把 lv_port_linux_frame_buffer 里的 main.c 和 Makefile 复制进 lvgl_demo。
- 把 lvgl 里的 lv_conf_template.h 复制出来改名 lv_conf.h。
- 把 lv_drivers 里的 lv_drv_conf_template.h 复制出来改名 lv_drv_conf.h。
三、修改 lv_drv_conf.h
- 把
#if 0 改成 #if 1,让配置块生效。
- 把
USE_FBDEV 的值改为 1,使能 framebuffer 设备,这是 Linux 下直接写显存的显示后端。
- 把
USE_EVDEV 的值改为 1,指定触摸输入设备路径。输入事件号可以先 cat /dev/input/eventX,再触摸屏观察有没有内容输出来确认 X 是几。
四、修改 lv_conf.h
- 同样把
#if 0 改成 #if 1。
- 按实际环境适当调大内存相关配置,8.3 版本里是 LV_MEM_SIZE 一类参数。
- 可改刷新周期,默认 30ms。
- 设置 Tick:使用 LV_TICK_CUSTOM 加自定义时间源。
- 使能 widgets demo,方便验证移植是否成功。
五、main.c 的核心改动
#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"
#include "lv_drivers/display/fbdev.h"
#include "lv_drivers/indev/evdev.h"
#define DISP_BUF_SIZE (800 * 480)
int main(void)
{
lv_init();
/* Linux framebuffer 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);
/* Linux input device init */
evdev_init();
/* Initialize and register a display input driver */
lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = evdev_read;
lv_indev_t *my_indev = lv_indev_drv_register(&indev_drv);
/* Create a Demo */
lv_demo_widgets();
/* Handle LVGL tasks */
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 = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;
return (uint32_t)(now_ms - start_ms);
}
几个必改的字段:disp_drv.flush_cb 必须是 fbdev_flush;横竖分辨率要和你实际屏一致,填错会导致画面拉伸;Tick 用自定义时间源实现,否则 LVGL 的任务调度会失去心跳。主循环里调 lv_timer_handler 加 usleep 让出 CPU,不要写死循环空转。
六、Makefile 调整
- 指定编译器:编译前会设环境变量,为避免重复定义报错,此处注释掉 Makefile 里的编译器设置,使用环境默认值。
- 引入 lv_drivers.mk:把 lv_drivers 的 mk 加进编译目标;同时注释掉鼠标样式源文件,嵌入式环境没有鼠标时会报缺失。
- 改构建目标名称:按项目需要改成自己的产物名。
- 可选编译选项调整:若报
unrecognized command line option '-Wshift-negative-value' 这类未识别选项错,直接把这个检查项删掉即可——它只是在做左移负值的静态检查,和移植本身无关。
七、验证要点
- 先 x86 本机跑一遍,确认 widgets demo 能起来,再切交叉编译。
- 交叉编译后用
file 确认产物是 ARM 架构再下载。
- 屏幕上出现 demo 界面、点触摸有响应,才算移植完整;只有画面没触摸,多半是 evdev 事件号填错。
qidao123.com企服评测-应用市场 编辑提示 |