ESP32 Driving ILI9341 Display via 8-bit Parallel Bus

A detailed guide on using ESP32 to drive ILI9341 display via 8-bit parallel bus, providing extremely high refresh rates compared to SPI serial driving, perfect for displaying dynamic content.

This article provides a detailed guide on using ESP32 to drive an ILI9341 display via 8-bit Parallel Bus. Compared to the common SPI serial driving, parallel mode can provide extremely high refresh rates, making it ideal for displaying dynamic content.

Development Environment

OS: MacOS

Arduino IDE Version: 2.3.7

esp32 Version: 3.3.5

TFT_eSPI Version: 2.5.43

BOM

ESP32 x1

2.4 inch TFT display x1

Dupont wires xN

Wiring Connection

TFT PinESP32 PinFunction Description
VCC (3V3/5V)3V3 / VINDisplay power (try 3.3V first)
GNDGNDCommon ground
LCD_D0GPIO 26Data bit 0
LCD_D1GPIO 25Data bit 1
LCD_D2GPIO 19Data bit 2
LCD_D3GPIO 18Data bit 3
LCD_D4GPIO 5Data bit 4
LCD_D5GPIO 21Data bit 5
LCD_D6GPIO 22Data bit 6
LCD_D7GPIO 23Data bit 7
LCD_CSGPIO 32Chip Select
LCD_RTSGPIO 33Reset
LCD_RS (DC)GPIO 14Data/Command (Register Select)
LCD_WRGPIO 27Write Control
LCD_RDGPIO 2Read Control (connect to 3.3V if ID reading not needed)

Required Libraries

Arduino IDE Boards Manager: esp32

You must install the esp32 library from Espressif Systems. Here we’re using the latest version.

Arduino IDE Library Manager: TFT_eSPI

You must install the TFT_eSPI library.

TFT_eSPI Configuration File “User_Setup.h”

TFT_eSPI is an excellent library for ESP32 to drive displays. However, the pin definitions, board definitions, and screen definitions are all configured in the User_Setup.h file, so modifying this file is very important.

The file location is:

Documents > Arduino > libraries > TFT_eSPI > User_Setup.h

Action: Open this file, clear the original content, copy and save the following code:

// =========================================================================
//   User_Setup.h - Display driver configuration file for TFT_eSPI library
//   User_Setup.h - 用于 TFT_eSPI 库的显示驱动配置文件
//
//   Hardware: ESP32 (No PSRAM or not using GPIO 16/17)
//   硬件: ESP32 (无 PSRAM 或不使用 GPIO 16/17)
//
//   Driver: ILI9341 (8-bit parallel mode)
//   驱动: ILI9341 (8位并行模式)
// =========================================================================

// -------------------------------------------------------------------------
// 1. Driver Type Definition
//    定义驱动类型
// -------------------------------------------------------------------------
#define ILI9341_DRIVER       // Generic ILI9341 Driver (通用 ILI9341 驱动)

// -------------------------------------------------------------------------
// 2. Color Order Definition
//    定义颜色顺序
// -------------------------------------------------------------------------
// If colors are inverted (e.g., red becomes blue), change this.
// 如果颜色反了(比如红变蓝),请更改此项。
#define TFT_RGB_ORDER TFT_BGR  // Most ILI9341 screens use BGR order (大部分 ILI9341 屏幕使用的是 BGR 顺序)
// #define TFT_RGB_ORDER TFT_RGB

// -------------------------------------------------------------------------
// 3. Screen Resolution
//    定义屏幕分辨率
// -------------------------------------------------------------------------
#define TFT_WIDTH  240
#define TFT_HEIGHT 320

// -------------------------------------------------------------------------
// 4. Interface Configuration (Critical)
//    接口配置 (关键部分)
// -------------------------------------------------------------------------
#define ESP32_PARALLEL       // Enable ESP32 parallel mode (启用 ESP32 并行模式)
#define TFT_PARALLEL_8_BIT   // Use 8-bit parallel bus (使用 8 位并行总线)

// -------------------------------------------------------------------------
// 5. Pin Definitions
//    引脚定义
// -------------------------------------------------------------------------

// --- Control Pins (控制引脚) ---
// Optimization: CS/RST moved to GPIO 32+, keeping low GPIOs for data bus and WR.
// 您的优化方案:将 CS/RST 移至 GPIO 32+,保留低位 GPIO 给数据总线和 WR。

#define TFT_CS   32  // Chip Select (片选)
#define TFT_RST  33  // Reset (复位)

// Data/Command selection - Must be in GPIO 0-31(or RS)
// 数据/命令选择 - 必须在 GPIO 0-31 (或者叫RS)
#define TFT_DC   14

// Write signal - ★ Critical pin, must be in GPIO 0-31 and keep connections short
// 写信号 - ★关键引脚,必须在 GPIO 0-31 且尽量短线连接
#define TFT_WR   27

// Read signal - If not reading screen data, can connect to 3.3V, but must be defined in library
// 读信号 - 如果不读取屏幕数据,此脚可接 3.3V,但在库中必须定义
#define TFT_RD    2

// --- Data Bus Pins D0 - D7 (数据总线引脚) ---
// Must be within GPIO 0-31 range.
// 必须在 GPIO 0-31 范围内。
// Avoided GPIO 16, 17 (PSRAM/Flash) and 12 (Strap).
// 避开了 GPIO 16, 17 (PSRAM/Flash) 和 12 (Strap)。

#define TFT_D0   26
#define TFT_D1   25
#define TFT_D2   19
#define TFT_D3   18
#define TFT_D4    5  // Note: GPIO 5 is a Strap pin, ensure screen does not pull it high during power-up
                     // 注意:GPIO 5 是 Strap 引脚,上电时请确保屏幕未将其拉高
#define TFT_D5   21
#define TFT_D6   22
#define TFT_D7   23

// -------------------------------------------------------------------------
// 6. Backlight Control (Optional)
//    背光控制 (可选)
// -------------------------------------------------------------------------
// If your screen has a BLK or LED pin, connect it to an ESP32 pin and define it here.
// 如果您的屏幕有 BLK 或 LED 引脚,请连接到 ESP32 的某个引脚并在此定义。
// #define TFT_BL   4            // Example: Connected to GPIO 4 (示例:连接到 GPIO 4)
// #define TFT_BACKLIGHT_ON HIGH // High logic level turns on backlight (背光高电平点亮)

// -------------------------------------------------------------------------
// 7. Font Loading
//    字体加载
// -------------------------------------------------------------------------
// Enable as needed; enabling more fonts consumes more Flash memory.
// 根据需要启用,启用越多占用 Flash 越多。

#define LOAD_GLCD   // Font 1. Original Glcd font
#define LOAD_FONT2  // Font 2. Small 16 pixel high font
#define LOAD_FONT4  // Font 4. Medium 26 pixel high font
#define LOAD_FONT6  // Font 6. Large 48 pixel font
#define LOAD_FONT7  // Font 7. 7 segment 48 pixel font
#define LOAD_FONT8  // Font 8. Large 75 pixel font
#define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48

#define SMOOTH_FONT // Enable smooth font loading (启用平滑字体加载)

// -------------------------------------------------------------------------
// 8. Other Settings
//    其他设置
// -------------------------------------------------------------------------
// In parallel mode, SPI frequency is usually ignored as speed is determined by CPU register write speed.
// Kept here for compatibility.
// 并行模式下,SPI 频率设置通常被忽略,因为速度由 CPU 写寄存器速度决定。
// 但为了兼容性,保留此定义。
#define SPI_FREQUENCY       27000000
#define SPI_READ_FREQUENCY  20000000
#define SPI_TOUCH_FREQUENCY  2500000

// --- Touch Screen Settings (触摸屏设置) ---
// If you use XPT2046 touch function.
// Parallel screens usually have a separate SPI interface for touch (T_CLK, T_CS, T_DIN, T_DO, T_IRQ).
// 如果您使用了触摸功能 XPT2046。
// 并行屏幕通常触摸是独立的 SPI 接口 (T_CLK, T_CS, T_DIN, T_DO, T_IRQ)。

// If using touch, uncomment below and set pins (can use VSPI default pins).
// 如果使用触摸,请取消下面注释并设置引脚 (可以使用 VSPI 默认引脚)。

// #define TOUCH_CS 22
// WARNING: You used TFT_D6 on GPIO 22 above. If using touch, find another pin or use SoftSPI.
// 警告:您上面 TFT_D6 占用了 22,如果用触摸,需另找引脚或使用软 SPI。

Open Example Program

Open the example program through the following path, which can be used for testing:

Arduino IDE: File -> Examples -> TFT_eSPI -> 320 x 240 -> TFT_graphicstest_one_lib

Upload Program - Compilation Error Issue

If your ESP32 board library version has been updated to 3.0.0 or above, you will most likely encounter the following error when compiling TFT_eSPI:

In file included from /Users/shawn/Documents/Arduino/libraries/TFT_eSPI/TFT_eSPI.cpp:24:

/Users/shawn/Documents/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP32.c: In member function 'uint8_t TFT_eSPI::readByte()':

/Users/shawn/Documents/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP32.c:113:9: error: 'gpio_input_get' was not declared in this scope; did you mean 'gpio_num_t'?
113 |   reg = gpio_input_get(); // Read three times to allow for bus access time
|         ^~~~~~~~~~~~~~
|         gpio_num_t
exit status 1

Compilation error: exit status 1

error: 'gpio_input_get' was not declared in this scope

Error Analysis

gpio_input_get() is a macro or function in the early ESP32 low-level development framework (ESP-IDF). In the recently released ESP32 Arduino Core 3.0.x version, Espressif performed a major refactoring of the underlying API, removing or changing many old low-level functions, causing the TFT_eSPI library to fail to find the definition when calling this function, resulting in an error.

You can fix this by downgrading, for example, downgrading the esp32 library to 2.0.x. This is the easiest and most convenient method. However, I provide another method using the modified TFT_eSPI library for fixing:

Find and open this file:

Documents/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP32.c

Add the following macro definition code at the beginning of the code and save the modified file:

#if !defined(gpio_input_get)
  #define gpio_input_get() GPIO.in
#endif

Upload Program Again - Screen Mirroring Issue

At this point, compilation has passed and successfully uploaded to the board, and the screen is also lit. However, don’t celebrate too early yet, because upon careful observation, you’ll find that the screen text is mirrored.

In the example program, make modifications around line 102:

void loop(void) {
  for (uint8_t rotation = 4; rotation < 8; rotation++) {
    tft.setRotation(rotation);
    testText();
    delay(2000);
  }
}

Final Upload

At this point, the display is normal. Congratulations, you have successfully lit up this 2.4-inch TFT display (ILI9341).

FAQ (Frequently Asked Questions)

The following are the most common problems and solutions encountered during development for quick reference.

Q1: Screen lights up white but no display?

  • A1: 90% is because parallel mode is not enabled. Please check again in User_Setup.h if #define ESP32_PARALLEL is uncommented.
  • A2: Check if TFT_RST (GPIO 33) is making good contact.

Q2: Display colors are wrong, red becomes blue?

  • A: This is an RGB order definition issue. In User_Setup.h, change #define TFT_RGB_ORDER TFT_RGB to TFT_BGR (or vice versa).

Q3: Does this configuration support Touch functionality?

  • A: This article only configures the display driver. ILI9341 screens usually come with XPT2046 touch chip, which uses an independent SPI interface. You need to additionally connect touch pins (T_CLK, T_CS, T_DIN, T_DO, T_IRQ) and uncomment TOUCH_CS in User_Setup.h. Warning: Touch uses SPI protocol and cannot share pins with parallel data lines D0-D7.

Q4: Why not use VSPI/HSPI driving directly?

  • A: The theoretical refresh speed of parallel driving (8-bit Parallel) is several times that of SPI, suitable for UI interfaces requiring high frame rates or retro game emulator development.