ESP32使用platformio创建工程移植LVGL 8.3配置以及踩坑

mengyan233 发布于 2023-12-09 4822 次阅读


写在全文之前的重点

这篇文章解决了我一个月的问题
LittleVGL踩坑指南03:Arduino下显示和触摸驱动配置(TFT_eSPI)
这个作者剩下的3篇文章也有很大的帮助

废话

到屏幕到手为止,已经用过了tftespi和u8g2库,想着有更大的屏幕了用个高级一点的图形库。选来选去打算用LVGL。然后一个月一直卡在触摸屏不响应的位置,屏幕给的例程也是esp32的,库用的也是arduino的,实在搞不明白为什么就是跑不起来。直到这两天手痒再次创建了个新的项目,从头开始再试试,然后就找到了这一篇帖子
LittleVGL踩坑指南03:Arduino下显示和触摸驱动配置(TFT_eSPI)
看到了这一句话

3.官方的LVGL_Arduino.ino文件有错误,没有计时语句,会导致LVGL对触摸没有响应。另外缺少SPI库,导致驱动在底层无法与触摸芯片通信。

于是恍然大悟,想起来之前尝试的时候看到过这个报错,便感慨为什么之前半天找不到这帖子,唉

解决了这个问题之后,后面就是一帆风顺了

环境

|
---|---
IDE | vscode + platformio
框架 | arduino
开发板 | esp32s3
屏幕 | 3.2寸ILI9341 + FT6336
此处的platformio我默认为安装并且配置好的,从头开始下载需要花太多时间

创建工程

咱们从零开始新建一个工程
打开空白的vscode窗口,点击左边的platformio图标,点击Create New Project,就会跳转到PIO主界面了,然哦户我们点击New Project创建新的工程
image.png

工程名称咱们随意,我就以板子名称+外设或者其他作为命名了,比如32s3_LVGL_SHT40
开发板随便选个对的上模块的其实差不多,一般选择乐鑫官方自己的就行,此处我选择的Espressid ESP32-S3-DevKitC。我的板子是有psram和flash的,我们后面再配置
框架选择Arduino
位置我们不选择默认位置,默认位置会放在C盘。此处我选择了自己的工程目录,在目录新建文件夹的话可以选择New,在下面Folder Name写上名字就行。例如我们的32s3_LVGL_SHT40
image.png
然后等待PIO下载开发板文件完成,工程就会创建完成了
image.png
下载完成之后就会默认打开platformio.ini文件。左边是整个工程的目录

32s3_LVGL_SHT40
 |--/.pio
 |    |--/build     //存放PIO编译后生成的文件
 |    |--(/libdeps) //用于存放下载的库文件,此时还没生成 
 |--/.vscode        //vscode编辑器的配置文件目录
 |    |--*
 |--/include        //自己定义、库的头文件可以放在这里
 |--/lib            //还没弄清楚干嘛的。。
 |--/src            //main.cpp所在目录,是工程文件的主要存放目录
 |--/test           //PIO测试时存放文件的目录
 |--platformio.ini  //PIO工程配置文件
 |--.gitignore

配置工程

配置Flash和PSRAM

我的板子是16MBFlash加上8MBPSRAM,参考了以下的文章
VS Code+platformio配置ESP32-S3-N16R8(8MB PSRAM + 16MB FLASH)工程 - Macrored)
所以加上配置之后,PIO配置文件应该是这样的

[env:esp32-s3-devkitc-1]

platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
board_build.arduino.partitions = default_16MB.csv
board_build.arduino.memory_type = qio_opi
build_flags = -DBOARD_HAS_PSRAM
board_upload.flash_size = 16MB

添加TFT_eSPI库和LVGL库

在PIO主界面的Libraries搜索tft就可以看到tftespi库了
image.png

这个库更新奇快,一般下最新的就行。点击Add to Project,在下拉框选择我们刚刚创建的工程,点击Add,等待下载完成就好了
image.png
LVGL的库也是如此。截止到我落笔时,LVGL最新的库版本为8.3.9。搜索LVGL之后记得选择lvgl库,不是第一个GFX Library for Arduino
image.png
至此我们的库文件就配置完成了

配置TFT_eSPI和LVGL库

32s3_LVGL_SHT40/.pio目录下可以发现多了lvglTFT_eSPI文件夹
首先打开TFT_eSPI文件夹下的User_Setup.h,我们来配置驱动

屏幕驱动

Ctrl + F搜索,找到ILI9341,发现已经默认取消注释了

#define ILI9341_DRIVER       // Generic driver for common displays

屏幕分辨率

我这块屏幕的手册里写的宽度是240,长度320
找到TFT_WDITH和TFT_HEIGHT并且修改

#define TFT_WIDTH  240 // ST7789 240 x 240 and 240 x 320
#define TFT_HEIGHT 320 // ST7789 240 x 320

颜色翻转

在我后面测试的时候,我发现颜色反转了,故在TFT_eSPI进行配置
搜索到此行并且取消注释

#define TFT_INVERSION_ON

!配置引脚

ILI9341是SPI通信,我这块屏幕一共10pin。不多说直接展示配置
此处的TOUCH_CS配置为悬空的18引脚是为了减少后面vscode在编译时报warning
FT6336我后面是另外配置引脚的

#define TFT_MISO 12
#define TFT_MOSI 13
#define TFT_SCLK 14
#define TFT_CS   15  // Chip select control pin
#define TFT_DC    2  // Data Command control pin
#define TFT_RST   4  // Reset pin (could connect to RST pin)
#define TFT_BL   21  // LED back-light

#define TOUCH_CS 18     // Chip select pin (T_CS) of touch screen

字体设置

这一部分我没动,毕竟用LVGL画图就不需要这个部分

其他设置

这里的SPI频率最高只能设置成40Mhz,再高的话会花屏,其他的选项默认

#define SPI_FREQUENCY  40000000

还有就是,如果使用硬件SPI的话,后面有个USE HSPI的配置,取消注释可以解决一些问题。

#define USE_HSPI_PORT

导入LVGL_Arduino例程

在此之前还需要将lvgl根目录下的demos和examples文件下复制到src文件夹下,否则编译的时候会报错。虽然报的是warning不是error,但最后就是编译不了
undefined reference to 'lv_demo_benchmark'(例如lv_demo_benchmark)

在lvgl目录下打开examples/arduino/LVGL_Arduino.ino,把里面的全部复制到main.cpp中
还有复制粘贴一份目录下的lv_conf_template.h文件命名为lv_conf.h,并且打开文件,将#if 0修改为if 1,该配置文件就启用了

!修改main.cpp

回到main.cpp,接下来适配触摸屏驱动程序

FT6336的驱动文件链接在这:FT6336-arduino.zip
放入libdeps目录下,打开touch.h,修改ft6336的引脚和大小

 #define TOUCH_FT6336
 #define TOUCH_FT6336_SCL 38
 #define TOUCH_FT6336_SDA 39
 #define TOUCH_FT6336_INT 40
 #define TOUCH_FT6336_RST 41
 #define TOUCH_MAP_X1 0
 #define TOUCH_MAP_X2 240
 #define TOUCH_MAP_Y1 0
 #define TOUCH_MAP_Y2 320

在main.cpp最上头添加touch.h的头文件

#include <touch.h>

在main.cpp中找到my_touchpad_read函数,修改为以下内容

/* Reading input device (simulated encoder here) */
void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
  if (touch_has_signal())
  {
    if (touch_touched())
    {
      data->state = LV_INDEV_STATE_PR;

      /*Set the coordinates*/
      data->point.x = touch_last_x;
      data->point.y = touch_last_y;
    }
    else if (touch_released())
    {
      data->state = LV_INDEV_STATE_REL;
    }
  }
  else
  {
    data->state = LV_INDEV_STATE_REL;
  }
}

然后在入口函数void setup()里删掉这一段,因为我们不需要tft espi自带的触屏驱动

    /*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 );

然后在LVGL初始化之前添加下面语句

    touch_init(320, 240,3);

在开头添加头文件

#include <./demos/lv_demos.h>

还有最重要的一步,在void loop()循环函数中,只有lv_timer_handler()delay( 5 )这两句,是跑不起来的,将其修改为

void loop()
{
    long last_time = millis();
    lv_timer_handler(); /* let the GUI do its work */
    delay(5);
    lv_tick_inc(int(millis() - last_time));
}

就可以正常运行了
最后取消注销掉demo的语句就可以正常跑起来啦
记得在lv_conf中也需要修改DEMO USAGE的部分,比如我要使用widgets的demo就define为1
image.png

后话

麻烦了半天居然被一句话解决了,顿感恼火,代码不想写了就来搓博客,一边搓一边骂CSDN

此作者没有提供个人介绍。
最后更新于 2023-12-09