1. 程式人生 > 其它 >ESP32 + Arduino使用TFT_eSPI庫(LCD驅動晶片ST7789)

ESP32 + Arduino使用TFT_eSPI庫(LCD驅動晶片ST7789)

TFT_eSPI是用於TFT-LCD液晶屏的Arduino圖形庫,可支援下面多種液晶屏驅動晶片:

  • ILI9163
  • ILI9225
  • ILI9341
  • ILI9481 (DMA not supported with SPI)
  • ILI9486 (DMA not supported with SPI)
  • ILI9488 (DMA not supported with SPI)
  • HX8357D
  • S6D02A1
  • SSD1351
  • SSD1963
  • ST7735
  • ST7789
  • ST7796
  • GC9A01

之前在淘寶買了一塊2.4寸240×320畫素的SPI串列埠屏(使用的驅動晶片是ST7789V),下面嘗試使用TFT_eSPI庫在Arduino+ESP32上快速點亮這個螢幕。螢幕上有8個引腳,我對應的接線如下(我買的這個螢幕背光線不接懸空的話螢幕不會亮)

ESP32引腳 ST7789引腳 功能
GND GND 接地
3V3 VCC 電源
18 SCL SPI時鐘
23 SDA(MOSI) SPI主出從入
26 RES 復位引腳
27 DC 資料/命令選擇
5 CS SPI片選
22 BLK 背光控制

 在Arduino的庫管理器中下載TFT_eSPI庫,之後在該庫的路徑下(C:\Users\xx\Documents\Arduino\libraries\TFT_eSPI)開啟User_Setup.h檔案。User_Setup.h中有一些需要自己配置的巨集,需要仔細閱讀這個標頭檔案中的註釋。幾個比較關鍵的地方如下:

(1)選擇對應的液晶屏驅動晶片,取消註釋

// Only define one driver, the other ones must be commented out
//#define ILI9341_DRIVER       // Generic driver for common displays
//#define ILI9341_2_DRIVER     // Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172
//#define ST7735_DRIVER      // Define additional parameters below for this display
//#define ILI9163_DRIVER // Define additional parameters below for this display //#define S6D02A1_DRIVER //#define RPI_ILI9486_DRIVER // 20MHz maximum SPI //#define HX8357D_DRIVER //#define ILI9481_DRIVER //#define ILI9486_DRIVER //#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high) #define ST7789_DRIVER // Full configuration option, define additional parameters below for this display //#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display //#define R61581_DRIVER //#define RM68140_DRIVER //#define ST7796_DRIVER //#define SSD1351_DRIVER //#define SSD1963_480_DRIVER //#define SSD1963_800_DRIVER //#define SSD1963_800ALT_DRIVER //#define ILI9225_DRIVER //#define GC9A01_DRIVER

(2)定義螢幕尺寸,我的螢幕是240×320畫素,因此選擇TFT_WIDTH為240,TFT_HEIGHT為320

// For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation
// #define TFT_WIDTH  80
// #define TFT_WIDTH  128
#define TFT_WIDTH  240 // ST7789 240 x 240 and 240 x 320
// #define TFT_HEIGHT 160
// #define TFT_HEIGHT 128
// #define TFT_HEIGHT 240 // ST7789 240 x 240
#define TFT_HEIGHT 320 // ST7789 240 x 320
// #define TFT_HEIGHT 240 // GC9A01 240 x 240

(3) 定義對應模組的引腳

// For ESP32 Dev board (only tested with ILI9341 display)
// The hardware SPI can be mapped to any pins

#define TFT_MISO 19
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS    5  // Chip select control pin
#define TFT_DC   27  // Data Command control pin
#define TFT_RST  26  // Reset pin (could connect to RST pin)
#define TFT_BL   22
//#define TFT_RST  -1  // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST

(4)定義用到的字型(由於會佔用微控制器儲存空間,沒用的字型可以註釋掉)

// Comment out the #defines below with // to stop that font being loaded
// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not
// normally necessary. If all fonts are loaded the extra FLASH space required is
// about 17Kbytes. To save FLASH space only enable the fonts you need!

#define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
#define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
#define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts

(5)其它設定如SPI頻率,按照User_Setup.h標頭檔案中的提示來設定。

// Define the SPI clock frequency, this affects the graphics rendering speed. Too
// fast and the TFT driver will not keep up and display corruption appears.
// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails
// With a ST7735 display more than 27MHz may not work (spurious pixels and lines)
// With an ILI9163 display 27 MHz works OK.

// #define SPI_FREQUENCY   1000000
// #define SPI_FREQUENCY   5000000
// #define SPI_FREQUENCY  10000000
// #define SPI_FREQUENCY  20000000
// #define SPI_FREQUENCY  27000000
#define SPI_FREQUENCY  40000000
// #define SPI_FREQUENCY  55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
// #define SPI_FREQUENCY  80000000

// Optional reduced SPI frequency for reading TFT
#define SPI_READ_FREQUENCY  20000000

// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
#define SPI_TOUCH_FREQUENCY  2500000

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

在測試的時候發現螢幕上某些顏色很奇怪,比如設定字型為藍色但顯示紅色。原因是在ST7789晶片中MADCTL (36h)暫存器的第3位控制畫素顏色順序,當該位為0時顏色按R-G-B顯示,當該位為1時按B-G-R顯示:

Bit D3- RGB/BGR Order
“0” = RGB (When MADCTL D3=”0”)
“1” = BGR (When MADCTL D3=”1”)

 出現這種問題時可以在User_Setup.h中取消掉下面某一行的註釋,來控制顏色順序

// For ST7735, ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display
// Try ONE option at a time to find the correct colour order for your display

//  #define TFT_RGB_ORDER TFT_RGB  // Colour order Red-Green-Blue
#define TFT_RGB_ORDER TFT_BGR  // Colour order Blue-Green-Red

 初次使用過程中還可能遇到螢幕方向或者顏色反轉的問題,可以通過TFT_eSPI提供的函式來控制螢幕旋轉和顏色反轉(參考光學中的互補色,如白-黑,藍-黃)

/***************************************************************************************
** Function name:           invertDisplay
** Description:             invert the display colours i = 1 invert, i = 0 normal
***************************************************************************************/
void TFT_eSPI::invertDisplay(bool i)


/***************************************************************************************
** Function name:           setRotation
** Description:             rotate the screen orientation m = 0-3 or 4-7 for BMP drawing
***************************************************************************************/
void TFT_eSPI::setRotation(uint8_t m)

注意到TFT_eSPI庫下面還有一個User_Setup_Select.h標頭檔案,這個標頭檔案中可以選擇預先定義好的使用者配置(相關檔案位於TFT_eSPI/User_Setups資料夾中)。由於這些配置不適用於我買的這個螢幕,因此直接使用User_Setup.h中的定義。

// Only ONE line below should be uncommented.  Add extra lines and files as needed.

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

//#include <User_Setups/Setup1_ILI9341.h>  // Setup file configured for my ILI9341
//#include <User_Setups/Setup2_ST7735.h>   // Setup file configured for my ST7735
//#include <User_Setups/Setup3_ILI9163.h>  // Setup file configured for my ILI9163
//#include <User_Setups/Setup4_S6D02A1.h>  // Setup file configured for my S6D02A1
//#include <User_Setups/Setup5_RPi_ILI9486.h>        // Setup file configured for my stock RPi TFT
//#include <User_Setups/Setup6_RPi_Wr_ILI9486.h>     // Setup file configured for my modified RPi TFT
//#include <User_Setups/Setup7_ST7735_128x128.h>     // Setup file configured for my ST7735 128x128 display
//#include <User_Setups/Setup8_ILI9163_128x128.h>    // Setup file configured for my ILI9163 128x128 display
//#include <User_Setups/Setup9_ST7735_Overlap.h>     // Setup file configured for my ST7735
//#include <User_Setups/Setup10_RPi_touch_ILI9486.h> // Setup file configured for ESP8266 and RPi TFT with touch
...

 下面的程式碼在螢幕上測試文字輸出,從TFT_eSPI/examples中可以找到各種例子來進行測試。

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

#define TFT_GREY 0x5AEB // New colour

TFT_eSPI tft = TFT_eSPI();  // Invoke library


void setup(void) {
  tft.init();
  tft.setRotation(0);
  tft.invertDisplay(0);
}

void loop() {
  
  // Fill screen with grey so we can see the effect of printing with and without 
  // a background colour defined
  tft.fillScreen(TFT_GREY);
  
  // Set "cursor" at top left corner of display (0,0) and select font 2
  // (cursor will move to next line automatically during printing with 'tft.println'
  //  or stay on the line is there is room for the text with tft.print)
  tft.setCursor(0, 0, 2);
  // Set the font colour to be white with a black background, set text size multiplier to 1
  tft.setTextColor(TFT_WHITE,TFT_BLACK);  tft.setTextSize(1);
  // We can now plot text on screen using the "print" class
  tft.println("Hello World!");
  
  // Set the font colour to be yellow with no background, set to font 7
  tft.setTextColor(TFT_YELLOW,TFT_BLACK); tft.setTextFont(7);
  tft.println(1234.56);
  
  // Set the font colour to be green with black background, set to font 4
  tft.setTextColor(TFT_GREEN,TFT_BLACK);
  tft.setTextFont(4);
  tft.println("Groop");
  tft.println("I implore thee,");

  // Change to font 2
  tft.setTextFont(2);
  tft.println("my foonting turlingdromes.");
  tft.println("And hooptiously drangle me");
  tft.println("with crinkly bindlewurdles,");
  // This next line is deliberately made too long for the display width to test
  // automatic text wrapping onto the next line
  tft.println("Or I will rend thee in the gobberwarts with my blurglecruncheon, see if I don't!");
  
  // Test some print formatting functions
  float fnumber = 123.45;
   // Set the font colour to be blue with no background, set to font 4
  tft.setTextColor(TFT_BLUE);    tft.setTextFont(4);
  tft.print("Float = "); tft.println(fnumber);           // Print floating point number
  tft.print("Binary = "); tft.println((int)fnumber, BIN); // Print as integer value in binary
  tft.print("Hexadecimal = "); tft.println((int)fnumber, HEX); // Print as integer number in Hexadecimal
  delay(10000);
}
View Code

 

 

  

參考:

TFT_eSPI

ESP32驅動ST7789液晶屏

ESP32_Arduino_TFT_eSPI的使用記錄

玩轉 ESP32 + Arduino(二十八) TFT_eSPI庫驅動ST7789