Adding a full-colour TFT display to your Arduino project transforms it from a blinking-LED prototype into a polished, professional device. The ST7789 controller chip drives some of the sharpest, brightest small displays available — 240×240 pixels of 65,536 colours on screens as compact as 1.3 inches. Whether you are building a weather station dashboard, a retro game console, a sensor readout, or a smart clock, this tutorial gets you from unboxed module to drawing graphics in under an hour.
Table of Contents
- ST7789 Display Overview and Common Modules
- Wiring the ST7789 to Arduino
- Library Installation and First Sketch
- Drawing Basics: Shapes, Text, and Colours
- Displaying Images and Sprites
- Project: Weather Station Display
- Performance Tips for Smooth Updates
- Frequently Asked Questions
ST7789 Display Overview and Common Modules
The ST7789 is an IPS TFT LCD controller from Sitronix. IPS (In-Plane Switching) technology gives it far better colour accuracy and viewing angles compared to older TN panels — you can view the screen from nearly any angle without colour shift. Key specifications:
- Resolution: 240×240 (most common), also 240×320 and 135×240 variants
- Colour depth: 16-bit (65,536 colours) or 18-bit (262,144 colours)
- Interface: 4-wire SPI (up to 80 MHz clock)
- Supply voltage: 3.3V (logic and backlight) — needs level shifting from 5V Arduino
- Refresh rate: Up to 60 fps possible with optimised code
Common ST7789 Module Variants
You will typically find ST7789 modules in these form factors:
- 1.3″ 240×240 IPS — most common for Arduino projects, square aspect ratio
- 1.54″ 240×240 IPS — slightly larger, same resolution, very sharp
- 2.0″ 240×320 IPS — portrait orientation, similar to phone screen feel
- 0.96″ 80×160 — uses ST7735 controller, sometimes confused with ST7789
Check your module’s datasheet or seller listing to confirm the exact controller and resolution — the library initialisation parameters differ between variants.
Wiring the ST7789 to Arduino
The ST7789 uses SPI for data transfer and requires 3.3V logic. Since the Arduino Uno operates at 5V, you need level shifting on the SPI data lines. Many ST7789 modules include on-board level shifters — check your module documentation.
Pins on the ST7789 Module
| Module Pin | Function |
|---|---|
| GND | Ground |
| VCC | Power (3.3V or 5V if module has regulator) |
| SCL / SCK | SPI clock |
| SDA / MOSI | SPI data in to display |
| RES / RST | Reset (active low) |
| DC / A0 | Data/Command select |
| CS / BLK | Chip select / Backlight |
Wiring to Arduino Uno (Module with On-Board Level Shifter)
| ST7789 Module | Arduino Uno |
|---|---|
| GND | GND |
| VCC | 5V |
| SCL | D13 (SCK) |
| SDA | D11 (MOSI) |
| RST | D8 |
| DC | D7 |
| CS | D10 |
For bare ST7789 modules without level shifters (direct 3.3V logic), connect VCC and all signal pins to the Arduino’s 3.3V pin and use 330Ω resistors in series on SCK, MOSI, RST, DC, and CS lines from the 5V Arduino. Better yet, use a 3.3V Arduino like the Arduino Pro Mini 3.3V or Nano 33 for a cleaner design.
Library Installation and First Sketch
The recommended library combination is Adafruit ST7789 with Adafruit GFX Library. Install both from Arduino Library Manager (Sketch → Include Library → Manage Libraries).
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>
// Pin definitions
#define TFT_CS 10
#define TFT_DC 7
#define TFT_RST 8
// Create display object (240x240 — adjust for your module)
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
void setup() {
Serial.begin(115200);
// Initialize display — use correct constructor for your screen size
tft.init(240, 240); // Width, height in pixels
tft.setRotation(0); // 0-3 for portrait/landscape orientations
// Fill screen with black
tft.fillScreen(ST77XX_BLACK);
// Draw white text
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(2);
tft.setCursor(10, 10);
tft.println("Hello, India!");
Serial.println("Display initialized!");
}
void loop() {
// Nothing here for now
}
If your display shows a blank white or black screen with no output, try changing tft.setRotation() to values 0–3. Also verify your DC and CS pin assignments in the constructor match your wiring.
Drawing Basics: Shapes, Text, and Colours
The Adafruit GFX library provides a rich set of drawing primitives:
// Colours (16-bit RGB565 format)
#define MY_RED 0xF800
#define MY_GREEN 0x07E0
#define MY_BLUE 0x001F
#define MY_YELLOW 0xFFE0
#define MY_CYAN 0x07FF
#define MY_PURPLE 0x780F
void drawBasicShapes() {
tft.fillScreen(ST77XX_BLACK);
// Filled rectangle
tft.fillRect(10, 10, 80, 60, MY_RED);
// Outline circle
tft.drawCircle(160, 40, 30, MY_GREEN);
// Filled triangle
tft.fillTriangle(120, 80, 60, 140, 180, 140, MY_BLUE);
// Rounded rectangle
tft.drawRoundRect(10, 90, 100, 50, 10, MY_YELLOW);
// Line
tft.drawLine(0, 0, 240, 240, MY_CYAN);
}
void displayText() {
tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK); // Text, background
// Size 1 = 6×8 pixels, Size 2 = 12×16, Size 3 = 18×24
tft.setTextSize(1); tft.setCursor(10, 10); tft.println("Small text");
tft.setTextSize(2); tft.setCursor(10, 30); tft.println("Medium text");
tft.setTextSize(3); tft.setCursor(10, 60); tft.println("Large");
}
Custom Colours with RGB565
Convert any RGB colour to 16-bit RGB565 format:
// Convert R,G,B (each 0-255) to RGB565
uint16_t color565(uint8_t r, uint8_t g, uint8_t b) {
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}
// Orange: R=255, G=128, B=0
uint16_t orange = color565(255, 128, 0);
Displaying Images and Sprites
To display a bitmap image (logo, icon, photo thumbnail), convert it to a C array using the image2cpp tool (available online at javl.github.io/image2cpp/). Select RGB565 output format, resize to fit your screen, and it generates a header file with the pixel array.
// Include your generated image header
#include "logo.h" // Contains: const uint16_t logo[] PROGMEM = {...};
// Display at position x=0, y=0, width=80, height=80
tft.drawRGBBitmap(0, 0, logo, 80, 80);
The PROGMEM keyword is critical on AVR Arduinos — it stores the large pixel array in flash memory rather than RAM. A 240×240 image at 16-bit colour is 115,200 bytes — far more than the Uno’s 2KB RAM can hold. Always use PROGMEM for images on ATmega boards.
Project: Weather Station Display
This project reads temperature and humidity from a DHT11 sensor and displays them on the ST7789 with a graphical layout:
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <DHT.h>
#define TFT_CS 10
#define TFT_DC 7
#define TFT_RST 8
#define DHT_PIN 6
Adafruit_ST7789 tft(TFT_CS, TFT_DC, TFT_RST);
DHT dht(DHT_PIN, DHT11);
void drawHeader() {
tft.fillRect(0, 0, 240, 40, 0x02B5); // Dark blue header
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(2);
tft.setCursor(45, 12);
tft.print("Weather Station");
}
void displayReading(float temp, float hum) {
// Temperature card
tft.fillRoundRect(10, 50, 220, 80, 12, 0xF800); // Red card
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(1); tft.setCursor(20, 60); tft.print("TEMPERATURE");
tft.setTextSize(4); tft.setCursor(20, 78);
tft.print(temp, 1); tft.print(" C");
// Humidity card
tft.fillRoundRect(10, 145, 220, 80, 12, 0x001F); // Blue card
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(1); tft.setCursor(20, 155); tft.print("HUMIDITY");
tft.setTextSize(4); tft.setCursor(20, 173);
tft.print(hum, 1); tft.print(" %");
}
void setup() {
tft.init(240, 240);
tft.setRotation(2);
tft.fillScreen(ST77XX_BLACK);
dht.begin();
drawHeader();
}
void loop() {
float t = dht.readTemperature();
float h = dht.readHumidity();
if (!isnan(t) && !isnan(h)) {
displayReading(t, h);
}
delay(2000); // Update every 2 seconds
}
Performance Tips for Smooth Updates
The biggest performance bottleneck with ST7789 on AVR Arduino is SPI speed. The ATmega328P can only clock SPI at 8 MHz maximum (half of 16 MHz system clock). Filling the entire 240×240 screen takes about 55 ms — at most 18 full frame refreshes per second.
1. Only Redraw What Changed
Instead of tft.fillScreen(BLACK) followed by redrawing everything, only update the specific regions that changed. On a weather dashboard, only the temperature/humidity text changes — redraw just those rectangles:
// Clear only the number area, not the whole screen
tft.fillRect(20, 78, 200, 50, 0xF800); // Same colour as card background
tft.setCursor(20, 78);
tft.print(newTemp, 1);
2. Increase SPI Clock Speed
The default Adafruit library uses 40 MHz SPI — this is automatically capped at the hardware maximum for your platform. On an RP2040 or Nano 33 at 48+ MHz, you can achieve much faster full-screen redraws.
3. Use the TFT_eSPI Library for Maximum Speed
The TFT_eSPI library by Bodmer is significantly faster than Adafruit’s implementation, especially on ESP32 and RP2040. For AVR Arduinos, the speed difference is smaller but still meaningful. It requires configuration via a User_Setup.h file rather than constructor arguments.
4. Use Hardware SPI, Not Software SPI
Always connect the display to the hardware SPI pins (D11/D12/D13 on Uno). Software SPI (any arbitrary pins) is 10–20× slower because it is bit-banged in firmware.
Frequently Asked Questions
My ST7789 display shows only a white screen — what is wrong?
A solid white screen usually means the initialisation command sequence is not reaching the display correctly. Check: (1) SPI wiring — particularly that MOSI (not MISO) connects to the display’s SDA pin; (2) DC pin is connected — without the DC pin, the display cannot distinguish commands from data; (3) The module needs 3.3V logic but you are driving it with 5V without level shifters; (4) Try adding a 10 µF capacitor across VCC-GND and a 0.1 µF bypass capacitor.
Can I use ST7789 with Arduino Mega?
Yes. The Mega’s hardware SPI pins are D50 (MISO), D51 (MOSI), D52 (SCK) — different from the Uno’s D11/D12/D13. Use these pins for SCK and SDA/MOSI, while CS, DC, and RST can be any digital pins. Update the pin definitions in your sketch accordingly.
How do I display Hindi or regional language text?
The default Adafruit GFX font set only includes ASCII characters (English). For Indian language scripts (Hindi, Tamil, Telugu, etc.), you need a custom font containing the Unicode characters for your script, converted using the Adafruit font converter tool. Alternatively, display pre-rendered bitmap images of text in your language.
What is the difference between ST7789 and ST7735?
Both are SPI TFT controllers from Sitronix. The ST7735 is older and typically drives smaller 128×160 or 128×128 screens. The ST7789 supports higher resolutions (up to 240×320) with better colour fidelity and IPS panel technology. They use different initialisation sequences and different Adafruit library classes (Adafruit_ST7735 vs Adafruit_ST7789).
Can ST7789 display video?
Not practical on AVR Arduino. Video at 30 fps would require transferring 240×240×2×30 = ~3.5 MB/s of pixel data continuously — far beyond what Arduino Uno’s 8 MHz SPI can handle. On an ESP32 or RP2040 with DMA, smooth video playback from an SD card is achievable at reduced resolutions. For AVR boards, limit yourself to animations with small sprites or partial-screen updates.
Ready to build your colour display project? Browse our full range of Arduino boards, TFT displays, and sensors at Zbotic.in — fast delivery across India, with expert support for your projects.
Add comment