Skip to content

MicroPython ST7789V LCD Display

Welcome to the ST7789V Color LCD Lab

Monty waving welcome In this lab, you will connect a beautiful 2-inch color display to your Pico and write code to show text in many colors. Let's paint the screen!

What Is This Display?

The ST7789 is a driver chip made by a company called Sitronix. It controls small color Liquid Crystal Displays (LCDs) that use an In-Plane Switching (IPS) panel. IPS panels look great from any angle — the colors stay bright even when you look at the screen from the side.

This lab uses a 2-inch color LCD made by Waveshare. It costs about $13 to $15.

Specifications

  • Resolution: 240 pixels wide by 320 pixels tall
  • Color depth: 18-bit color (6 bits each for Red, Green, and Blue)
  • Interface: 4-wire Serial Peripheral Interface (SPI)
  • Operating voltage: 3.3V

Important note about SPI: The ST7789 uses SPI to send data, but it only uses the MOSI (data out) wire. It does not send data back to the Pico. You only need four wires to connect it.

Device Interface

Here are the pins on the back of the display board:

  1. VCC — Power supply (connect to 3.3V)
  2. GND — Ground
  3. DIN — SPI data input (MOSI)
  4. CLK — SPI clock input
  5. CS — Chip select (active when set Low)
  6. DC — Data or Command select (High = data, Low = command)
  7. RST — Reset (active when set Low)
  8. BL — Backlight (tie to GND to turn the backlight on)

Although there are eight wires, the Pico only controls a few of them through General-Purpose Input/Output (GPIO) pins.

Watch Out!

Monty warning This display runs on 3.3V. Never connect it to a 5V power supply. Using 5V can damage the driver chip permanently.

Uploading the ST7789V Firmware

This display needs a special firmware file. The firmware includes the display driver and built-in fonts. You need to load it onto your Pico before running any code.

Follow these steps to install the firmware:

  1. Download the firmware file from this GitHub page. Look for a file ending in .uf2.
  2. Hold down the BOOTSEL button on your Pico.
  3. While holding BOOTSEL, plug the Pico into your computer with a USB cable.
  4. Release the BOOTSEL button. A new drive called RPI-RP2 will appear on your computer.
  5. Drag the .uf2 firmware file into that drive.
  6. The Pico will restart automatically with the new firmware ready to use.

Wiring the Display to the Pico

Connect the display to Pico SPI port 1 using the pins along the lower-left corner of the Pico:

Pico Pin Number GPIO Number Display Label
14 GP10 BL (Backlight)
15 GP11 RST (Reset)
16 GP12 DC (Data/Command)
17 GP13 CS (Chip Select)
18 GND GND
19 GP14 CLK (Clock)
20 GP15 DIN (Data In)

Why These Pins?

Monty thinking The Pico has two SPI ports: SPI0 and SPI1. This wiring uses SPI1. The clock and data pins for SPI1 are fixed — they must be on GP14 and GP15. The other pins (CS, DC, RST, BL) can be on almost any GPIO.

Set Up the Display

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from machine import Pin, SPI    # import Pin for GPIO and SPI for the fast data bus
import st7789                   # import the ST7789 display driver

# give each pin a clear name so the code is easy to read
BACKLIGHT_PIN = 10   # controls the screen backlight
RESET_PIN = 11       # resets the display
DC_PIN = 12          # tells display: is this data or a command?
CS_PIN = 13          # chip select — activates the display
CLK_PIN = 14         # SPI clock — keeps data in sync
DIN_PIN = 15         # SPI data — sends pixel information to the display

import vga1_bold_16x32 as font  # import a bold font that is 16 pixels wide and 32 pixels tall

# set up the SPI bus at 31,250,000 bits per second (very fast!)
spi = SPI(1, baudrate=31250000, sck=Pin(CLK_PIN), mosi=Pin(DIN_PIN))

# create the display object: 240 wide, 320 tall, with all control pins
tft = st7789.ST7789(spi, 240, 320,
    reset=Pin(RESET_PIN, Pin.OUT),      # set RST as an output pin
    cs=Pin(CS_PIN, Pin.OUT),            # set CS as an output pin
    dc=Pin(DC_PIN, Pin.OUT),            # set DC as an output pin
    backlight=Pin(BACKLIGHT_PIN, Pin.OUT),  # set BL as an output pin
    rotation=3)                         # rotation=3 puts 0,0 at top-left in landscape mode

tft.init()   # start up the display — sends setup commands to the driver chip

# draw white text on a black background, starting 10 pixels from left and 20 from top
tft.text(font, "Hello World!", 10, 20, st7789.color565(255,255,255), st7789.color565(0,0,0))

What Each Line Does

  1. from machine import Pin, SPI — loads the tools for GPIO pins and SPI communication.
  2. import st7789 — loads the display driver for the ST7789 chip.
  3. BACKLIGHT_PIN = 10 through DIN_PIN = 15 — gives each wire a clear name instead of just a number.
  4. import vga1_bold_16x32 as font — loads a bold font where each letter is 16 pixels wide and 32 pixels tall.
  5. spi = SPI(1, baudrate=31250000, ...) — starts SPI port 1 at a very high speed.
  6. tft = st7789.ST7789(...) — creates the display object with all the pin settings.
  7. rotation=3 — sets the screen to landscape mode with the origin at the top-left corner.
  8. tft.init() — sends startup commands to the display driver chip to wake it up.
  9. tft.text(font, "Hello World!", 10, 20, ...) — draws text. The color565() function converts red, green, blue values into the 16-bit color format the display uses.

Show Text in Four Colors

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from machine import Pin, SPI    # import GPIO and SPI tools
import st7789                   # import the display driver

BACKLIGHT_PIN = 10
RESET_PIN = 11
DC_PIN = 12
CS_PIN = 13
CLK_PIN = 14
DIN_PIN = 15

import vga1_bold_16x32 as font  # use the same bold font

spi = SPI(1, baudrate=31250000, sck=Pin(CLK_PIN), mosi=Pin(DIN_PIN))
tft = st7789.ST7789(spi, 240, 320,
    reset=Pin(RESET_PIN, Pin.OUT),
    cs=Pin(CS_PIN, Pin.OUT),
    dc=Pin(DC_PIN, Pin.OUT),
    backlight=Pin(BACKLIGHT_PIN, Pin.OUT),
    rotation=3)
tft.init()

# draw "Hello World!" four times, each in a different color
tft.text(font, "Hello World!", 10, 0,   st7789.color565(255,255,255), st7789.color565(0,0,0))  # white text
tft.text(font, "Hello World!", 10, 50,  st7789.color565(255,0,0),     st7789.color565(0,0,0))  # red text
tft.text(font, "Hello World!", 10, 100, st7789.color565(0,255,0),     st7789.color565(0,0,0))  # green text
tft.text(font, "Hello World!", 10, 150, st7789.color565(0,0,255),     st7789.color565(0,0,0))  # blue text

What Each Line Does

  1. Lines 1–16 are the same setup as before.
  2. Each tft.text() call draws the same words at a different vertical position (0, 50, 100, 150 pixels from the top).
  3. color565(255,255,255) = white (all red, all green, all blue turned on fully).
  4. color565(255,0,0) = red (only red turned on).
  5. color565(0,255,0) = green (only green turned on).
  6. color565(0,0,255) = blue (only blue turned on).
  7. The second color565(0,0,0) in each line sets the background color to black.

Monty's Tip

Monty giving a tip The color565() function takes three numbers — red, green, and blue — each from 0 to 255. Mix them to make any color you want!

How the Driver Handles Color

The ST7789V chip supports three different color formats. This display uses RGB565. In RGB565, each pixel is stored using 16 bits:

  • 5 bits for red (0–31)
  • 6 bits for green (0–63)
  • 5 bits for blue (0–31)

This is why you use color565() — it converts normal 0–255 color values into the 16-bit format the display expects.

The SPI Communication Timing

The display uses 4-wire SPI. Here is what each wire does during communication:

  1. RESX (Reset): Must be set Low at power-on, then set High for normal operation.
  2. CSX (Chip Select): The display only listens when CS is set Low.
  3. D/CX (Data/Command): When Low, the Pico is sending a command. When High, the Pico is sending pixel data.
  4. SDA (Data): Carries the actual pixel data (RGB values).
  5. SCL (Clock): Keeps the data transfer in sync between the Pico and the display.

Timing Diagram

You can see how the data and clock signals work together in this diagram:

The SPI protocol uses two settings called clock polarity (CPOL) and clock phase (CPHA). Together they make four possible modes. This display uses SPI mode 0 (CPOL=0, CPHA=0). Data is sent 8 bits at a time, starting with the most significant bit.

References

  1. ST7789C Datasheet (PDF)
  2. Waveshare Wiki — 2 inch LCD Module
  3. Waveshare Pico LCD 2

Great Work!

Monty celebrating You connected a color LCD and showed text in four different colors! Next, try drawing shapes or displaying sensor readings on your screen.