初试LVGL图形化编程GUI
LVGL介绍
LVGL(Light and Versatile Graphics Library)是一个免费的开源图形库,提供创建嵌入式 GUI 所需的一切,具有易于使用的图形元素、漂亮的视觉效果和低内存占用。
强大的构建块,例如按钮、图表、列表、滑块、图像等。
具有动画、抗锯齿、不透明度、平滑滚动的高级图形
各种输入设备,如触摸板、鼠标、键盘、编码器等。
使用 UTF-8 编码的多语言支持
多显示器支持,即同时使用多个TFT、单色显示器
具有类 CSS 样式的完全可定制的图形元素
独立于硬件:与任何微控制器或显示器一起使用
可扩展:能够以很少的内存运行(64 kB 闪存,16 kB RAM)
支持操作系统、外部存储器和 GPU,但不是必需的
单帧缓冲操作,即使具有高级图形效果
用 C 编写以获得最大兼容性(C++ 兼容)
无需嵌入式硬件即可在 PC 上启动嵌入式 GUI 设计的模拟器
绑定到 MicroPython
用于快速 GUI 设计的教程、示例和主题
文档可在线获取并以 PDF 格式提供
官方配置要求
基本上,每个能够驱动显示器的现代控制器都适合运行 LVGL。最低要求是:
16、32 或 64 位微控制器或处理器
> 推荐 16 MHz 时钟速度
闪存/ROM:> 64 kB 用于非常重要的组件(建议 > 180 kB)
内存:
静态 RAM 使用:~2 kB,具体取决于使用的功能和对象类型
堆栈:> 2kB(建议> 8 kB)
动态数据(堆):> 2 KB(如果使用多个对象,建议> 48 kB)。
LV_MEM_SIZE
在lv_conf.h中设置。显示缓冲区:> “水平分辨率”像素(建议>10 “水平分辨率” )
MCU 或外部显示控制器中的一个帧缓冲器
C99 或更新的编译器
官方文档: https://docs.lvgl.io/master/intro/index.html
Esp官网文档也有对它的实例: https://docs.espressif.com/projects/espressif-esp-iot-solution/zh_CN/latest/gui/lvgl_gui.html
初试环境说明
硬件环境
ESP32-C3开发板 (博主使用的是合宙)
TFT-SPI接口的屏幕
TFT驱动板
软件
Vscode-PlatfromIO (Arduino)
SquareLine Stduio (lgvl图形化拖拽式GUI编辑器-个人免费版,官方可免费下载,需要注册)
准备步骤
1. SquareLine Stduio软件简单教程
SquareLine Studio做为LVGL官方推出的PC端开发工具,采用所见即所得的开发方式,大大减少了敲代码方式开发UI的时间。
我们下载并安装好此款软件后,直接打开然后登录或者注册账号即可。
下面来说下这个软件的一些简单的使用
首次打开界面应该会长这样,这个界面是引导新建项目。
Create选项卡是选择我们要指定的平台,这里我选择的是Arduino,然后在右边有个输入框内容,我们要在里面配置一些我们的配置信息,Resolution是配置TFT屏幕的尺寸如果你的TFT是128x128那么就填写128x128。 下面的保持默认就好。最后点击Create就可以创建项目了。
如果你打开这个软件发现字体很小,那么请设置软件的缩放尺寸为你认为合适的尺寸。点击左上角的File -> Preferencs 在弹出的选项卡设置UI Scale缩放尺寸即可。
上面介绍说明了我们可以创建自己的项目也可以使用软件自定义的模板来测试
随便选中一个直接点Create按钮即可,上方的参数我们是改不了的,但是可以在设置完成后进行改动。
项目设置
创建好的项目我们可以设置项目的参数,以及导出代码的位置
点击左上角菜单 File -> Project Settings
在Display Properties内容区中,这里是设置屏幕的尺寸,然后选择颜色深度 例如我的屏幕选择16位就OK,32位就花屏。其他都保持默认即可。
BoardGroup选择Arduino,版本选择最新。
File Export面板中,我们只需要设置Project Export Root 导出的根路径就行了。
最后其他保持不变直接点击Apply Changes保存修改。
下面来说明介绍下如何导出项目。
我们首先需要点击上方的菜单栏 Export - > Create Template Project 然后选择保存路径默认就是我们设置的root根路径。
第二步: Export -> Export UI Files 导出UI组件
到这里就完整的导出项目了。
接下来我们来说下如何将导出的项目文件整合到我们的Vscode中然后烧录到单片机中。
LVGL整合Vscode-PlatformIO烧录程序
在上面我们教您如何将代码导出,下面来说下如何将上面导出的代码复制到我们的项目中去来。
1. 创建PlatformIO ESP32项目
创建好的项目我们添加依赖 TFT_eSPI
其实刚刚那个软件导出来的有这个依赖库,但是我们为什么不用呢?其实我这里实验发现如果使用软件生成的库文件到项目中Fount字体文件编译会报错,但是同一份文件如果是依赖引入的就是我上面的方式就不会有问题出现了。 这个就很奇怪不过我们不研究这个没有意义的。
2. 修改屏幕配置文件,与引脚
这里的配置方法大家就不做过多介绍了,如果你这个库都没用过建议先学会使用它在玩这个lgvl高级的东西。
这里我就当你已经会配置这些东西了,如果你觉得有点困难,可以在文章下方评论寻求帮助。
3. 复制生成文件到项目
我们要复制到项目中的目录文件是 lib 文件夹。
打开生成的目录它应该是长这样的
这里有两个文件夹我们说明下,lib开头的是我们要复制到 上面说的要复制到我们的项目中lib目录下
下面来说下要复制那些东西,首先打开这个文件夹,它应该是长这样的
第一步先将lvgl文件夹和lv_conf.h这两个文件拷贝并直接复制到项目lib目录中,接下里将lv_conf.h移动到lvgl文件夹中。
第二步来复制红框中ui文件夹,我们首先打开它
打开直至src文件 ,到这里我们直接全选然后拷贝并赋值到lib文件夹下,不过我们首先先建立一个ui目录然后再复制到这个新的目录中。
最终的目录结构应该和我下面的图是一样的。
接下来,我们编写main文件夹
我们复制代码
打开ui文件夹,里面应该会有一个 ui.ino 文件,直接打开编辑我们复制里面的内容,然后直接粘贴在我们项目中main.cpp文件中,效果应该是这样的。
/*
* @Description:
* @Author: chenzedeng
* @Date: 2023-06-17 17:18:01
* @LastEditTime: 2023-06-17 18:48:29
*/
#include <Arduino.h>
#include <lvgl.h>
#include <TFT_eSPI.h>
#include "ui.h"
/*Don't forget to set Sketchbook location in File/Preferencesto the path of your UI project (the parent foder of this INO file)*/
/*Change to your screen resolution*/
static const uint16_t screenWidth = 128;
static const uint16_t screenHeight = 128;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[ screenWidth * screenHeight / 10 ];
TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* TFT instance */
#if LV_USE_LOG != 0
/* Serial debugging */
void my_print(const char * buf)
{
Serial.printf(buf);
Serial.flush();
}
#endif
/* Display flushing */
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( ( uint16_t * )&color_p->full, w * h, true );
tft.endWrite();
lv_disp_flush_ready( disp );
}
/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_driver, lv_indev_data_t * data )
{
uint16_t touchX = 0, touchY = 0;
bool touched = false;//tft.getTouch( &touchX, &touchY, 600 );
if( !touched )
{
data->state = LV_INDEV_STATE_REL;
}
else
{
data->state = LV_INDEV_STATE_PR;
/*Set the coordinates*/
data->point.x = touchX;
data->point.y = touchY;
Serial.print( "Data x " );
Serial.println( touchX );
Serial.print( "Data y " );
Serial.println( touchY );
}
}
void setup()
{
Serial.begin( 115200 ); /* prepare for possible serial debug */
String LVGL_Arduino = "Hello Arduino! ";
LVGL_Arduino += String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
Serial.println( LVGL_Arduino );
Serial.println( "I am LVGL_Arduino" );
lv_init();
#if LV_USE_LOG != 0
lv_log_register_print_cb( my_print ); /* register print function for debugging */
#endif
tft.begin(); /* TFT init */
tft.setRotation( 1 ); /* Landscape orientation, flipped */
lv_disp_draw_buf_init( &draw_buf, buf, NULL, screenWidth * screenHeight / 10 );
/*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;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register( &disp_drv );
/*Initialize the (dummy) input device driver*/
static lv_indev_drv_t indev_drv;
lv_indev_drv_init( &indev_drv );
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_touchpad_read;
lv_indev_drv_register( &indev_drv );
ui_init();
Serial.println( "Setup done" );
}
void loop()
{
lv_timer_handler(); /* let the GUI do its work */
delay(5000);
}
上面的代码我改动了一点,你不必和我保持一样,直接用你生成的代码即可。
哈哈,我实验做完收起来了,忘记拍照了 后续有机会拍照在补上。不过可以看下面的这个效果图
评论区