news 2026/6/27 13:43:25

基于LVGL的嵌入式系统监控界面开发实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于LVGL的嵌入式系统监控界面开发实践

1. 项目概述

泰山派NAS-LVGL9监控器是一个基于LVGL图形库开发的嵌入式系统监控界面项目。作为一名长期从事嵌入式开发的工程师,我最近在泰山派开发板上实现了一个完整的系统监控解决方案,现在将详细的技术实现过程分享给大家。

这个项目最大的特点是将安卓Activity的组件化思想引入到嵌入式GUI开发中,配合LVGL9.1的强大功能,实现了模块化、可扩展的监控界面。整个项目从环境搭建到最终实现,涉及多个关键技术点,包括:

  • LVGL在嵌入式Linux平台的移植
  • FrameBuffer驱动适配
  • 触摸输入系统集成
  • 仿安卓Activity的UI框架设计
  • 系统资源监控实现
  • 开发调试技巧

下面我将从环境搭建开始,逐步讲解这个项目的完整实现过程。

2. 开发环境搭建

2.1 LVGL基础环境配置

LVGL(Light and Versatile Graphics Library)是一个专为嵌入式系统设计的轻量级图形库,支持多种显示设备和输入设备。在开始项目前,我们需要搭建好开发环境。

首先创建工作目录并获取LVGL源代码:

mkdir lvgl_blog_demo cd lvgl_blog_demo git clone https://github.com/lvgl/lvgl.git -b release/v9.1

为了便于开发调试,我们还需要获取Visual Studio模拟器项目:

git clone --recurse-submodules https://github.com/lvgl/lv_port_pc_visual_studio.git

以及Linux平台适配代码:

git clone https://github.com/lvgl/lv_port_linux.git -b release/v9.0

2.2 配置文件调整

将lv_port_linux目录下的关键文件复制到项目根目录:

cp lv_port_linux/{Makefile,main.c,CMakeLists.txt,.gitignore} .

然后修改Makefile,注释掉mouse_cursor_icon.c的引用:

# CSRCS +=$(LVGL_DIR)/mouse_cursor_icon.c

同样修改CMakeLists.txt,移除mouse_cursor_icon.c的编译:

add_executable(main main.c)

2.3 屏幕参数配置

复制lvgl目录下的lv_conf_template.h到项目根目录,并重命名为lv_conf.h。然后进行以下关键配置:

#define DISP_WIDTH 320 // 设置屏幕宽度 #define DISP_HIGHT 240 // 设置屏幕高度 #define LV_MEM_SIZE (2048 * 1024U) // 分配2MB内存给LVGL #define LV_DEF_REFR_PERIOD 10 // 设置刷新周期为10ms #define LV_USE_OS LV_OS_PTHREAD // 使用Linux线程 #define LV_USE_LOG 1 // 启用日志 #define LV_USE_FLOAT 1 // 启用浮点支持 #define LV_USE_GIF 1 // 启用GIF支持 #define LV_GIF_CACHE_DECODE_DATA 1 // 启用GIF缓存 #define LV_USE_SYSMON 1 // 启用系统监控 #define LV_USE_LINUX_FBDEV 1 // 启用FrameBuffer支持 #define LV_LINUX_FBDEV_BUFFER_COUNT 2 // 启用双缓冲 #define LV_USE_EVDEV 1 // 启用输入设备支持

这些配置为后续开发奠定了基础,特别是双缓冲和输入设备支持,对流畅的UI体验至关重要。

3. 显示与输入驱动适配

3.1 FrameBuffer驱动适配

为了让LVGL能够在泰山派开发板上正常显示,我们需要修改FrameBuffer驱动接口。主要修改位于lvgl/src/drivers/display/fb/lv_linux_fbdev.c

lv_display_t * lv_linux_fbdev_create(int32_t hor_res, int32_t ver_res) { static bool inited = false; if(!inited) { lv_tick_set_cb(tick_get_cb); inited = true; } lv_linux_fb_t * dsc = lv_malloc_zeroed(sizeof(lv_linux_fb_t)); LV_ASSERT_MALLOC(dsc); if(dsc == NULL) return NULL; lv_display_t * disp = lv_display_create(hor_res, ver_res); if(disp == NULL) { lv_free(dsc); return NULL; } dsc->fbfd = -1; lv_display_set_driver_data(disp, dsc); lv_display_set_flush_cb(disp, flush_cb); return disp; }

同时需要修改头文件中的函数声明:

lv_display_t * lv_linux_fbdev_create(int32_t hor_res, int32_t ver_res);

在main.c中初始化显示设备:

lv_display_t * disp = lv_linux_fbdev_create(DISP_WIDTH, DISP_HIGHT); lv_linux_fbdev_set_file(disp, "/dev/fb0");

3.2 触摸输入驱动适配

泰山派开发板通常使用Linux输入子系统(evdev)来处理触摸输入。在main.c中添加以下代码:

char evdev[41] = "/dev/input/event1"; lv_indev_t* cdev = lv_evdev_create(LV_INDEV_TYPE_POINTER, evdev); lv_evdev_set_swap_axes(cdev, true); // 交换XY轴 lv_evdev_set_calibration(cdev, 0, 0, DISP_WIDTH, DISP_HIGHT); // 设置触摸范围

这里有几个关键点需要注意:

  1. 触摸设备节点通常是/dev/input/eventX,具体是哪个需要根据实际情况确定
  2. 某些屏幕可能需要交换XY轴坐标
  3. 校准参数需要根据实际触摸屏特性调整

4. 开发工具链配置

4.1 交叉编译环境

泰山派开发板使用ARM架构处理器,我们需要配置交叉编译工具链。假设SDK已经解压到~/share_file/tspi_linux/,可以这样设置环境变量:

export CC=~/share_file/tspi_linux/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc

然后创建build目录并编译:

mkdir build cd build cmake .. make -j8

编译完成后,可执行文件会生成在bin目录下。

4.2 VSCode开发环境

为了提高开发效率,建议使用VSCode进行开发。首先安装以下插件:

  • Remote - SSH:用于远程连接开发主机
  • CMake Tools:用于CMake项目管理

配置交叉编译工具链:

{ "name": "GCC 6.3.1 arm-rockchip-tspi", "compilers": { "C": "/home/chen/share_file/tspi_linux/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc", "CXX": "/home/chen/share_file/tspi_linux/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-g++" } }

配置完成后,可以在VSCode中一键编译项目,大大提高开发效率。

4.3 Visual Studio模拟器

为了加快UI开发速度,我们可以使用Visual Studio模拟器进行前期开发:

  1. 下载安装Visual Studio
  2. 打开lv_port_pc_visual_studio/LVGL.sln
  3. 修改LvglWindowsSimulator.cpp中的屏幕尺寸:
lv_display_t* display = lv_windows_create_display( L"LVGL Windows Simulator Display 1", 350, // 宽度 200, // 高度 zoom_level, allow_dpi_override, simulator_mode);

模拟器开发可以大大减少实际设备上的调试时间,特别适合UI布局和动画效果的调试。

5. Activity组件化框架设计

5.1 设计思想

借鉴安卓Activity的设计理念,我实现了一个轻量级的UI框架,主要特点包括:

  • 页面组件化:每个界面作为独立组件
  • 生命周期管理:onCreate、onDestroy等回调
  • 三种压栈模式:STANDARD、SINGLE_TOP、SINGLE_TASK
  • 消息总线:支持跨页面通信
  • 动态启动页设置

这种设计使得UI开发更加模块化,便于维护和扩展。

5.2 核心实现

框架核心代码位于uikit目录,主要包含:

  • ui.c:实现Activity管理
  • data_bus.c:实现消息总线

页面组件的基本结构如下:

#include "application.h" static lv_obj_t * container; static ui_data_t * ui; LV_IMG_DECLARE(img_start_lunch) static void timer_cb(lv_timer_t * timer) { ui_intent_t intent; intent.anim = true; ui_fun_fast_create_intent(ui, PAGE_MONITOR_STYLE1, &intent); ui_fun_start_activity(&intent); ui_fun_finish(ui, false); } static void on_page_create(ui_data_t * ui_dat, void * params) { ui = ui_dat; container = lv_image_create(lv_screen_active()); lv_img_set_src(container, &img_start_lunch); lv_timer_t * timer = lv_timer_create(timer_cb, 3000, NULL); lv_timer_set_repeat_count(timer, 1); } static void on_page_destoy(void * params) {} static lv_obj_t * page_get_view() { return container; } ui_data_t page_lunch = { .id = PAGE_LUNCH, .launcher = true, .launcher_mode = SINGLE_TASK, .fun_get_view = page_get_view, .fun_on_create = on_page_create, .fun_on_destoy = on_page_destoy };

5.3 页面管理与跳转

所有页面需要在application.h中注册:

#include "application.h" extern ui_data_t page_lunch; extern ui_data_t page_monitor; static ui_data_t* pages[] = {&page_lunch, &page_monitor}; void app_lunch() { ui_init_and_start(pages, sizeof(pages)); }

页面跳转通过intent实现:

ui_intent_t intent; intent.anim = true; // 启用切换动画 ui_fun_fast_create_intent(ui, PAGE_MONITOR_STYLE1, &intent); ui_fun_start_activity(&intent); ui_fun_finish(ui, false); // 结束当前页面

这种设计使得页面之间的跳转和通信变得非常清晰和可控。

6. GIF动画集成

6.1 准备工作

首先确保lv_conf.h中启用了GIF支持:

#define LV_USE_GIF 1 #define LV_GIF_CACHE_DECODE_DATA 1

使用LVGL官方提供的在线图片转换工具将GIF转换为C数组: https://lvgl.io/tools/imageconverter

转换时注意选择正确的颜色格式:

  • CF_RAW:无透明通道
  • CF_RAW_ALPHA:带透明通道

6.2 GIF使用示例

声明GIF资源:

LV_IMG_DECLARE(gif_radiantboy)

创建并显示GIF:

lv_obj_t * gif_obj = lv_gif_create(parent); lv_gif_set_src(gif_obj, &gif_radiantboy); lv_obj_set_pos(gif_obj, x, y);

控制GIF播放:

lv_gif_pause(gif_obj); // 暂停 lv_gif_resume(gif_obj); // 恢复

在实际项目中,GIF动画可以大大增强用户体验,但需要注意:

  1. 控制GIF大小,避免占用过多内存
  2. 复杂动画可能会影响性能
  3. 考虑提供暂停/播放控制接口

7. 项目构建系统

7.1 目录结构

项目采用模块化目录结构:

├── app/ # 页面组件 ├── assets/ # 原始资源 ├── font/ # 字体文件 ├── image/ # 图片资源 ├── monitor/ # 系统监控实现 ├── store/ # 存储相关 └── uikit/ # UI框架

7.2 CMake配置

修改CMakeLists.txt包含所有模块:

include_directories( ${PROJECT_SOURCE_DIR}/app ${PROJECT_SOURCE_DIR}/monitor ${PROJECT_SOURCE_DIR}/uikit ${PROJECT_SOURCE_DIR}/store ) file(GLOB APP ${CMAKE_CURRENT_SOURCE_DIR}/app/*.c) file(GLOB MONITOR ${CMAKE_CURRENT_SOURCE_DIR}/monitor/*.c) file(GLOB UIKIT ${CMAKE_CURRENT_SOURCE_DIR}/uikit/*.c) file(GLOB STORE ${CMAKE_CURRENT_SOURCE_DIR}/store/*.c) file(GLOB FONT ${CMAKE_CURRENT_SOURCE_DIR}/font/*.c) file(GLOB IMG ${CMAKE_CURRENT_SOURCE_DIR}/image/*.c) add_executable(nas_monitor main.c ${STORE} ${UIKIT} ${MONITOR} ${FONT} ${IMG} ${APP}) target_link_libraries(nas_monitor lvgl lvgl::thorvg ${SDL2_LIBRARIES} m pthread)

这种配置方式使得项目结构清晰,便于维护和扩展。

8. 启动参数解析

8.1 参数设计

程序支持以下启动参数:

./nas_monitor -fb 0 -ev 1 -disk /dev/sda1 -net eth0
  • -fb:指定FrameBuffer设备号
  • -ev:指定输入设备号
  • -disk:监控的磁盘设备
  • -net:监控的网络接口

8.2 实现代码

参数解析工具函数:

int extractData(int argc, char* argv[], char* buf, const char* key) { for (int i = 1; i < argc; i++) { if (strncmp(argv[i], key, strlen(key)) == 0) { if (i + 1 < argc) { strcpy(buf, argv[i + 1]); return 0; } return -2; } } return -1; }

在main函数中使用:

char flag_fb[2] = "0"; char flag_ev[2] = "1"; extractData(argc, argv, flag_fb, "-fb"); extractData(argc, argv, flag_ev, "-evdev"); extractData(argc, argv, monitor_dat.disk_name, "-disk"); extractData(argc, argv, monitor_dat.net_name, "-net"); if(extractData(argc, argv, NULL, "-h") == -2){ printf("\tNAS MONITOR Helper\n \ INPUT:-fb DESC: Display Output; Example: -fb 0\n \ INPUT:-evdev DESC: Touch the input subsystem used; Example:-evdev 1\n \ INPUT:-disk DESC: The hard drive to be monitored; Example: -disk /dev/sda1\n \ INPUT:-net DESC: The name of the NIC to which you want to monitor the network speed; Example: -net eth0\n"); return 0; } char fb[41] = "/dev/fb"; char evdev[41] = "/dev/input/event"; strcat(fb, flag_fb); strcat(evdev, flag_ev);

这种设计使得程序更加灵活,可以适应不同的硬件配置。

9. 部署与测试

9.1 文件传输

编译完成后,使用scp将程序传输到开发板:

scp bin/nas_monitor user@192.168.110.167:~/

9.2 运行测试

在开发板上运行程序:

./nas_monitor -fb 0 -ev 1 -disk /dev/sda1 -net eth0

9.3 性能优化建议

在实际部署时,可以考虑以下优化措施:

  1. 调整LVGL的内存配置
  2. 优化刷新频率
  3. 精简不必要的组件
  4. 使用更高效的绘图方式
  5. 合理使用双缓冲

10. 项目总结与扩展

通过这个项目,我们实现了一个完整的嵌入式系统监控界面,主要技术亮点包括:

  1. LVGL在嵌入式Linux平台的完整适配
  2. 创新的Activity组件化设计
  3. 灵活的参数配置系统
  4. 高效的开发调试流程

这个项目还可以进一步扩展:

  1. 添加更多监控指标
  2. 实现远程配置功能
  3. 增加告警通知机制
  4. 支持多语言
  5. 优化性能表现

在实际开发过程中,我总结了以下几点经验:

  1. 模拟器开发可以大大提高效率
  2. 组件化设计使项目更易维护
  3. 合理的日志系统对调试很有帮助
  4. 性能优化需要结合实际测试数据
  5. 良好的文档习惯很重要
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/27 13:39:48

Java Swing学生成绩管理系统

一、项目概述本项目为三人小组Java课程设计&#xff0c;基于Java Swing桌面GUI SQLite轻量文件数据库开发学生成绩管理系统。 系统实现用户登录鉴权、学生信息增删改查、多科目成绩录入与自动统计、CSV文件导入导出、成绩柱状图可视化、批量生成测试数据六大核心功能。 项目采…

作者头像 李华
网站建设 2026/6/27 13:39:03

4G+Lora物联网在智慧农业土壤监测中的应用实践

1. 项目背景与核心需求在农业物联网领域&#xff0c;土壤养分监测一直是个技术难点。传统的手动采样检测方式耗时耗力&#xff0c;而市面上常见的无线监测设备要么传输距离有限&#xff0c;要么功耗过高。这个项目正好解决了这些痛点——通过4GLora的组合&#xff0c;实现了远程…

作者头像 李华
网站建设 2026/6/27 13:23:01

树莓派摄像头应用rpicam-apps核心选项详解与实战调优指南

1. rpicam-apps 核心选项全解析&#xff1a;从入门到精通如果你正在玩树莓派&#xff0c;并且用上了官方的摄像头模块&#xff0c;那么rpicam-apps这套工具集绝对是你绕不开的利器。它基于libcamera&#xff0c;提供了rpicam-hello、rpicam-still、rpicam-vid等一系列命令行应用…

作者头像 李华
网站建设 2026/6/27 13:17:39

树莓派5通过M.2 HAT+扩展NVMe硬盘:从硬件安装到系统配置全指南

1. 项目概述&#xff1a;为树莓派5扩展高速存储 如果你手头有一块树莓派5&#xff0c;并且觉得它的存储性能或容量有些捉襟见肘&#xff0c;那么给这个小家伙加装一块M.2 NVMe固态硬盘&#xff0c;绝对是能带来质变体验的升级。今天要聊的&#xff0c;就是如何通过一块名为“M.…

作者头像 李华
网站建设 2026/6/27 12:58:08

基于ISL73849SLHEV1Z评估板的GaN多相POL电源设计与实战指南

1. 项目概述与核心价值 如果你正在为新一代的FPGA、ASIC或者高性能处理器设计核心供电电路&#xff0c;那么对高效率、高功率密度、快速瞬态响应的点负载电源的需求&#xff0c;一定深有体会。传统的硅基MOSFET方案在开关频率和效率上逐渐触及天花板&#xff0c;而氮化镓器件的…

作者头像 李华