GC9A01 Round TFT Display
with ESP32 Dev Board
What You Need
Parts
- ESP32 Dev Board (38-pin)
- GC9A01 240x240 round IPS TFT module
- Jumper wires
- USB data cable for flashing
Software
- Arduino IDE with ESP32 board support
Arduino_GFX_Libraryby Moon On Our Nation
Install via Arduino IDE Library Manager - search Arduino_GFX.
How It Works
The GC9A01 is a round 240x240 IPS TFT driven over SPI. It's write-only - no MISO line needed. The breakout module includes onboard voltage regulation so it runs happily from either 3.3V or 5V. The ESP32 pushes pixel data fast enough for smooth animations.
The display controller expects commands and data over 4-wire SPI: clock (SCL), data (SDA), chip select (CS), and data/command select (DC). A reset pin (RST) handles hardware resets on startup.
Wiring
| Display Pin | ESP32 Pin | Notes |
|---|---|---|
| VCC | 3.3V or 5V | Module has onboard regulator - accepts 3.3V or 5V |
| GND | GND | |
| SCL | GPIO 18 | SPI clock (SCLK) |
| SDA | GPIO 23 | SPI data (MOSI) |
| DC | GPIO 27 | Data / Command select |
| CS | GPIO 5 | Chip select |
| RST | GPIO 4 | Reset |
No MISO connection needed - the GC9A01 is write-only. The module includes onboard voltage regulation so VCC accepts either 3.3V or 5V.
Library Setup
Open Arduino IDE, go to Tools → Manage Libraries, search for Arduino_GFX and install Arduino_GFX Library by Moon On Our Nation.
This library supports the GC9A01 natively and is significantly faster than Adafruit alternatives for this display. It also has a clean API for drawing primitives, text, and bitmaps.
Test Sketch
Flash this to confirm your wiring is correct. Renders a 150-star warp speed starfield - stars stream toward you from the centre. Smooth animation means everything is working.
/*
* We stand on the shoulders of giants when we build
* with knowledge gained from others' efforts.
* That doesn't make us giants. Be humble.
* Create with care. Open source is the way.
*
* GC9A01 Round TFT Display - Starfield Test Sketch
* -------------------------------------------------
* Renders a 150-star warp speed starfield on a
* GC9A01 240x240 round IPS TFT display via SPI.
* Stars stream from centre to edge with perspective.
* Confirms wiring, library, and animation are working.
*
* Board: ESP32 Dev Board (38-pin)
* Library: Arduino_GFX_Library by Moon On Our Nation
*
* Wiring:
* VCC -> 3.3V or 5V GND -> GND
* SCL -> GPIO 18 SDA -> GPIO 23
* DC -> GPIO 27 CS -> GPIO 5
* RST -> GPIO 4
*
* Open source - MIT Licence
* Full guide and wiring diagram:
* https://electroniczoology.com/guides/gc9a01-round-display-esp32
*
* Electronic Zoology - field notes from the garage
*/
#include <Arduino_GFX_Library.h>
#define TFT_DC 27
#define TFT_CS 5
#define TFT_RST 4
Arduino_DataBus *bus = new Arduino_HWSPI(TFT_DC, TFT_CS);
Arduino_GFX *gfx = new Arduino_GC9A01(bus, TFT_RST, 0, true);
#define CX 120
#define CY 120
#define NUM_STARS 150
#define SPEED 3.5f
struct Star { float x, y, z; int px, py; };
Star stars[NUM_STARS];
void resetStar(Star &s) {
s.x = random(-120, 120);
s.y = random(-120, 120);
s.z = random(60, 240);
s.px = -1;
s.py = -1;
}
// Pack a grey brightness value into RGB565
uint16_t grey(uint8_t v) {
return ((v >> 3) << 11) | ((v >> 2) << 5) | (v >> 3);
}
void drawTitle() {
gfx->setTextColor(0xFFFF);
gfx->setTextSize(2);
gfx->setCursor(60, 100);
gfx->print("Electronic");
gfx->setCursor(54, 122);
gfx->print("Zoology.com");
}
void setup() {
Serial.begin(115200);
randomSeed(analogRead(0));
gfx->begin();
gfx->fillScreen(0x0000);
for (int i = 0; i < NUM_STARS; i++) {
resetStar(stars[i]);
stars[i].z = random(1, 240); // spread z on startup
}
}
void loop() {
for (int i = 0; i < NUM_STARS; i++) {
Star &s = stars[i];
// Erase previous position
if (s.px >= 0) {
gfx->fillCircle(s.px, s.py, s.z > 120 ? 1 : 2, 0x0000);
}
s.z -= SPEED;
if (s.z <= 1) { resetStar(s); continue; }
// Perspective projection
int sx = CX + (int)(s.x * 120.0f / s.z);
int sy = CY + (int)(s.y * 120.0f / s.z);
if (sx < 0 || sx >= 240 || sy < 0 || sy >= 240) {
resetStar(s); continue;
}
// Closer = brighter and bigger
uint8_t brightness = (uint8_t)((1.0f - s.z / 240.0f) * 220 + 35);
int radius = s.z < 80 ? 2 : 1;
gfx->fillCircle(sx, sy, radius, grey(brightness));
s.px = sx;
s.py = sy;
}
// Redraw title on top of stars each frame
drawTitle();
} Troubleshooting
White screen / no output
- Check wiring - DC and CS are the most commonly swapped pins
- Confirm RST is connected, not floating
- Confirm VCC has power - module accepts 3.3V or 5V
Garbled pixels, green lines, wrong colours
- Bad display batch - a known issue with some AliExpress AU depot stock
- If after many hours of exhausting debugging nothing works 😩 try a different supplier
- The code may not be the problem - try a different display before deep debugging
Display initialises but nothing draws
- Make sure you're using
Arduino_GFX_Library, not TFT_eSPI or Adafruit_GC9A01A - Constructor arguments differ between libraries - copy the exact sketch above
Works on desk, crashes when enclosed
- Heat - the ESP32 WiFi radio plus SPI generates real heat in an enclosure
- Bond a small heatsink or aluminium offcut to the ESP32