文章版本7.10,LVGL更新极快,不同版本配置方法可能存在差异

前言

  触摸搞了好几天,坑太多了,好在总算飞过来了。顺便把显示驱动也写了;提前说一下,我的硬件是2.4寸ILI9341驱动屏幕+XPT2046电阻触摸,触摸芯片和屏幕共用SPI数据和时钟引脚,只有CS引脚不同。


一、遇到的坑

  1.TFT_eSPI库不只是显示驱动,还带有触摸驱动,可以打开并尝试TFT_eSPI/examples/Generic/Touch_calibrate/Touch_calibrate.ino例程,看是否能成功实现触摸。如果可以实现则不需要第三方驱动,省去API适配的麻烦。
  2.LVGL支持多平台,ino文件是专为Arduino平台编写的。官方LVGL_Arduino.ino文件已带有输入设备(indev)配置语句。如果你手头里有lv_port_indev_template.c和lv_port_indev_template.h文件的话,它们没有用,至少Arduino用不到。
  3.官方的LVGL_Arduino.ino文件有错误,没有计时语句,会导致LVGL对触摸没有响应。另外缺少SPI库,导致驱动在底层无法与触摸芯片通信。

二、显示驱动配置

1.用户配置文件选择

  打开TFT_eSPI/User_Setup_Select.h,找到:

#include <User_Setup.h>           // Default setup is root library folder

   并删掉它前面的注释符号,这是用来选择驱动配置文件的,TFT_eSPI有很多默认配置文件,这里我们选择User_Setup,自己来配置屏幕。接下来打开User_Setup.h。
  在这个文件里你要选择屏幕驱动、定义引脚并配置SPI速度,部分显示驱动还会有自己的专有配置项,注意看注释,或者用编辑器的查找来搜索一下自己显示驱动的型号。
   如果你用的是ESP32的话,到文件底部找到

 // The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default.
// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam)
// then uncomment the following line:
//#define USE_HSPI_PORT

   并把#define USE_HSPI_PORT前的注释符号去掉,这句话用来解决硬件SPI的占用问题

   踩坑指南01里说的启用CS引脚也是在这里完成的,举个栗子:

// The hardware SPI can be mapped to any pins

#define TFT_MISO 19
#define TFT_MOSI 23
#define TFT_SCLK 18
#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_RST  -1  // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST

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

   要有#define TOUCH_CS这一条,因为文件里有一块条件定义,如果CS引脚没有被定义,触摸相关模块不会被编译,导致ino文件touch部分报错。所以要么#define TOUCH_CS,要么把touch部分代码全删掉。

三、触摸驱动配置

  LVGL支持多种输入设备,包括鼠标、键盘、编码器等,这里介绍触摸屏(Touchpad)配置方法。

1.修补库加载

  打开LVGL_Arduino.ino,在一群include里加一句:

#include <SPI.h>

  加完之后总共要有四句include,如下:

#include <lv_examples.h>
#include <lvgl.h>
#include <TFT_eSPI.h>
#include <SPI.h>

2.修复错误

  我们找到最下方只有两行的loop()函数;添加一行代码,完成后如下:

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

   lv_tick_inc(5)是告诉LVGL,5毫秒过去了。没有这句话,LVGL会失去时钟,因此无法做出响应。
   完成了,就两步,简单吧。

三、ino文件简析

   最后,我们来看一下官方给的ino文件。主要看一下LittleVGL和TFT_eSPI是如何对接的。首先文件顶部,为TFT_eSPI类创建名为tft的对象实例:

TFT_eSPI tft = TFT_eSPI(); /* TFT instance */

1.显示部分

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);
}

lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);

    /*Initialize the display*/
    lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.hor_res = 320;
    disp_drv.ver_res = 240;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.buffer = &disp_buf;
    lv_disp_drv_register(&disp_drv);

   上半个是需要自己写的显示刷新函数,因为TFT_eSPI是官方钦点的驱动,所以这里官方写好了。下半个是LVGL的显示输出设备定义,LVGL其实不在乎屏幕是什么,定义好显示设备后它就会把每帧的像素信息交给设备指定处理函数,即my_disp_flush;my_disp_flush里面都是TFT_eSPI定义的方法,把像素信息显示到屏幕上。

2.触摸部分

   输入和输出设备对LVGL都一样,都是Device,所以代码和显示部分差不多

  bool my_touchpad_read(lv_indev_drv_t * indev_driver, 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);
    }

    return false; /*Return `false` because we are not buffering and no more data to read*/
}

/*SETUP函数里散落了一些触摸屏初始化和校准语句*/
	tft.begin(); /* TFT init */
    tft.setRotation(1); /* Landscape orientation */

    uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
    tft.setTouch(calData);

/*Initialize the (dummy) input device driver*/
    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);

  底部是输入设备定义,告诉LVGL这里有一个Touchpad触摸设备,LVGL会定时去执行一下my_touchpad_read,定时的时间在lv_conf里设置,默认30ms。my_touchpad_read就是处理函数,告知触摸状态和最后坐标。


END

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐