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 绘制一个按钮的官网样例代

### STM32 上移植 LVGL 至 OLED 屏幕并显示图片 #### 准备工作 为了在 STM32 设备上成功移植 LVGL 框架至 OLED 屏幕,并实现图片显示功能,需先确认所使用的硬件资源满足需求。对于不同型号的 STM32 芯片而言,其 Flash 和 RAM 的容量有所不同[^1]。 针对此项目,推荐选用具备较大内存空间的芯片如 STM32F407VE 或者更新一代的产品线中的成员,因为这些设备拥有足够的存储器来支持图形库的操作以及图像数据缓存的需求。 #### 下载与配置 LVGL 库 从 GitHub 获取指定版本(例如 v8.3 版本)的 LVGL 官方源码仓库[^3]: ```bash git clone https://github.com/lvgl/lvgl.git -b release/v8.3 ``` 接着按照指导说明将 `demos` 文件夹内的 `porting` 子文件夹连同 `examples/keypad_encoder` 一起复制到项目的根目录下[^2]。 #### 初始化显示屏驱动程序 确保已经安装好适用于目标开发板的 LCD 控制器驱动程序包;这通常由制造商提供或可通过第三方渠道获得。之后,在应用程序初始化阶段调用相应的 API 来设置屏幕参数,比如分辨率、颜色模式等。 #### 配置刷新回调函数 特别注意的是,如果遇到画面异常现象——即所谓的“花屏”,则可能是由于自定义编写的 `lv_disp_drv_register()` 中注册的那个用于处理帧缓冲区传输过程的回调方法存在问题所致[^4]。因此建议仔细检查这部分逻辑是否正确实现了对物理显示器的数据写入操作。 下面给出一段简单的 C++ 实现片段作为参考,展示了如何通过 SPI 接口向 SSD1306 型号的小尺寸单色 OLED 发送位图格式的画面内容: ```cpp #include "lvgl.h" // ...其他必要的头文件... static void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) { /* 将 color_p 数组里的像素值发送给外部显示器 */ uint16_t w = (area- area->y1 + 1); ssd1306_DrawBitmap(area->x1, area->y1, w, h, (uint8_t *)color_p); //假设存在这样的API lv_disp_flush_ready(disp); } void setup_lvgl() { static lv_disp_buf_t disp_buf; static lv_color_t buf[LV_HOR_RES_MAX * 10]; // 创建一个足够大的缓冲区 lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10); lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.buffer = &disp_buf; disp_drv.flush_cb = my_disp_flush; lv_disp_drv_register(&disp_drv); } ``` 这段代码主要完成了两件事情:一是创建了一个适当大小的颜色缓冲区供内部渲染引擎使用;二是定义了当需要同步最新绘制结果到实际可见区域时应执行的具体动作序列。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值