esp8266应用教程——TFT LCD显示

esp8266应用教程——TFT LCD显示

前言

esp8266虽然硬件资源比较少,但是用它驱动LCD并做一些简单的应用还是可以的。
本文介绍的软件开发基于Arduino,esp8266开发的方式有很多,对于功能较为简单的项目或者前期方案验证,用Arduino是最简单最直接的。

1 硬件介绍

本文的硬件配置如下:

模块 型号 说明
ESP8266 ESP-12F 这是安信可的一款模组,内部主要是用乐鑫的ESP8266EX再加上一个片外FLASH组成
LCD ST7789 LCD常用的驱动IC有很多,如:ILI9341、ST7735等,不同的驱动IC,驱动代码也是有区别的

1.1 模块介绍

ESP8266我用的是安信可的开发板(NodeMCU-12F CH340版本),具体的硬件参数和电路原理图这里就不发出来了,不同的板子引脚可能会有差别。

TFT LCD彩屏不管用的是什么驱动IC,硬件上基本都是一样的,通讯方式常用的是SPI、并口、IIC等,并口有4线、8线和16线,并口速度是最快的,但需要的引脚资源也多,SPI占用的硬件资源较少,速度也还可以,通讯速度一般可达20M,主要看驱动IC,有些驱动IC最大只能支持27M。

我用的LCD屏分辨率是240x240的,驱动IC用的是ST7789,ST7789的通讯方式有两种,SPI和并口,并口要用到的IO口比较多,所以如果对速度要求不是非常高的情况下一般都是选用SPI。
下面这是我在某宝买的屏幕,它把SPI接口和并口都引出来了,不过默认使用的并口,我这里要用的SPI,就需要把背面的R5电阻拆掉放到R4的位置。
在这里插入图片描述
在这里插入图片描述

1.2 硬件连接

esp8266 lcd 说明
VCC VCC 电源正
GND GND 电源负
GPIO14\HSPI_CLK CLK SPI时钟线
GPIO13\HSPI_MOSI SDI SPI数据线,esp8266输出,lcd输入
GPIO12\HSPI_MISO SDO SPI数据线,esp8266输入,lcd输出,注:该引脚一般可以不用,除非你要读取LCD的信息
GPIO4 CS SPI片选
GPIO5 WR(D/C) 并口时作为写入信号/SPI时作为命令或参数的选择
RST RST LCD复位引脚,可以用普通IO控制,引脚不足的情况下也可以和esp8266的复位引脚接到一起

特别说明:不同厂家做的LCD对这几个引脚的命名可能会有差异,但意思是一样的。

2 软件开发

2.1 安装开发板

关于ESP8266 Arduino的环境搭建我之前出过教程了,这里就不多说了,不懂的同学可以先看下我之前的博客。
esp8266开发入门教程(基于Arduino)——环境安装

2.2 安装库

打开Arduino IDE,依次打开 工具 -> 管理库…
在搜索框输入需要安装的库名称,找到对应的库,点击安装即可。

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

Arduino库 版本 说明
TFT_eSPI 2.4.2 该库通过SPI方式驱动LCD,支持多种LCD常用驱动IC
Adafruit GFX Library 1.10.12 很实用的图形库,可以用这个库来绘制一些基础的图案

关于LCD驱动的库其实有很多,之所以用TFT_eSPI是因为这个库比较通用,支持很多驱动IC,而且有些图形库也依赖于这个库。不过这个库也有缺点,就是有些配置只能在底层定义不能在应用层修改,这样一来比如我有多个不同的MCU或者屏幕,我不能随意的切换,因为每次切换的时候都得改一遍底层。
题外话:ST7789也有专门的驱动库,也是可以使用,也包含有图片显示的函数,但是呢因为我后面还要用这个屏幕做gif的显示,gif的那个库有个比较重要的函数是依赖于TFT_eSPI库的,如果不用TFT_eSPI库,那我还要自己改一个函数来替代,因为它这个框架已经定好了,我自己去改的话还要去动框架里面的东西,估计会比较费时间,暂时就先不搞了。

2.3 修改TFT_eSPI库基础配置

安装好TFT_eSPI库之后需要根据自己电路实际的情况配置底层接口。
Arduino安装的库一般在C盘文档目录下,如:C:\Users\xxx\Documents\Arduino\libraries (xxx是你电脑的用户名)
在这里插入图片描述

找到TFT_eSPI文件夹,打开User_Setup.h文
件,修改以下几项参数。
在这里插入图片描述
我最后修改好的User_Setup.h会完整的贴在后面。如果你的硬件方案跟我的一样可以直接拷贝过去。

1)驱动IC
根据自己使用的LCD驱动IC打开对应的宏。注意这些驱动只能选择一个打开,不用的要注释掉。
在这里插入图片描述

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

3)像素
根据自己屏幕的像素修改,也可以先不改,直接在后面应用的时候再改。
在这里插入图片描述

4)GPIO
根据自己的电路设置引脚,除了几个必要的引脚,有些引脚可以不配置,如:RST可以通过硬件和MCU的RST接到一起,软件配置成-1即可。BL背光也可以硬件直接控制。
还有像ESP8266也可以不自定义SPI的几个引脚,它默认用的就是ESP8266硬件SPI的接口,你的接线保持一致即可。
注意:相同的GPIO定义只能打开一个,默认有些打开了的要注释掉。
在这里插入图片描述
5)字库
TFT_eSPI自带的这些字库你可以直接用,如果你有自己的字库不用这里的话也可以注释掉。flash空间足够的情况下,这点代码加不加都没关系。
在这里插入图片描述
6)SPI通讯速率
SPI通讯速率一般默认即可,默认的这个速率一般是足够了的,如果需要更快的话可以自己修改。
在这里插入图片描述
完整的User_Setup.h示例:

//                            USER DEFINED SETTINGS
//   Set driver type, fonts to be loaded, pins used and SPI control method etc
//
//   See the User_Setup_Select.h file if you wish to be able to define multiple
//   setups and then easily select which setup file is used by the compiler.
//
//   If this file is edited correctly then all the library example sketches should
//   run without the need to make any more changes for a particular hardware setup!
//   Note that some sketches are designed for a particular TFT pixel width/height


// ##################################################################################
//
// Section 1. Call up the right driver file and any options for it
//
// ##################################################################################

// Define STM32 to invoke optimised processor support (only for STM32)
//#define STM32

// Defining the STM32 board allows the library to optimise the performance
// for UNO compatible "MCUfriend" style shields
//#define NUCLEO_64_TFT
//#define NUCLEO_144_TFT

// STM32 8 bit parallel only:
// If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7
// then this will improve rendering performance by a factor of ~8x
//#define STM_PORTA_DATA_BUS
//#define STM_PORTB_DATA_BUS

// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
//#define TFT_PARALLEL_8_BIT

// Display type -  only define if RPi display
//#define RPI_DISPLAY_TYPE // 20MHz maximum SPI

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

// Some displays support SPI reads via the MISO pin, other displays have a single
// bi-directional SDA pin and the library will try to read this via the MOSI line.
// To use the SDA line for reading data from the TFT uncomment the following line:

// #define TFT_SDA_READ      // This option is for ESP32 ONLY, tested with ST7789 and GC9A01 display only

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

// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below

// #define M5STACK

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

// For ST7735 ONLY, define the type of display, originally this was based on the
// colour of the tab on the screen protector film but this is not always true, so try
// out the different options below if the screen does not display graphics correctly,
// e.g. colours wrong, mirror images, or stray pixels at the edges.
// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this
// this User_Setup file, then rebuild and upload the sketch to the board again:

// #define ST7735_INITB
// #define ST7735_GREENTAB
// #define ST7735_GREENTAB2
// #define ST7735_GREENTAB3
// #define ST7735_GREENTAB128    // For 128 x 128 display
// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset)
// #define ST7735_REDTAB
// #define ST7735_BLACKTAB
// #define ST7735_REDTAB160x80   // For 160 x 80 display with 24 pixel offset

// If colours are inverted (white shows as black) then uncomment one of the next
// 2 lines try both options, one of the options should correct the inversion.

// #define TFT_INVERSION_ON
// #define TFT_INVERSION_OFF


// ##################################################################################
//
// Section 2. Define the pins that are used to interface with the display here
//
// ##################################################################################

// If a backlight control signal is available then define the TFT_BL pin in Section 2
// below. The backlight will be turned ON when tft.begin() is called, but the library
// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be
// driven with a PWM signal or turned OFF/ON then this must be handled by the user
// sketch. e.g. with digitalWrite(TFT_BL, LOW);

// #define TFT_BL   32            // LED back-light control pin
// #define TFT_BACKLIGHT_ON HIGH  // Level to turn ON back-light (HIGH or LOW)



// We must use hardware SPI, a minimum of 3 GPIO pins is needed.
// Typical setup for ESP8266 NodeMCU ESP-12 is :
//
// Display SDO/MISO  to NodeMCU pin D6 (or leave disconnected if not reading TFT)
// Display LED       to NodeMCU pin VIN (or 5V, see below)
// Display SCK       to NodeMCU pin D5
// Display SDI/MOSI  to NodeMCU pin D7
// Display DC (RS/AO)to NodeMCU pin D3
// Display RESET     to NodeMCU pin D4 (or RST, see below)
// Display CS        to NodeMCU pin D8 (or GND, see below)
// Display GND       to NodeMCU pin GND (0V)
// Display VCC       to NodeMCU 5V or 3.3V
//
// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin
//
// The DC (Data Command) pin may be labelled AO or RS (Register Select)
//
// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more
// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS
// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin
// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected.
//
// The NodeMCU D0 pin can be used for RST
//
//
// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin
// If 5V is not available at a pin you can use 3.3V but backlight brightness
// will be lower.


// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ######

// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
// #define TFT_CS   PIN_D8  // Chip select control pin D8
// #define TFT_DC   PIN_D3  // Data Command control pin
// #define TFT_RST  PIN_D4  // Reset pin (could connect to NodeMCU RST, see next line)
//#define TFT_RST  -1    // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V

//#define TFT_BL PIN_D1  // LED back-light (only for ST7789 with backlight control pin)

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

//#define TFT_WR PIN_D2       // Write strobe for modified Raspberry Pi TFT only


// ######  FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES  ######

// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact
// but saves pins for other functions. It is best not to connect MISO as some displays
// do not tristate that line when chip select is high!
// Note: Only one SPI device can share the FLASH SPI lines, so a SPI touch controller
// cannot be connected as well to the same SPI signals.
// On NodeMCU 1.0 SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode
// On NodeMCU V3  S0 =MISO, S1 =MOSI, S2 =SCLK
// In ESP8266 overlap mode the following must be defined

//#define TFT_SPI_OVERLAP

// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3
//#define TFT_CS   PIN_D3
//#define TFT_DC   PIN_D5  // Data Command control pin
//#define TFT_RST  PIN_D4  // Reset pin (could connect to NodeMCU RST, see next line)
//#define TFT_RST  -1  // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V

#define TFT_MISO 12
#define TFT_MOSI 13
#define TFT_SCLK 14
#define TFT_CS   4
#define TFT_DC   5  // Data Command control pin
#define TFT_RST  -1  // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V

// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP   ######

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

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

//#define TFT_MOSI 15 // In some display driver board, it might be written as "SDA" and so on.
//#define TFT_SCLK 14
//#define TFT_CS   5  // Chip select control pin
//#define TFT_DC   27  // Data Command control pin
//#define TFT_RST  33  // Reset pin (could connect to Arduino RESET pin)
//#define TFT_BL   22  // LED back-light

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

//#define TFT_WR 22    // Write strobe for modified Raspberry Pi TFT only

// For the M5Stack module use these #define lines
//#define TFT_MISO 19
//#define TFT_MOSI 23
//#define TFT_SCLK 18
//#define TFT_CS   14  // Chip select control pin
//#define TFT_DC   27  // Data Command control pin
//#define TFT_RST  33  // Reset pin (could connect to Arduino RESET pin)
//#define TFT_BL   32  // LED back-light (required for M5Stack)

// ######       EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP        ######

// The library supports 8 bit parallel TFTs with the ESP32, the pin
// selection below is compatible with ESP32 boards in UNO format.
// Wemos D32 boards need to be modified, see diagram in Tools folder.
// Only ILI9481 and ILI9341 based displays have been tested!

// Parallel bus is only supported for the STM32 and ESP32
// Example below is for ESP32 Parallel interface with UNO displays

// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
//#define TFT_PARALLEL_8_BIT

// The ESP32 and TFT the pins used for testing are:
//#define TFT_CS   33  // Chip select control pin (library pulls permanently low
//#define TFT_DC   15  // Data Command control pin - must use a pin in the range 0-31
//#define TFT_RST  32  // Reset pin, toggles on startup

//#define TFT_WR    4  // Write strobe control pin - must use a pin in the range 0-31
//#define TFT_RD    2  // Read strobe control pin

//#define TFT_D0   12  // Must use pins in the range 0-31 for the data bus
//#define TFT_D1   13  // so a single register write sets/clears all bits.
//#define TFT_D2   26  // Pins can be randomly assigned, this does not affect
//#define TFT_D3   25  // TFT screen update performance.
//#define TFT_D4   17
//#define TFT_D5   16
//#define TFT_D6   27
//#define TFT_D7   14

// ######       EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP        ######

// The TFT can be connected to SPI port 1 or 2
//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
//#define TFT_MOSI PA7
//#define TFT_MISO PA6
//#define TFT_SCLK PA5

//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz
//#define TFT_MOSI PB15
//#define TFT_MISO PB14
//#define TFT_SCLK PB13

// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
//#define TFT_CS   D5 // Chip select control pin to TFT CS
//#define TFT_DC   D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
//#define TFT_RST  D7 // Reset pin to TFT RST (or RESET)
// OR alternatively, we can use STM32 port reference names PXnn
//#define TFT_CS   PE11 // Nucleo-F767ZI equivalent of D5
//#define TFT_DC   PE9  // Nucleo-F767ZI equivalent of D6
//#define TFT_RST  PF13 // Nucleo-F767ZI equivalent of D7

//#define TFT_RST  -1   // Set TFT_RST to -1 if the display RESET is connected to processor reset
                        // Use an Arduino pin for initial testing as connecting to processor reset
                        // may not work (pulse too short at power up?)

// ##################################################################################
//
// Section 3. Define the fonts that are to be used here
//
// ##################################################################################

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

// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded
// this will save ~20kbytes of FLASH
#define SMOOTH_FONT


// ##################################################################################
//
// Section 4. Other options
//
// ##################################################################################

// For the RP2040 processor define the SPI port channel used (default 0 if undefined)
//#define TFT_SPI_PORT 1 // Set to 0 if SPI0 pins are used, or 1 if spi1 pins used

// For the STM32 processor define the SPI port channel used (default 1 if undefined)
//#define TFT_SPI_PORT 2 // Set to 1 for SPI port 1, or 2 for SPI port 2

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

// Comment out the following #define if "SPI Transactions" do not need to be
// supported. When commented out the code size will be smaller and sketches will
// run slightly faster, so leave it commented out unless you need it!

// Transaction support is needed to work with SD library but not needed with TFT_SdFat
// Transaction support is required if other SPI devices are connected.

// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex)
// so changing it here has no effect

// #define SUPPORT_TRANSACTIONS

2.4 创建项目并编写应用程序

使用Arduino IDE新建一个项目,并编写代码。
示例代码如下:
该代码利用图形库绘制了一些线条和图案,这一讲主要先测试一下LCD驱动,下一讲我会介绍图片的显示。

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

float p = 3.1415926;

// TFT_eSPI tft = TFT_eSPI(240, 240);
TFT_eSPI tft = TFT_eSPI(); 

void setup() 
{
  Serial.begin(115200);

  tft.begin();

  tft.setRotation(0);

  tft.fillScreen(TFT_BLACK);

  // large block of text
  tft.fillScreen(TFT_BLACK);
  testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", TFT_WHITE);
  delay(1000);

  // tft print function!
  tftPrintTest();
  delay(4000);

  // a single pixel
  tft.drawPixel(tft.width()/2, tft.height()/2, TFT_GREEN);
  delay(500);

  // line draw test
  testlines(TFT_YELLOW);
  delay(500);

  // optimized lines
  testfastlines(TFT_RED, TFT_BLUE);
  delay(500);

  testdrawrects(TFT_GREEN);
  delay(500);

  testfillrects(TFT_YELLOW, TFT_MAGENTA);
  delay(500);

  tft.fillScreen(TFT_BLACK);
  testfillcircles(10, TFT_BLUE);
  testdrawcircles(10, TFT_WHITE);
  delay(500);

  testroundrects();
  delay(500);

  testtriangles();
  delay(500);

  mediabuttons();
  delay(500);
}

void loop()
{
  // tft.fillScreen(TFT_WHITE);
  // Serial.printf("test\n");
  // delay(1000);
}

void testlines(uint16_t color) {
  tft.fillScreen(TFT_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, 0, x, tft.height()-1, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, 0, tft.width()-1, y, color);
    delay(0);
  }

  tft.fillScreen(TFT_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, 0, 0, y, color);
    delay(0);
  }

  tft.fillScreen(TFT_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, tft.height()-1, x, 0, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, tft.height()-1, tft.width()-1, y, color);
    delay(0);
  }

  tft.fillScreen(TFT_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color);
    delay(0);
  }
}

void testdrawtext(char *text, uint16_t color) {
  tft.setCursor(0, 0);
  tft.setTextColor(color);
  tft.setTextWrap(true);
  tft.print(text);
}

void testfastlines(uint16_t color1, uint16_t color2) {
  tft.fillScreen(TFT_BLACK);
  for (int16_t y=0; y < tft.height(); y+=5) {
    tft.drawFastHLine(0, y, tft.width(), color1);
  }
  for (int16_t x=0; x < tft.width(); x+=5) {
    tft.drawFastVLine(x, 0, tft.height(), color2);
  }
}

void testdrawrects(uint16_t color) {
  tft.fillScreen(TFT_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color);
  }
}

void testfillrects(uint16_t color1, uint16_t color2) {
  tft.fillScreen(TFT_BLACK);
  for (int16_t x=tft.width()-1; x > 6; x-=6) {
    tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1);
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2);
  }
}

void testfillcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=radius; x < tft.width(); x+=radius*2) {
    for (int16_t y=radius; y < tft.height(); y+=radius*2) {
      tft.fillCircle(x, y, radius, color);
    }
  }
}

void testdrawcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=0; x < tft.width()+radius; x+=radius*2) {
    for (int16_t y=0; y < tft.height()+radius; y+=radius*2) {
      tft.drawCircle(x, y, radius, color);
    }
  }
}

void testtriangles() {
  tft.fillScreen(TFT_BLACK);
  uint16_t color = 0xF800;
  int t;
  int w = tft.width()/2;
  int x = tft.height()-1;
  int y = 0;
  int z = tft.width();
  for(t = 0 ; t <= 15; t++) {
    tft.drawTriangle(w, y, y, x, z, x, color);
    x-=4;
    y+=4;
    z-=4;
    color+=100;
  }
}

void testroundrects() {
  tft.fillScreen(TFT_BLACK);
  uint16_t color = 100;
  int i;
  int t;
  for(t = 0 ; t <= 4; t+=1) {
    int x = 0;
    int y = 0;
    int w = tft.width()-2;
    int h = tft.height()-2;
    for(i = 0 ; i <= 16; i+=1) {
      tft.drawRoundRect(x, y, w, h, 5, color);
      x+=2;
      y+=3;
      w-=4;
      h-=6;
      color+=1100;
    }
    color+=100;
  }
}

void tftPrintTest() {
  tft.setTextWrap(false);
  tft.fillScreen(TFT_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(TFT_RED);
  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(TFT_YELLOW);
  tft.setTextSize(2);
  tft.println("Hello World!");
  tft.setTextColor(TFT_GREEN);
  tft.setTextSize(3);
  tft.println("Hello World!");
  tft.setTextColor(TFT_BLUE);
  tft.setTextSize(4);
  tft.print(1234.567);
  delay(1500);
  tft.setCursor(0, 0);
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE);
  tft.setTextSize(0);
  tft.println("Hello World!");
  tft.setTextSize(1);
  tft.setTextColor(TFT_GREEN);
  tft.print(p, 6);
  tft.println(" Want pi?");
  tft.println(" ");
  tft.print(8675309, HEX); // print 8,675,309 out in HEX!
  tft.println(" Print HEX!");
  tft.println(" ");
  tft.setTextColor(TFT_WHITE);
  tft.println("Sketch has been");
  tft.println("running for: ");
  tft.setTextColor(TFT_MAGENTA);
  tft.print(millis() / 1000);
  tft.setTextColor(TFT_WHITE);
  tft.print(" seconds.");
}

void mediabuttons() {
  // play
  tft.fillScreen(TFT_BLACK);
  tft.fillRoundRect(25, 10, 78, 60, 8, TFT_WHITE);
  tft.fillTriangle(42, 20, 42, 60, 90, 40, TFT_RED);
  delay(500);
  // pause
  tft.fillRoundRect(25, 90, 78, 60, 8, TFT_WHITE);
  tft.fillRoundRect(39, 98, 20, 45, 5, TFT_GREEN);
  tft.fillRoundRect(69, 98, 20, 45, 5, TFT_GREEN);
  delay(500);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, TFT_BLUE);
  delay(50);
  // pause color
  tft.fillRoundRect(39, 98, 20, 45, 5, TFT_RED);
  tft.fillRoundRect(69, 98, 20, 45, 5, TFT_RED);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, TFT_GREEN);
}

3 测试验证

手机拍摄LCD屏幕颜色有失真太严重了,拍不出原来的效果,将就着看吧。
这个示例包含了文本显示(不同字号的文本),画点,画线,画矩形,画圆,画三角形等等。
请添加图片描述

4 常用API介绍

TFT_eSPI 库里面的函数太多了,我选一部分简单介绍一下,其他的函数感兴趣的同学可以去看下源码,很多函数都有注释,即使不看注释只看函数名和变量名其实也能理解,可读性还是很强的。

函数 说明 示例
TFT_eSPI 类函数,不理解的话可以当做变量定义,可以选择入参,入参值依次为分辨率的宽度和高度 TFT_eSPI tft = TFT_eSPI(); TFT_eSPI tft = TFT_eSPI(240, 240);
begin 初始化函数 tft.begin();
setRotation 显示画面旋转,入参的数值为0-3
0:90度
1:180度
2:270度
3:360度
tft.setRotation(0);
fillScreen 填充屏幕,可以把整个屏幕刷成任意颜色,入参值为16位颜色值 tft.fillScreen(TFT_BLACK);
注: TFT_BLACK在库里面是有定义的,值为0x0000,这里也可以直接写颜色值
setCursor(int16_t x, int16_t y, uint8_t font) 设置文本光标位置 tft.setCursor(0, 30);
setTextColor(uint16_t c, uint16_t b) 设置字体前景和背景颜色 tft.setTextColor(TFT_RED);
setTextSize(uint8_t s) 设置文本大小放大倍数,倍数指的是是字库本身大小的基础上再翻倍 tft.setTextSize(1);
print\println\printf等 显示文本,跟串口打印的用法差不多 tft.println(“Hello World!”);
setTextWrap(bool wrapX, bool wrapY) 当光标在行结尾或者列结尾时是否切换到下一行或者下一列继续显示 tft.setTextWrap(false);
drawPixel(int32_t x, int32_t y, uint32_t color) 画一个点,入参依次为x坐标,y坐标,颜色值 drawPixel(120, 120, TFT_GREEN);
drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) 画线
drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) 画矩形
drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color) 画圆角矩形
drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) 画三角形
drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) 画圆
pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) 显示图片,这个函数其实是有多个定义的,我这里列一个常用的,其他入参的格式和含义可以在库源码查看 *data入参的是16位色深的位图数据

5 开发中遇到的一些问题

5.1 没有显示

供电是正常的,背光也是亮的,就是没显示,一开始我以为是接线问题,检查了几遍都没发现问题,后来才发现是我的显示屏硬件有问题,买回来的这个屏是可选并口通讯或者SPI通讯的,默认是并口,需要改一个电阻的位置才能切换到SPI模式,改了之后就OK了。
建议:这个代码比较简单,很多都是直接调用库函数的,所以没有显示的话,大概率是引脚配置或者接线的问题。如果怀疑代码有问题的话可以在loop函数里面定时调用串口打印和刷屏函数(不要刷黑色,黑色看不出的,换一个显眼的颜色),串口打印可以验证代码是否跑起来了,也可以验证时钟是否正确,因为我就遇到过一种情况,硬件用的是40M的晶振,然后我选的那个开发板默认配置是26M的,结果就是串口的波特率,延时什么的都不对,这个是会影响SPI的时序的。串口如果是正常的话就检查引脚和接线。

5.2 显示不全

特别说明:这是一个只出现在某个240x240屏幕的奇怪问题及解决法办法

同样是240x240的分辨率,同样是ST7789的驱动IC,但是屏幕是不同的厂家做的,尺寸也不同,我博客这里介绍的是1.3寸的屏幕,显示正常,但是用我公司某个项目的屏幕(2.6寸),结果出现了一个奇怪的现象。
显示时x坐标是对的,但是y坐标往下偏移了一些位置,比如我显示一张240x240的图片,结果是图片是从显示屏中间偏上的位置开始显示的,上面空出了一部分不能正常显示,又因为显示屏尺寸有限,导致图片下面一部分被截掉了。我又试了一下用其他库,结果试了几个库都是一样的结果,然后我换了一块240x320的屏幕,显示是正常的。所以我怀疑是y坐标的起始位置不对,翻了一下TFT_eSPI的源码,在TFT_eSPI.cpp里面找到了窗口设置的函数,里面有xy坐标起始位置相关的处理。我把这段代码做了一些修改。
原代码如下(起始位置都是0):

#ifdef CGRAM_OFFSET
  x0+=colstart;
  x1+=colstart;
  y0+=rowstart;  
  y1+=rowstart;
#endif

把代码修改如下:

#ifdef CGRAM_OFFSET
  x0+=colstart;
  x1+=colstart;
  y0+=rowstart - 80;  
  y1+=rowstart - 80;  
#endif

修改之后显示正常了。
这个可能是屏幕本身的点阵问题,应该只是个例,所以如果你没有出现这种情况就不用管,如果也有的话可以试下我上面的方法。

5.3 ESP8266一直重启

烧录之后如果一直重启,ESP8266出厂时本身是有烧录程序的,出现重启这种情况可能是因为你新烧录的固件占用内存不多只覆盖了原程序的一部分,然后原来的程序还有一部分没有擦除,导致两个代码揉到一起了,解决办法是用乐鑫的flash烧录工具把整个芯片都擦除掉。这个工具可以在乐鑫的官网上找到。

结束语

这一讲简单介绍了LCD的驱动方法和图形库的使用,因为篇幅问题,我这里就不深入讲了,后面我会继续介绍图片和动图的显示方法。如果还有什么问题,欢迎在评论区留言或者私信给我。

想要库源码和工程源码的小伙伴可以自行下载:
链接:https://pan.baidu.com/s/1OLbCzE_F0LkhLeAAnbWrEg
提取码:os0o

esp8266基于Arduino的开发教程汇总:
https://blog.csdn.net/ShenZhen_zixian/article/details/121659482

版权声明:本文为CSDN博主「Raywarm」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ShenZhen_zixian/article/details/122493117

生成海报
点赞 0

Raywarm

我还没有学会写个人说明!

暂无评论

相关推荐

2WD远程控制小车——程序设计

1. 简介 本文主要包括ESP32开发板的程序和ESP8266开发板的程序。涉及到的内容有OLED显示、DHT22的数据采集、ADC电压测量、TB6612驱动和PS2接收。 2. 电路连接 控制板ESP32的主要电路连接如下图所示&#xf