Documentation

ShillehTek 2.8" SPI TFT LCD Touch Screen Module 240x320 ILI9341 for Arduino | ShillehTek Product Manual
Documentation / ShillehTek 2.8" SPI TFT LCD Touch Screen Module 240x320 ILI9341 for Arduino | ShillehTek Product Manual

ShillehTek 2.8" SPI TFT LCD Touch Screen Module 240x320 ILI9341 for Arduino | ShillehTek Product Manual

manualshillehtek

Overview

This 2.8" SPI TFT LCD is a 240 x 320 pixel color display built around the ILI9341 controller — one of the most widely supported display chips in the maker world. It packs a sharp full-color screen, a resistive touch overlay (driven by an XPT2046 controller), and a microSD card slot all on one ~50 x 80 mm board, communicating over standard SPI so it works with almost any microcontroller.

You get three SPI peripherals on one PCB: the ILI9341 LCD itself, the XPT2046 touchscreen controller, and the microSD card slot. They share the SPI bus (MOSI / MISO / SCK) and have separate chip-select lines (LCD CS, T_CS, SD_CS), letting you talk to them independently from one bus.

Driver libraries are mature and fast — Adafruit_ILI9341, TFT_eSPI, LovyanGFX, and lvgl all support it on Arduino, ESP32, ESP8266, STM32, RP2040, and others. It's the go-to display for ESP32 dashboards, retro game emulators, weather stations, and handheld instrument projects.

At a Glance

Display
2.8" TFT, 240 x 320 px, 16-bit color
Driver IC
ILI9341 (LCD) + XPT2046 (touch)
Interface
4-wire SPI
Logic Voltage
3.3V (5V tolerant via on-board level shifter on most variants)
Touch
Resistive, 4-wire
Extras
microSD card slot, LED backlight

Specifications

Parameter Value
Display Size 2.8 inch diagonal
Resolution 240 x 320 pixels
Color Depth 16-bit (65k colors), supports 18-bit
LCD Driver IC ILI9341
Touch Driver IC XPT2046 (resistive)
Interface 4-wire SPI for LCD, separate SPI for touch and SD
Logic Voltage 3.3V (level shifter on-board for 5V control)
Supply Voltage (VCC) 3.3V - 5V
Backlight White LED, ~30-100 mA
microSD Slot SPI, FAT16/FAT32
Operating Temperature -10 degC to +60 degC
Module Dimensions ~50 x 86 mm
Active Area ~43 x 57 mm

Pinout Diagram

ILI9341 2.8 inch SPI TFT LCD module pinout diagram showing the left header (T_IRQ, T_DO, T_DIN, T_CS, T_CLK, SDO/MISO, LED, SCK, SDI/MOSI, D/C, RESET, CS, GND, VCC) and the right header for microSD card SPI (SD_CS, SD_MOSI, SD_MISO, SD_SCK)

Wiring Guide

Arduino UNO Wiring

The UNO can drive the LCD over hardware SPI on D11 (MOSI) / D12 (MISO) / D13 (SCK). It's slow on UNO due to 16 MHz SPI, but works for static UIs. Use the LED pin via a 100-ohm series resistor or a transistor — it can pull 30-100 mA.

TFT Pin Arduino UNO Pin
VCC 5V
GND GND
CS D10
RESET D8
D/C D9
SDI (MOSI) D11
SCK D13
LED 3.3V (via 100 ohm)
SDO (MISO) D12 (only if reading)
Tip: If your board has a level shifter, drive it from 5V; otherwise feed 3.3V to VCC and use level-shifters on the data lines. The touch and SD card both share MOSI/MISO/SCK with the LCD — only their CS pins need to be separate.

ESP32 Wiring (TFT_eSPI)

The ESP32 is the natural pairing for this display — fast SPI, plenty of RAM for frame buffers, and TFT_eSPI handles it at 40+ MHz. Use the VSPI pins (default).

TFT Pin ESP32 Pin
VCC 3.3V (or 5V if level-shifter on board)
GND GND
CS GPIO 15
RESET GPIO 4
D/C GPIO 2
SDI (MOSI) GPIO 23
SCK GPIO 18
LED 3.3V
SDO (MISO) GPIO 19
T_CS GPIO 21
T_IRQ GPIO 22 (optional, for touch interrupt)
Info: When using TFT_eSPI, you configure pins in User_Setup.h (or pick a ready-made setup like Setup42_ILI9341_ESP32.h). The library is much faster than Adafruit_ILI9341 on ESP32.

Raspberry Pi Wiring

On a Raspberry Pi, SPI must be enabled via raspi-config. The Pi's CE0/CE1 hardware chip-selects can be used, or any free GPIO. The fbtft framebuffer driver can show the Linux desktop on the LCD.

TFT Pin Raspberry Pi Pin (BCM)
VCC Pin 1 (3.3V) or Pin 2 (5V)
GND Pin 6 (GND)
CS Pin 24 (GPIO 8 / CE0)
RESET Pin 22 (GPIO 25)
D/C Pin 18 (GPIO 24)
SDI (MOSI) Pin 19 (GPIO 10)
SCK Pin 23 (GPIO 11)
LED Pin 12 (GPIO 18, optional PWM dimming)
SDO (MISO) Pin 21 (GPIO 9)
Tip: The notro/fbtft module (now in the mainline kernel) lets you mount the ILI9341 as /dev/fb1 and use it as a normal Linux framebuffer — handy for Kivy, pygame, or even mirroring the desktop with fbcp.

Raspberry Pi Pico Wiring

The Pico has two SPI peripherals (SPI0 and SPI1). Either works, both are fast.

TFT Pin Pico Pin
VCC 3V3 (OUT)
GND GND
CS GP17 (SPI0 CSn)
RESET GP20
D/C GP21
SDI (MOSI) GP19 (SPI0 TX)
SCK GP18 (SPI0 SCK)
LED 3V3 (OUT)

Code Examples

Arduino - Hello World with Adafruit_ILI9341

ili9341_hello.ino
// Install: Adafruit ILI9341 + Adafruit GFX Library

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

#define TFT_CS   10
#define TFT_DC    9
#define TFT_RST   8

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

void setup() {
  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(ILI9341_BLACK);

  tft.setCursor(20, 20);
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(3);
  tft.println("Hello,");
  tft.setTextColor(ILI9341_CYAN);
  tft.println("ILI9341!");
}

void loop() {}

ESP32 - TFT_eSPI Smooth Graphics

ili9341_tft_espi.ino
// Install "TFT_eSPI" library and configure User_Setup.h
// for ILI9341 + your ESP32 SPI pins.

#include <TFT_eSPI.h>

TFT_eSPI tft = TFT_eSPI();

void setup() {
  tft.init();
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);

  tft.setTextFont(4);
  tft.setTextColor(TFT_GREEN, TFT_BLACK);
  tft.drawString("ESP32 + ILI9341", 20, 30);

  // Some shapes
  tft.drawRect(20, 80, 280, 60, TFT_WHITE);
  tft.fillCircle(160, 200, 40, TFT_RED);
}

void loop() {}

ESP32 - Read Touch Coordinates (XPT2046)

ili9341_touch.ino
// Install "XPT2046_Touchscreen" by Paul Stoffregen

#include <SPI.h>
#include <XPT2046_Touchscreen.h>

#define T_CS  21
#define T_IRQ 22

XPT2046_Touchscreen ts(T_CS, T_IRQ);

void setup() {
  Serial.begin(115200);
  ts.begin();
  ts.setRotation(1);
}

void loop() {
  if (ts.touched()) {
    TS_Point p = ts.getPoint();
    Serial.print("x="); Serial.print(p.x);
    Serial.print("  y="); Serial.print(p.y);
    Serial.print("  z="); Serial.println(p.z);
  }
  delay(50);
}

Raspberry Pi Pico - MicroPython (gc9a01-style example, ILI9341 driver)

ili9341_pico.py
# Install "rdagger/micropython-ili9341" driver to /lib

from ili9341 import Display, color565
from machine import Pin, SPI

spi = SPI(0, baudrate=40000000, sck=Pin(18), mosi=Pin(19))
display = Display(spi, dc=Pin(21), cs=Pin(17), rst=Pin(20))

display.clear(color565(0, 0, 0))
display.draw_text8x8(20, 20, "Hello Pico!", color565(255, 255, 255))
display.draw_rectangle(20, 60, 200, 40, color565(0, 255, 255))

Frequently Asked Questions

My screen stays white / black — what's wrong?
The most common causes: (1) RESET not connected (the chip needs a real reset pin, not just power), (2) D/C swapped with CS, or (3) MISO/MOSI swapped. Double-check the pinout against your library configuration. A backlight that comes on but no image usually means the LCD isn't being initialized — check your CS/DC/RESET pins first.
Can I drive it from 5V or only 3.3V?
The ILI9341 chip is strictly 3.3V. Most modules sold for hobby use have an on-board level shifter that lets you drive the data lines and supply VCC from 5V — but some bare boards do not. If you're not sure, power VCC from 3.3V and drive the signal lines from 3.3V logic; that's always safe. Backlight (LED) tolerates either via series resistor.
Is the touch panel capacitive or resistive?
Resistive. It detects pressure, not capacitance, so it works with a stylus, fingernail, or gloved finger — but not multi-touch. Calibrate it with a 4-point routine (touch each corner, save min/max) before mapping raw XPT2046 readings to screen coordinates.
Why is drawing so slow on Arduino UNO?
UNO maxes out around 8 MHz hardware SPI, has only 2 KB of RAM, and no DMA — so full-screen redraws take a noticeable fraction of a second. For smooth animation, move to a faster MCU like the ESP32, RP2040, or STM32. The TFT_eSPI library plus an ESP32 will give you 30+ FPS on this display.
Can I read the SD card and update the display at the same time?
Yes, but they share the SPI bus. Make sure each peripheral has its own CS pin and that you toggle CS correctly between SD and LCD operations. Most libraries handle this when you use SD.begin(SD_CS) alongside tft.begin(). If you get garbled output, you've left two CS lines low at the same time.
How do I rotate the display?
Use tft.setRotation(0..3) in any GFX-based library. Rotation 0 is portrait (240 wide x 320 tall); rotations 1 and 3 are landscape (320 wide x 240 tall). You may need to remap touch coordinates accordingly — most libraries handle this for you if you also call ts.setRotation().
Can I dim the backlight?
Yes — the LED pin is just a resistor-limited input to the backlight LED string. PWM it from any GPIO that supports PWM (use a transistor or MOSFET if your MCU pin can't sink the full current). On ESP32, drive it directly via LEDC and you get smooth 8- to 12-bit dimming.