Source: https://mokxi.com/learn/arduino-ili9341-tft
Updated: 2026-10-05

Learn

# Pong on a color TFT: an ILI9341 on an Arduino Uno

Advanced

Written by the Mokxi team, updated October 5, 2026

Start building free Open the editor

Or see every lesson.

- 261 parts on the bench
- 31 boards running now
- 1.00x real time, on every board

Press the thumb stick to serve, then push it left and right

The Pong console example on a simulated ATmega328P. Press the stick to serve.

The ILI9341 is the chip behind the common 2.4 and 2.8 inch color TFT screens, 240 by 320 pixels. It is a big step up from a small OLED. You get 65,536 colors and room for a real game or a dashboard. It talks to the Arduino over SPI with a few extra control pins.

The circuit above is an Arduino Uno playing Pong on an ILI9341, with a thumb stick to move the paddle and a piezo for the beeps. Press the stick to serve. It runs in your browser on the sketch below, and the way it draws teaches the most important thing about these screens: only redraw what moved.

## What you need

- An Arduino Uno
- A 2.4 inch ILI9341 SPI TFT module (240x320)
- A thumb stick module and a piezo buzzer, for the game
- A full-size breadboard and jumper wires

## Wiring

Part and pin | Goes to | Note

TFT CS | Pin 10 | Chip select

TFT DC | Pin 9 | LOW for a command, HIGH for data

TFT SCK | Pin 13 | SPI clock

TFT MOSI | Pin 11 | SPI data to the screen

TFT RST | 5 V | Tied high here; or wire it to a pin and name it in the sketch

TFT LED | 5 V | The backlight; without it the screen stays dark

TFT VCC and GND | 5 V and GND | Check your module: many want 3.3 V logic

Stick VRX, VRY | A0, A1 | The two axes

Stick SW | Pin 2 | The press

Piezo | Pin 6 and GND | The beeps

## DC: command or data

The ILI9341 has one extra pin that makes it different from a plain SPI chip: DC, for data or command. When DC is LOW, the byte you send is a command, like "set the window" or "start writing pixels". When DC is HIGH, the bytes are the data for that command, including the pixels themselves.

Drawing a rectangle is three steps. Set the column range, set the row range, then stream the right number of pixel colors. Every library does exactly this under the hood.

## Why the game only redraws what moved

Each pixel is 16 bits, and the whole screen is 76,800 pixels. That is a lot of data for an Uno. In Mokxi the Uno model has no SPI hardware, so every bit is sent by hand, and clearing the whole screen takes about a second and a half. A real Uno’s hardware SPI is faster, but a full redraw is still too slow for a smooth game.

So the sketch draws the frame, the labels and the score once. After that, each frame only repaints the ball and the strip of paddle that moved: under two thousand pixels, which keeps the game at 30 frames a second. The game also lives in a 160 by 200 window in the middle of the screen, which makes the one-time clear shorter.

This habit, draw once and then update only what changed, is the key to any fast display project, on any board.

Drawing the fixed parts once, from the Pong console example

## Using the Adafruit library

The example uses mokxi_ili9341.h, a small driver that ships with Mokxi. On a real Uno, most tutorials use the Adafruit_ILI9341 and Adafruit_GFX libraries, and Mokxi ships headers with those names and their usual calls too. The hello world below is written the way those tutorials write it.

Mokxi’s version has a few differences. The built-in font is Mokxi’s own 5x8, and the Fonts/ headers are Mokxi’s letters at each font’s size. Nothing is read back from the screen. And the bus is software SPI, so draw what moved rather than filling the whole screen often.

Hello world with the Adafruit ILI9341 library

## Try it in the editor

Change BALL_COLOUR to ILI9341_RED and the ball turns red. Colors are 16-bit RGB565 numbers, so you can also write your own, like 0xF81F for magenta.

Make the paddle wider by raising PADDLE_W from 36 to 60, and the game gets easier. Make the window bigger by changing FW and FH, and watch the first clear take longer.

## Common mistakes

A white or dark screen. Check the LED pin: it is the backlight, and the screen stays dark without it. A white screen with the backlight on usually means the init never ran: check CS, DC and RST.

5 V logic on a 3.3 V screen. Many ILI9341 modules are 3.3 V parts. Some have a level shifter on the board and some do not. Check yours before you wire it to an Uno, and use level shifters if needed.

Clearing the whole screen every frame. It flickers and crawls. Draw the background once and repaint only what changed.

Mixing up DC and CS in the constructor. The order is CS first, then DC.

## Questions

Which pins does an ILI9341 use on an Arduino Uno?

SCK to 13 and MOSI to 11 (the Uno’s SPI pins), CS and DC to any two pins you name in the sketch, RST to a pin or to the supply, and LED to the supply for the backlight.

Why is my ILI9341 so slow on an Uno?

A full screen is 76,800 pixels of 16 bits each. Redraw only what changes. In Mokxi the Uno’s SPI is done in software, so it is slower still, and the Pong example shows how to work within that.

Does Mokxi support the touch version?

Yes. There is an ILI9341 with a touch panel in the parts bin, read with the XPT2046_Touchscreen library, and a Touch paint project that uses it.

Related

## Keep going

Arduino OLED Display (SSD1306) Tutorial SPI Explained: Clock, Data and Chip Select Arduino Joystick Module: Wiring, Code, Live Demo Arduino I2C LCD 16x2: Wiring and Code How the ILI9341 is modeled Snake on the same screen Advanced The Arduino Uno simulator The project page, with the full sketch Advanced

## Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.

Start building free Open the editor
