jjzjj

基于Arduino框架下的ESP32移植LVGL教程

Yogurt-994 2024-05-17 原文

  这篇文章将成为一个教程–关于如何在Arduino框架下ESP32移植LVGL(Light and Versatile Graphics Library)。学习之余,在此写下我的学习笔记。

文章目录

关于LVGL

  简而言之,LVGL是一个具有广泛功能的轻量图形库。基本上适用于所有的显示器,因为其本身不是LCD驱动库—它依赖于其他额外的库来驱动显示器。此外,它还是一个开源库,在此附上开源链接

硬件软件

硬件:
· ESP32开发板
· 带有SPI接口的LCD
· USB供电线
软件:
· Platform IO(也可以使用Arduino IDE,本教程中使用前者)
· TFT_eSPI或其他显示屏驱动库(例如Adafruit GFX Library

开发环境

  对于本教程,我将使用PlatformIO开发环境。该IDE相较于Arduino IDE,个人使用感觉更加便捷容易。
  要开始使用 PlatformIO,首先,你需要下载它。实际上,它是 Visual Studio Code 的一个附加组件——可扩展的文本编辑器。
安装后,可以创建你的第一个项目。使用方法在此就不赘述。

硬件设置

本教程中,使用是的1.44寸TFT屏模块/SPI,驱动IC是ST7735,连接ESP32开发板如下

在移植LVGL前驱动LCD

  首先,你需要一个在 LVGL 之外工作的显示器——只有它的驱动程序库。根据显示类型(SPI、I2C、并行),有多种选择。如果你使用 Adafruit 的(或具有相同驱动器 IC 的类似 LCD)显示器,则可以使用 Adafruit 库。你还可以使用基于 Adafruit 库的Bodmer 的 TFT_eSPI库。如果你已经熟悉 eSPi 库,则可以使用它。你还可以为显示器编写你自己的几个驱动程序函数——这样你将节省一些程序内存,因为 LVGL 只需要上述库中的一些函数。本教程中使用的是TFT_eSPI。

TFT_eSPI驱动TFT显示屏

  你可以在PlatformIO中直接下载,或从GithubTFT_eSPI获取,也可以直接获取本教程的驱动代码
  将库文件添加至工程后,需要编辑修改User_Setup.h文件以满足你的要求。以下代码为本教程

#define USER_SETUP_INFO "User_Setup"

#define ST7735_DRIVER      // Define additional parameters below for this display

#define TFT_WIDTH  128
#define TFT_HEIGHT 128

#define ST7735_GREENTAB128    // For 128 x 128 display

#define TFT_MOSI 13 // In some display driver board, it might be written as "SDA" and so on.15
#define TFT_SCLK 14 //14
#define TFT_CS   15  // Chip select control pin
#define TFT_DC   27  // Data Command control pin
#define TFT_RST  4  // Reset pin (could connect to Arduino RESET pin)
#define TFT_BL   26  // LED back-ligh t

#define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
#define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
#define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts

// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded
// this will save ~20kbytes of FLASH
#define SMOOTH_FONT

#define SPI_FREQUENCY  40000000
#define SPI_READ_FREQUENCY  20000000
// #define SPI_TOUCH_FREQUENCY  2500000

此外,还需实例化一个tft对象并初始化

static const uint16_t screenWidth = 128;
static const uint16_t screenHeight = 128;

TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* TFT instance */

/* TFT init */
tft.init(ST7735_BLACK);
tft.setRotation(0); 

至此,LCD屏幕驱动完成。

移植LVGL

  当LCD屏幕启动并运行时,下一步就是使LVGL适配你的显示设置。首先,下载LVGL至你的PlatformIO工程中,下载方法同上TFT_eSPI。本教程使用的@8.2.0版本。
ps:并非本教程中所有内容对不同版本的lvgl完全适用。

编辑配置文件

  一开始我们需要配置一些 LVGL 库。转到项目中的 LVGL 文件夹,找到“lv_conf_template.h”文件。将其重命名为“lv_conf.h”。然后,打开它进行编辑。在里面你会发现一行告诉你

/*
 * Copy this file as `lv_conf.h`
 * 1. simply next to the `lvgl` folder
 * 2. or any other places and
 *    - define `LV_CONF_INCLUDE_SIMPLE`
 *    - add the path as include path
 */

“将这个文件复制并重命名为 lv_conf.h并放至lvgl文件夹”。
首先,您应该将第一个定义更改为如下所示:

#if 1

然后,找到一行:

#define LV_TICK_CUSTOM 0

使用 Arduino 时,您需要将其值更改为 1:

#define LV_TICK_CUSTOM 1

  虽然此文件中有更多设置,但需要更改这两行才能在 Arduino 系统上启动一个简单的 LVGL 示例。此外,如果你将 LV_TICK_CUSTOM 的值保留为 0,则屏幕不会定期更新或在屏幕触摸后更新。

编辑main.cpp文件

  包含LVGL库

#include "../lvgl/src/lvgl.h"

  注意到上面的 include 中有一条很长的路径。通常它应该像这样工作:

#include "lvgl.h"

  但有时 PlatformIO 决定不查找所需的头文件,你将不得不从当前文件编写一个相对路径。
  接下来,让我们创建一些变量:

static lv_disp_draw_buf_t draw_buf; //初始化显示缓冲区
static lv_color_t buf_1[screenWidth * screenHeight];//用于LVGL使用的缓冲区

lv_obj_t *screenMain;	//指向所用屏幕的实例化对象
lv_obj_t *labelName;
lv_obj_t *labelTime;
lv_obj_t *labelLocation;
lv_obj_t *labelWeather;
lv_obj_t *labelTemperature;

编写回调函数

  编写回调函数,用于将缓冲区的内容复制到显示器的特定区域。

void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
    uint32_t w = (area->x2 - area->x1 + 1);
    uint32_t h = (area->y2 - area->y1 + 1);

    tft.startWrite();
    tft.setAddrWindow(area->x1, area->y1, w, h);
    tft.pushColors(&color_p->full, w * h, true);
    tft.endWrite();

    lv_disp_flush_ready(disp);
}

设置功能

  当我们完成以上步骤后,需要将所需代码添加至setup()函数中:

    /* TFT init */
    tft.init(ST7735_BLACK);
    tft.setRotation(0);
    /*初始化显示*/
    lv_init();  //初始化lvgl库
    lv_disp_draw_buf_init(&draw_buf, buf_1, NULL, screenWidth * screenHeight); //开启双缓冲

    /*Initialize the display*/
    static lv_disp_drv_t disp_drv;  
    lv_disp_drv_init(&disp_drv);
    /*Change the following line to your display resolution*/
    disp_drv.hor_res = screenWidth;
    disp_drv.ver_res = screenHeight;
    disp_drv.flush_cb = my_disp_flush;  /*Set your driver function*/
    disp_drv.draw_buf = &draw_buf;      /*Assign the buffer to the display*/
    lv_disp_drv_register(&disp_drv);    //注册显示屏

    screenMain = lv_obj_create(NULL);    //创建一个实际的屏幕对象
    labelName = lv_label_create(screenMain);
    // labelFans = lv_label_create(screenMain);  
    labelTime = lv_label_create(screenMain);
    labelLocation = lv_label_create(screenMain);
    labelWeather = lv_label_create(screenMain);
    labelTemperature = lv_label_create(screenMain);
    // imgHeadPhoto = lv_img_create(screenMain);

    while(1)
    {
        lv_label_set_long_mode(labelName, LV_LABEL_LONG_WRAP); 
        lv_label_set_text(labelName, "Hello! Yogurt");
        lv_obj_set_size(labelName, 120, 20);
        lv_obj_align(labelName, LV_ALIGN_DEFAULT, 0, 0);
        lv_obj_set_style_text_font(labelName,&lv_font_chinese_14, 0);

        lv_label_set_long_mode(labelLocation, LV_LABEL_LONG_WRAP); 
        lv_label_set_text_fmt(labelLocation, "城市: %s", location);
        lv_obj_set_size(labelLocation, 120, 20);
        lv_obj_align(labelLocation, LV_ALIGN_DEFAULT, 0, 40);
        lv_obj_set_style_text_font(labelLocation,&lv_font_chinese_14, 0);

        lv_label_set_long_mode(labelWeather, LV_LABEL_LONG_WRAP); 
        lv_label_set_text_fmt(labelWeather, "天气: %s",weather);
        lv_obj_set_size(labelWeather, 120, 20);
        lv_obj_align(labelWeather, LV_ALIGN_DEFAULT, 0, 60);
        lv_obj_set_style_text_font(labelWeather,&lv_font_chinese_14, 0);

        lv_label_set_long_mode(labelTemperature, LV_LABEL_LONG_WRAP); 
        lv_label_set_text_fmt(labelTemperature, "气温: %s度",temperature);
        lv_obj_set_size(labelTemperature, 120, 20);
        lv_obj_align(labelTemperature, LV_ALIGN_DEFAULT, 0, 80);
        lv_obj_set_style_text_font(labelTemperature,&lv_font_chinese_14, 0);

        // lv_img_set_src(imgHeadPhoto, &head_photo);
        // lv_obj_align(imgHeadPhoto, LV_ALIGN_CENTER, 64, 64);
        // lv_obj_set_size(imgHeadPhoto, 60, 60);

        lv_scr_load(screenMain); 

        lv_task_handler();
        vTaskDelay(1);
    }

  编译代码并烧录,至此,我们的LVGL移植完毕。

教程源码链接及其他

教程源码链接:https://github.com/Yogurt-994/MyESP32Project/tree/master/NODEMCU-32_LVGL_JSON
LVGL 官方网站:https://lvgl.io/
百问网韦东山LVGL 中文站:http://lvgl.100ask.net/8.2/index.html

有关基于Arduino框架下的ESP32移植LVGL教程的更多相关文章

  1. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  2. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  3. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  4. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  5. 在VMware16虚拟机安装Ubuntu详细教程 - 2

    在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主

  6. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  7. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  8. hadoop安装之保姆级教程(二)之YARN的配置 - 2

    1.1.1 YARN的介绍 为克服Hadoop1.0中HDFS和MapReduce存在的各种问题⽽提出的,针对Hadoop1.0中的MapReduce在扩展性和多框架⽀持⽅⾯的不⾜,提出了全新的资源管理框架YARN. ApacheYARN(YetanotherResourceNegotiator的缩写)是Hadoop集群的资源管理系统,负责为计算程序提供服务器计算资源,相当于⼀个分布式的操作系统平台,⽽MapReduce等计算程序则相当于运⾏于操作系统之上的应⽤程序。 YARN被引⼊Hadoop2,最初是为了改善MapReduce的实现,但是因为具有⾜够的通⽤性,同样可以⽀持其他的分布式计算模

  9. ruby - sinatra 框架的 MVC 模式 - 2

    我想开始使用“Sinatra”框架进行编码,但我找不到该框架的“MVC”模式。是“MVC-Sinatra”模式或框架吗? 最佳答案 您可能想查看Padrino这是一个围绕Sinatra构建的框架,可为您的项目提供更“类似Rails”的感觉,但没有那么多隐藏的魔法。这是使用Sinatra可以做什么的一个很好的例子。虽然如果您需要开始使用这很好,但我个人建议您将它用作学习工具,以对您来说最有意义的方式使用Sinatra构建您自己的应用程序。写一些测试/期望,写一些代码,通过测试-重复:)至于ORM,你还应该结帐Sequel其中(imho

  10. ruby-on-rails - (Ruby,Rails) 基于角色的身份验证和用户管理...? - 2

    我正在寻找用于Rails的优质管理插件。似乎大多数现有的插件/gem(例如“restful_authentication”、“acts_as_authenticated”)都围绕着self注册等展开。但是,我正在寻找一种功能齐全的基于管理/管理角色的解决方案——但不是简单地附加到另一个非基于角色的解决方案。如果我找不到,我想我会自己动手......只是不想重新发明轮子。 最佳答案 RyanBates最近做了两个关于授权的railscast(注意身份验证和授权之间的区别;身份验证检查用户是否如她所说的那样,授权检查用户是否有权访问资源

随机推荐