当前位置: 首页 > news >正文

LVGL第一篇-了解lvgl显示原理以及使用C++移植

一、引言

在当今嵌入式系统与图形界面开发的广阔领域中,轻量级图形库 LVGL(Light and Versatile Graphics Library)恰似一颗璀璨耀眼的明星,正日益受到开发者们的热烈推崇与追逐。它以小巧精致之姿、高效卓越之能以及丰富多元之功能,为各类设备赋予了强大无比的图形显示实力。本文将深入探寻 LVGL 的显示原理,同时详细介绍如何运用 C++进行移植,引领开发者踏上 LVGL 的精彩征程。

二、LVGL 显示原理

  1. 分层架构

    • LVGL 采用了极为精妙的分层架构设计,主要涵盖以下几个层次:
      • 驱动层:此层与底层硬件紧密交互,承担着控制显示屏、读取输入设备等重要任务。通常情况下,这一层需要依据具体的硬件平台进行精心适配。
      • 核心层:这里蕴含着 LVGL 的核心功能,诸如对象管理、事件处理以及动画引擎等。作为 LVGL 的核心部分,它提供了极为丰富的图形绘制与交互功能。
      • 应用层:开发者在这一层精心构建属于自己的图形界面,通过调用 LVGL 的 API 来创建诸如按钮、标签、图表等各式各样的对象。
  2. 绘制机制

    • LVGL 的绘制机制基于“脏矩形”(Dirty Rectangle)技术。当某个对象的状态发生变化时,LVGL 仅仅重新绘制该对象所在的矩形区域,而非整个屏幕。如此一来,在处理复杂界面时,能够大幅提高绘制效率。
  3. 事件处理

    • LVGL 借助事件驱动的方式来处理用户输入和系统事件。当用户触摸屏幕、按下按钮或者发生其他事件时,LVGL 会将相应的事件传递给应用程序进行处理。开发者可以通过注册事件回调函数来响应各种丰富多彩的事件。

三、LVGL 运行机制

关于 LVGL 在 main.c 中的初始化

在 LVGL 的程序运行入口 main.c 中,首先会调用 lv_init()函数来初始化 LVGL(Light and Versatile Graphics Library)图形库。此函数执行一系列重要操作,包括设置全局变量、初始化内部数据结构以及加载配置等,从而为后续对 LVGL 的使用做好充分准备。

硬件抽象层初始化

接着,调用 hal_init()函数以初始化 LVGL 所需的硬件抽象层。该函数会依据具体的硬件平台,进行显示屏的初始化、输入设备的配置以及设置系统时钟(tick)等操作。这样能够确保 LVGL 与底层硬件之间进行正确的交互。

以下是 main.c 的代码示例:

int main(int argc, char **argv)
{(void)argc; /*Unused*/(void)argv; /*Unused*//*Initialize LVGL*/lv_init();/*Initialize the HAL (display, input devices, tick) for LVGL*/hal_init();/*处理定时器事件:检查和执行已注册的定时器回调函数,实现定时任务的触发。例如,可以用于动画的更新、周期性的任务执行等。处理动画更新:如果有正在运行的动画,这个函数会更新动画的状态,确保动画的平滑过渡。分发用户输入事件:如果有用户输入(如触摸屏幕、按下按钮等),将这些事件分发给相应的对象进行处理。 */while (1){/* Periodically call the lv_task handler.* It could be done in a timer interrupt or an OS task too.*/lv_timer_handler();usleep(5 * 1000);}return 0;
}

使用 lvgl 绘制一个按钮的官网样例代码如下:

lv_obj_t *srceen = lv_scr_act();
lv_obj_t * btn = lv_btn_create(srceen);    
lv_obj_set_pos(btn, 10, 10);                            
lv_obj_set_size(btn, 120, 50);                          
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL);
lv_obj_t * label = lv_label_create(btn);     
lv_label_set_text(label, "Button");                     
lv_obj_center(label);

在这里插入图片描述

绘制步骤如下:

  1. 获取当前显示屏幕对象句柄。
  2. 调用 lvgl 函数将对象绘制到屏幕上。
  3. 设置组件之间的相对位置,左上角为原点。
  4. 还可以为按钮添加各种事件以及处理函数处理。

由于 lvgl 组件编码难度较高,并且效率也比较低下,在实际开发中从 lvgl 的函数中去实现一个组件的代码量和时间比较多,因此需要进行一个有效的封装。在参考现有的开源仓库中,找到了一个比较完善的基于 C++封装项目 lvglpp。将该项目引入代码中,就能实现一套类似于 QWidget 界面开发方式。

项目源码地址获取:

git clone https://github.com/vpaeder/lvglpp.git

三、引入 lvglpp 到 lvgl

将 lvglpp 放在项目同 lvgl 下面,如下图所示:

在这里插入图片描述

在项目主的 CMakeLists.txt 里面引入 lvglpp 编译模块,如下图所示:

在这里插入图片描述

在这里插入图片描述

基于 lvglpp 实现 led 组件,示例代码如下:

Object root = Object(lv_scr_act(), false);
static auto led1 = Led(root);
led1.align(LV_ALIGN_CENTER, -80, 0);
led1.off();/*Copy the previous LED and set a brightness*/
static auto led2 = Led(root);
led2.align(LV_ALIGN_CENTER, 0, 0);
led2.set_brightness(150);
led2.set_color(palette::main(Color::Red));/*Copy the previous LED and switch it ON*/
static auto led3 = Led(root);
led3.align(LV_ALIGN_CENTER, 80, 0);
led3.on();auto event_cb = [](Event &e) {if(led3.get_brightness() == LV_LED_BRIGHT_MIN) {led3.on();} else {led3.off();}
};led3.add_event_cb(event_cb, LV_EVENT_CLICKED);

在这里插入图片描述

其中创建了 3 个 led 组件,并且给 led3 绑定了一个点击函数,用来改变 led 灯的状态。

总结

lvgl 是一个比较适合嵌入式设备的图形框架。通过封装,可以将复杂的底层函数调用转化为更加直观、易用的接口,极大地提高了开发效率。开发者不再需要深入钻研底层代码的实现细节,而是能够以更简洁的方式构建出精美的图形界面。同时,封装也降低了开发难度,使得即使是经验相对不足的开发者也能轻松上手,快速开发出高质量的嵌入式图形界面应用。。


http://www.mrgr.cn/news/35481.html

相关文章:

  • Zookeeper
  • BERT训练环节(代码实现)
  • Seata分布式事务实践
  • Allegro视频去除走线的小方块
  • [linux][证书]证书导出公钥
  • 关于Python升级以后脚本不能运行的问题
  • LCR 028
  • 字符串哈希
  • 2-102基于matlab的蒙特卡洛仿真
  • 考研数据结构——C语言实现小顶堆
  • SpringBoot基础知识
  • string 的介绍及使用
  • C++语言桌面应用开发GTK3 Gtkmm3 Glade
  • 在Java中如何利用ClassLoader动态加密、解密Class文件
  • 面经宝典【1】-拼多多
  • 插入、更新与删除MySQL记录
  • Python 入门教程(7)面向对象 | 7.5、继承
  • Docker部署服务:快速入门指南
  • opencv学习笔记(一)
  • Vue3——Vite篇