加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

Arduino应用开发——esp32 lvgl v8.3环境搭建

04/01 16:11
1361
阅读需 24 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

LVGL (Light and Versatile Graphics Library) 是一个很流行的免费开源嵌入式图形库,可以帮助很多 MCUMPU 和显示类型创建好看的 UI。它由Gábor Kiss-Vámosi于2016年创建的一个开源项目,目前由来自世界各地的志愿者共同维护和开发。LVGL是用C语言编写的,遵循MIT协议,可以自由地使用和修改。LVGL支持多种操作系统,例如Linux、Windows、RTOS等,也可以在开发板上运行。LVGL还支持多种显示器驱动器触摸屏驱动器,可以与不同大小和分辨率的显示器兼容。

LVGL还提供了多种语言的绑定,例如Python、Micropython、JavaScript等,以及多种开发工具,例如模拟器、视觉化设计器、字体转换器等。

1 硬件设计

ESP32参数如下:

参数
型号 esp32-s2
flash 8M
psram 2M

LCD屏幕参数如下:

参数
尺寸 2.6寸
分辨率 240*240
接口 spi
驱动IC ST7789V
触摸

ESP32与LCD的接线如下:

esp32-s2 lcd 说明
VCC VCC 电源
GND GND 电源负
GPIO36SPI_CLK CLK SPI时钟线
GPIO35SPI_MOSI SDI SPI数据线,esp32输出,lcd输入
GPIO37SPI_MISO SDO SPI数据线,esp32输入,lcd输出,注:该引脚一般可以不用,除非你要读取LCD的信息
GPIO34 CS SPI片选
GPIO4 WR(D/C) 并口时作为写入信号/SPI时作为命令或参数的选择
GPIO1 RST LCD复位引脚,可以用普通IO控制,引脚不足的情况下也可以和esp32的复位引脚接到一起
GPIO2 BL 背光引脚

2 软件设计

注:本文是基于PlatformIO搭建的Arduino环境,所有软件代码也是基于这个环境编译。不知道怎么搭建的同学自行查阅资料,这个网上教程有很多的。

2.1 新建PlatformIO工程

输入项目名称,选择芯片及开发板,选择arduino架构。

请添加图片描述

配置项目参数(platformio.ini)。
注:具体的项目参数根据自己的实际情况配置。更多的参数详情及使用方法,可以在下面的链接查看。
https://docs.platformio.org/page/projectconf.html
https://docs.platformio.org/en/latest/platforms/espressif32.html

本文配置的参数如下:

[env:adafruit_metro_esp32s2]
platform = espressif32
board = adafruit_metro_esp32s2
framework = arduino
lib_deps = 
	bodmer/TFT_eSPI@^2.5.43
	lvgl/lvgl@^8.3.11
monitor_speed = 115200
board_build.f_cpu = 240000000L
board_build.f_flash = 80000000L
board_build.flash_mode = qio
board_upload.flash_size = 8MB
board_upload.speed = 921600
board_upload.use_1200bps_touch = true
board_upload.wait_for_upload_port = true
build_flags = 
	-DBOARD_HAS_PSRAM
	-mfix-esp32-psram-cache-issue
	-DARDUINO_USB_CDC_ON_BOOT=1
	-DARDUINO_USB_DFU_ON_BOOT=0
	-DARDUINO_USB_MSC_ON_BOOT=0
	-DCORE_DEBUG_LEVEL=0
lib_ldf_mode = deep+

2.2 添加开源库

在PIO Home界面选择Libraries,搜索需要的库并添加到自己的工程目录下。

注:每个PlatformIO工程的库都是独立的,所以你这里要把库添加到对应的工程,旧工程下载的库并不能直接用于新工程上。

本文需要使用的Arduino库如下:

Arduino库 版本 说明
TFT_eSPI 2.5.43 该库通过SPI方式驱动LCD,支持多种LCD常用驱动IC
lvgl 8.3.11 lvgl库,方便做各种图形处理

配置流程大致如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

添加成功后可以在工程目录下看到已添加的库,platformio.ini文件中也会自动生成依赖库代码。

在这里插入图片描述
在这里插入图片描述

2.3 配置LCD底层接口

2.3.1 LCD接口配置

TFT_eSPI库集成了很多常用LCD驱动IC的接口,根据自己使用的LCD屏幕参数修改User_Setup.h文件,即可调用底层的接口函数。

注:User_Setup.h定义的参数比较多,我这里就不一个个细说了。我主要讲几个重要的参数。

1)驱动IC

根据自己使用的LCD驱动IC打开对应的宏。注意这些驱动只能选择一个打开,不用的要注释掉。

在这里插入图片描述

2)RGB数据格式

RGB格式指的是像素点颜色数据的排列方式,一般就BGR和RGB两种,区别其实就是数据高位在前还是低位在前,这个主要是用于图片显示,要用哪种格式主要是看你要显示的内容是怎么排的,不确定的话可以先不改,调试的时候如果颜色不对的话再换过来就好了。

在这里插入图片描述

3)像素

根据自己屏幕的像素修改,也可以先不改,直接在后面应用的时候再改。

在这里插入图片描述

4)GPIO

根据自己的电路设置引脚,除了几个必要的引脚,有些引脚可以不配置。

如:RST可以通过硬件和MCU的RST接到一起,软件配置成-1即可。BL背光也可以硬件直接控制。

注意:相同的GPIO定义只能打开一个,默认有些打开了的要注释掉。

特别说明:建议使用2.4.0以上版本,因为之前的版本关于ESP32的引脚定义是分成HSPI和VSPI的,默认使用VSPI,如果要用HSPI要打开USE_HSPI_PORT定义,但是这套框架兼容性不强,不适用于ESP32-S2和ESP32-C2,而2.4.0以上版本取消了这个定义,直接都按引脚号来定义,这样一来就不用区分HSPI和VSPI了。

在这里插入图片描述

5)字库

TFT_eSPI自带的这些字库你可以直接用,如果你有自己的字库不用这里的话也可以注释掉。flash空间足够的情况下,这点代码加不加都没关系。

在这里插入图片描述

6)SPI通讯速率

SPI通讯速率一般默认即可,默认的这个速率一般是足够了的,如果需要更快的话可以自己修改。

在这里插入图片描述

7)ESP32的特殊定义

TFT_eSPI旧版本关于ESP32的SPI接口是分为HSPI和VSPI两种的,默认使用VSPI,如果要用HSPI要打开USE_HSPI_PORT定义,如果你只是用ESP32,那这个框架是没什么问题的。

但是我之前因为项目需要从ESP32改用ESP32-S2,结果发现ESP32-S2就没有HSPI和VSPI,所有接口都是FSPI,于是我就要把底层很多东西都改掉才能正常使用。

不过现在TFT_eSPI库2.4.0以上版本就已经把这个问题改掉了,兼容了ESP32-S2和ESP-C3,取消了USE_HSPI_PORT这个定义,SPI接口都以GPIO引脚号来定义。

所以,我建议都用新版本的库吧,兼容性更好,也不用去考虑用HSPI还是VSPI。

在这里插入图片描述

2.3.2 LCD驱动测试

TFT_eSPI库配置好了之后可以先烧录一个简单的程序,验证一下硬件接线和代码是否能正常运行。当然,到了后面把lvgl配置好再一步到位也行。

注意:如果此时已经把lvgl库加入到工程,又没有配置的话,编译会出错(找不到lv_conf.h文件),得把lvgl库删除或者配置好lvgl库再测试。

测试代码如下:

#include <Arduino.h>
#include <SPI.h>
#include <TFT_eSPI.h>

TFT_eSPI tft = TFT_eSPI(); 

void setup() 
{
  Serial.begin(115200);
  tft.begin();
  tft.setRotation(0);
  tft.fillScreen(TFT_BLACK);
}

void loop()
{
    tft.fillScreen(TFT_RED);
    delay(1000);
    tft.fillScreen(TFT_GREEN);
    delay(1000);
    tft.fillScreen(TFT_BLUE);
    delay(1000);
}

测试结果:

如果能正常运行的话,屏幕每隔1s会依次点亮红绿蓝三种颜色。

2.4 配置lvgl

2.4.1 添加配置文件

复制lv_conf_template.h到同一路径下,并改名为lvgl_conf.h。否则编译会报错(找不到lv_conf.h文件)。

2.4.2 修改lvgl配置

lvgl里面的lvgl_conf.h文件有很多配置参数,具体的我就不一一描述了。需要用到哪些配置,网上都能找到详细的教程。我这里讲几个必须要配置的东西。

1)把下面的宏打开。

在这里插入图片描述

2)启用自定义时钟

注意:没有一步的话会导致屏幕停留在第一帧的界面。

在这里插入图片描述

3)配置lvgl的显示接口

要把底层的LCD显示接口对接到lvgl这套框架里面,这样lvgl才能控制显示屏

参考代码:

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp_drv, 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_drv );
}

4)配置lvgl的触摸接口

:因为我这里屏幕没有触摸接口,所以我这里把代码注释掉了,如果要用触摸接口的话,这里需要打开。

参考代码:

/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data )
{
  // uint16_t touchX, touchY;

  // bool touched = 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 );
  // }
}
2.4.3 lvgl代码测试

示例代码:

#include <Arduino.h>
#include <SPI.h>
#include <TFT_eSPI.h>
#include "lvgl.h"

TFT_eSPI tft = TFT_eSPI(); 

static lv_disp_draw_buf_t draw_buf;

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp_drv, 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_drv );
}

/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data )
{
  // uint16_t touchX, touchY;

  // bool touched = 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 lvgl_user_init(void)
{
  lv_init();
  
  /*Set the touchscreen calibration data,
    the actual data for your display can be acquired using
    the Generic -> Touch_calibrate example from the TFT_eSPI library*/
  // uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
  // tft.setTouch( calData );
  
  lv_color_t* buf1 = (lv_color_t*) heap_caps_malloc(240 * 240, MALLOC_CAP_SPIRAM);
  // lv_color_t* buf2 = (lv_color_t*) heap_caps_malloc(240 * 240, MALLOC_CAP_SPIRAM);
  lv_disp_draw_buf_init( &draw_buf, buf1, NULL, 240 * 240);

  /*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 = 240;
  disp_drv.ver_res = 240;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.full_refresh = 1;
  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);

  /*Get lvgl version*/
  String LVGL_Arduino = "Hello LVGL! ";
  LVGL_Arduino += String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch(); // version
  lv_obj_t *label = lv_label_create(lv_scr_act());
  lv_label_set_text(label, LVGL_Arduino.c_str());
  lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); //display
}

void setup() 
{
  Serial.begin(115200);
  tft.begin();
  tft.setRotation(0);
  tft.fillScreen(TFT_BLACK);

  lvgl_user_init();
}

void loop()
{
  lv_timer_handler(); /* let the GUI do its work */
  delay(5);
}

测试结果:
代码正常运行,调用lvgl的文本控件,打印lvgl的版本号。
在这里插入图片描述

结束语

我这里只是举了一个简单的例子讲解如何搭建lvgl的环境,实际上lvgl还有很多的控件和功能,也有一些demo可以运行测试,这些就留给你们继续探索了。如果还有什么问题,欢迎在评论区留言。

完整工程源码下载链接

想了解更多Arduino的内容,可以关注一下博主,后续我还会继续分享更多的经验给大家。
基于Arduino的开发教程汇总:
https://blog.csdn.net/ShenZhen_zixian/article/details/121659482

如果这篇文章能够帮到你,就…你懂得。

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
ABLS-LR-3.000MHZ-T 1 Abracon Corporation CRYSTAL 3.0000MHZ 18PF SMD
$3.11 查看
LFSPXO019170REEL 1 IQD Frequency Products HCMOS Output Clock Oscillator, 25MHz Nom
$11.83 查看
6N137 1 Avago Technologies 1 CHANNEL LOGIC OUTPUT OPTOCOUPLER, 10Mbps, 0.300 INCH, DIP-8
$0.99 查看

相关推荐

电子产业图谱