LittleVGL pit guide 03: Arduino screen driver configuration (TFT_eSPI)


   after several days of touching, there were too many pits. Fortunately, it finally flew over. By the way, I also wrote the display driver; In advance, my hardware is a 2.4-inch ILI9341 drive screen + XPT2046 resistance touch. The touch chip and the screen share SPI data and clock pins, but only CS pins are different.

1, Pit encountered

  1.TFT_eSPI library is not only a display driver, but also a touch driver. You can open and try TFT_eSPI/examples/Generic/Touch_calibrate/Touch_calibrate.ino routine to see if the touch can be successfully realized. If it can be implemented, there is no need for a third-party driver, saving the trouble of API adaptation.
  2.LVGL supports multiple platforms, and the ino file is specially written for Arduino platform. Official lvgl_ Arduino. The ino file already has an input device (indev) configuration statement. If you have LV in hand_ port_ indev_ template. C and lv_port_indev_template.h files, they are useless, at least Arduino can't.
  3. Official LVGL_ Arduino. There is an error in the ino file and there is no timing statement, which will cause LVGL not to respond to touch. In addition, the lack of SPI library makes the driver unable to communicate with the touch chip at the bottom.

2, Display driver configuration

1. User profile selection

  turn on TFT_eSPI/User_Setup_Select.h. Found:

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

   and delete the comment symbol in front of it. This is used to select the driver configuration file, TFT_eSPI has many default configuration files. Here we choose User_Setup, configure the screen by yourself. Next, open User_Setup.h.
   in this file, you need to select the screen driver, define the pin and configure the SPI speed. Some display drivers also have their own proprietary configuration items. Pay attention to the notes, or use the editor to search the model of your own display driver.
If you find the file at the bottom, use esp8132

 // 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

   and put #define use_ HSPI_ The comment symbol before port is removed. This sentence is used to solve the occupation problem of hardware SPI

   the enabling CS pin mentioned in stepping on pit guide 01 is also completed here. For example:

// 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

   have #define touch_ For CS, there is a condition definition in the file. If the CS pin is not defined, the touch related module will not be compiled, resulting in an error in the touch part of the ino file. So either #define TOUCH_CS, or delete all the touch codes.

3, Touch drive configuration

   LVGL supports a variety of input devices, including mouse, keyboard, encoder, etc. here is the configuration method of touch screen (Touchpad).

1. Patch library loading

  open lvgl_ Arduino. No, add a sentence to a group of include:

#include <SPI.h>

   after adding, there should be four sentences including, as follows:

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

2. Fix errors

  we find the loop() function with only two lines at the bottom; Add a line of code as follows:

void loop()
    lv_task_handler(); /* let the GUI do its work */

   lv_tick_inc(5) tells LVGL that 5 milliseconds have passed. Without this sentence, LVGL will lose its clock and therefore cannot respond.
  when you're done, just two steps, easy.

3, Analysis of ino files

  finally, let's take a look at the official ino file. Let's focus on LittleVGL and tft_ How ESPI interfaces. First, the top of the file is tft_ The ESPI class creates an object instance named tft:

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

1. Display part

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.setAddrWindow(area->x1, area->y1, w, h);
    tft.pushColors(&color_p->full, w * h, true);


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

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

  the first half is the display refresh function that needs to be written by yourself, because TFT_eSPI is the official appointed driver, so it is officially written here. The second half is the definition of LVGL's display and output device. LVGL doesn't care what the screen is. After defining the display device, it will give the pixel information of each frame to the device to specify the processing function, that is, my_disp_flush´╝Ť my_ disp_ There are TFTs in the flush_ The method defined by ESPI displays the pixel information on the screen.

2. Touch part

   the input and output devices are the same for LVGL. They are all devices, so the code is similar to the display part

  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.print("Data y");

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

/*SETUP Some touch screen initialization and calibration statements are scattered in the function*/
	tft.begin(); /* TFT init */
    tft.setRotation(1); /* Landscape orientation */

    uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };

/*Initialize the (dummy) input device driver*/
    lv_indev_drv_t indev_drv;
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = my_touchpad_read;

   at the bottom is the input device definition, which tells LVGL that there is a Touchpad touch device here, and LVGL will execute it regularly_ Touchpad_ Read, the timed time is Lv_ Set in conf, the default is 30ms. my_touchpad_read is a processing function that tells the touch state and the last coordinate.


Tags: arduino

Posted by mubeena on Fri, 15 Apr 2022 06:44:40 +0930