Home ▸ Arduino ▸ Displays & Interfaces ▸ ST7735 Display Tutorial

ST7735 Arduino Tutorial: SPI Wiring, Text, Shapes and SD Card Images

The 1.8-inch ST7735 is a small color TFT display with a resolution of 128×160 pixels, and it connects to an Arduino over the SPI bus. It shows text, shapes and full-color bitmap images in 65,536 colors, which makes it a good next step for anyone who has outgrown a monochrome OLED. The Adafruit libraries handle the low-level communication, so a working screen needs only a few lines of code.

This tutorial shows how to wire the ST7735 to an Arduino Uno or Nano, install the Adafruit ST7735 and GFX libraries and confirm the setup with a test sketch. You will print text and numbers, draw lines, rectangles and circles, fill the screen with custom colors, change the screen rotation and control the backlight brightness. The last part adds an SD card on the same SPI bus and shows how to load 24-bit BMP images from it.

This display belongs to the Arduino display tutorials. If you need a smaller I2C screen, see the SSD1306 OLED tutorial or the SH1106 OLED tutorial. For a larger color screen with touch, the ILI9341 touchscreen tutorial is the natural upgrade, and the ST7920 graphic LCD tutorial covers a monochrome alternative. For number displays, see the MAX7219 and TM1637 tutorials. The SD card section builds on the SD card SPI tutorial.

ST7735 TFT Display Overview

The ST7735 is the driver chip of a small TFT (thin-film transistor) color display, and the common 1.8-inch module that uses it has a resolution of 128 by 160 pixels. The driver communicates over SPI, which allows fast transfers of pixel data from the Arduino to the screen. Each pixel uses 16 bits of color, which gives 65,536 colors and is enough for text, gauges, icons and small photos.

1.8-inch ST7735 TFT display module showing SPI pins, SD card slot, and backlight LED

ST7735 Specifications

SpecificationDetail
Display size1.8 inch, measured diagonally
Resolution128 × 160 pixels
Driver ICST7735
InterfaceSPI
Color depth16-bit, 65,536 colors
Logic level3.3 V
Supply voltage3.3 V, or 5 V on modules that include a regulator
BacklightWhite LED, controlled through the BL pin
ExtrasMany modules include a microSD card slot

Why Use the ST7735 with Arduino

  • SPI wiring needs only a few pins and works with the Uno, the Nano and the Mega.
  • The 16-bit color output suits gauges, graphs, menus and icons much better than a monochrome screen.
  • The Adafruit ST7735 and GFX libraries are well supported, and they use the same drawing functions as the SSD1306 OLED, so the code is easy to move between displays.
  • The module is small, inexpensive and light, which suits handheld and portable projects.

The controller itself works with 3.3 V logic. Many 1.8-inch modules add a voltage regulator and resistors on the signal lines so that they can run from a 5 V Arduino, but the exact circuit depends on the seller. The wiring section explains how to check your module.


ST7735 Pinout

The pin labels vary slightly between sellers, but most 1.8-inch modules use the pins in the diagram and table below.

ST7735 1.8-inch TFT pinout diagram showing the GND, VCC, SCL, SDA, RES, DC, CS and BL pins
PinFunctionDescription
GNDGroundConnects to the Arduino ground
VCCPower3.3 V, or 5 V on modules with an onboard regulator
SCL (CLK)SPI clockSynchronizes the data transfer
SDA (MOSI)SPI dataCarries pixel and command data from the Arduino to the display
RES (RESET)ResetResets the display when pulled LOW
DC (A0)Data or commandLOW means the byte is a command, and HIGH means it is data
CSChip selectEnables the display while it is LOW
BL (LED)BacklightConnect to 3.3 V for constant light, or drive it through a transistor for dimming

Modules with an SD card slot add the pins SD_CS, SD_MISO, SD_MOSI and SD_SCK, which belong to the card and not to the display. The SD card section below uses them.


ST7735 Arduino Wiring

The display uses the hardware SPI pins of the Arduino. On the Uno and the Nano, MOSI is on pin 11, MISO is on pin 12 and SCK is on pin 13. On the Mega, they are on pins 51, 50 and 52. The Arduino UNO pinout guide and the Arduino Nano pinout guide show all SPI pins in detail.

ST7735 to Arduino Uno wiring diagram with CS on D10, DC on D9, RES on D8, SDA on D11 and SCL on D13
ST7735 pinArduino Uno and Nano pinDescription
VCC5V or 3.3V, depending on the modulePower supply
GNDGNDCommon ground
SCL (CLK)D13SPI clock
SDA (MOSI)D11SPI data from the Arduino to the display
RES (RESET)D8Reset control
DC (A0)D9Data or command selection
CSD10Chip select
BL (LED)3.3VBacklight on

Check the Voltage Levels

An Arduino Uno outputs 5 V signals, while the ST7735 controller expects 3.3 V. Read the description of your module before you connect it.

  • If the module has a regulator on VCC and a level shifter or resistor dividers on the signal lines, you can connect it directly to a 5 V board.
  • If it has neither, power it from 3.3 V and place a level shifter or a resistor divider on SCK, MOSI, CS, DC and RES. A divider of 1 kΩ in series and 2 kΩ to ground works well.
  • A bare backlight pin without a series resistor can draw too much current, so connect BL through a resistor of about 100 Ω unless the module already includes one.

ST7735 SPI Communication

In SPI, the Arduino is the master, and the display is the slave. Four signals do the work.

  • SCL carries the clock that times each bit.
  • SDA (MOSI) carries the data from the Arduino to the display.
  • CS selects the display, so several SPI devices can share the same clock and data lines.
  • DC tells the display whether the next byte is a command or pixel data.

The display only receives data and never sends any back, so the MISO line is not needed for the display itself. Short wires reduce noise, and a regulated 3.3 V supply gives the most stable picture. If the picture flickers or the colors break up, shorten the wires or lower the SPI speed.


ST7735 Library Setup

Two Adafruit libraries are needed. The Adafruit ST7735 and ST7789 library controls the display, and the Adafruit GFX library provides the drawing functions for text, shapes and bitmaps.

Install the Adafruit ST7735 and GFX Libraries

  1. Open the Arduino IDE and go to Sketch, then Include Library, then Manage Libraries.
  2. Search for “Adafruit ST7735” and install Adafruit ST7735 and ST7789 Library.
  3. Search for “Adafruit GFX Library” and install it, if the IDE did not install it together with the first library.
Arduino IDE File menu with the graphicstest example listed under the Adafruit ST7735 and ST7789 Library examples

Keep both libraries up to date and use the versions from Adafruit, because older copies can cause compile errors.


ST7735 Test Sketch

A short sketch confirms that the wiring and the libraries work before you try anything larger. It sets up the display, fills the screen with black and prints a line of text.

#include <Adafruit_GFX.h>      // Core graphics library
#include <Adafruit_ST7735.h>   // ST7735 driver library
#include <SPI.h>

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

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

void setup() {
  Serial.begin(9600);

  tft.initR(INITR_BLACKTAB);   // Initialization for most 1.8-inch modules
  tft.fillScreen(ST77XX_BLACK);

  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(2);
  tft.setCursor(10, 20);
  tft.println("ST7735 Test!");

  Serial.println("Display initialized.");
}

void loop() {
}

The display should show the text “ST7735 Test!” in white on a black background.

ST7735 display showing the text ST7735 Test in white on a black background after initialization

Choose the Right Initialization Tab

The initR() function takes a tab color that selects the initialization sequence for your panel. The tab color is the color of the plastic protective film on the display when it was new, and it has no relation to the colors on the screen. Most 1.8-inch modules use INITR_BLACKTAB. If the screen is blank, shifted by a few pixels, shows a noisy line at the edge or displays wrong colors, try one of the other tabs.

tft.initR(INITR_GREENTAB);   // Alternatives: INITR_REDTAB, INITR_BLACKTAB

Try each option until the picture is correct. A 1.44-inch display with 128 by 128 pixels needs INITR_144GREENTAB in place of the tabs above.


Run the graphicstest Example

The library includes a larger test sketch that draws lines, shapes, color bars and text, so it checks the whole display. Open it from File, then Examples, then Adafruit ST7735 and ST7789 Library, then graphicstest.

Arduino IDE with the graphicstest example sketch of the Adafruit ST7735 library selected from the examples menu

The example is written for other pins by default, so edit the top of the sketch before you upload it. Set TFT_CS to 10, TFT_RST to 8 and TFT_DC to 9, and make sure that the line tft.initR(INITR_BLACKTAB); is the active initialization line.

Animated capture of the Adafruit graphicstest sketch on an ST7735 display cycling through lines, shapes, color bars and text

When the demo runs without problems, the wiring, the power and the SPI communication are all correct.


ST7735 Text and Numbers

The Adafruit GFX library prints text with the same print() and println() functions that the Serial Monitor uses. The functions below control the appearance of the text.

  • tft.setTextColor(color) sets the text color.
  • tft.setTextSize(size) multiplies the size of the built-in 6 by 8 pixel font by a whole number.
  • tft.setCursor(x, y) sets the position of the top-left corner of the next character.
  • tft.println() prints text or a number and moves to the next line.
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>

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

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

void setup() {
  tft.initR(INITR_BLACKTAB);
  tft.fillScreen(ST77XX_BLACK);

  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(1);
  tft.setCursor(10, 20);
  tft.println("Hello World!");

  tft.setTextColor(ST77XX_RED);
  tft.setTextSize(2);
  tft.setCursor(10, 80);
  tft.println(123.45);
}

void loop() {
}
ST7735 display showing Hello World in small green text and the number 123.45 in larger red text

At text size 1, the screen fits 21 characters per line and 20 lines, and at size 2 it fits 10 characters per line and 10 lines.

Update Values Without Flicker

A sketch that clears the whole screen with fillScreen() before every update makes the display flicker. A better method is to give setTextColor() a second color for the background. Each character then erases the pixels behind it, and the old value disappears without a clear step.

tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);   // Text color, background color
tft.setCursor(10, 40);
tft.print(temperature, 1);
tft.print(" C  ");   // Trailing spaces cover a longer previous value

This approach suits sensor readouts. The DHT11 and DHT22 tutorial, the BME280 tutorial and the MPU6050 tutorial provide values that you can print this way, and the DS3231 clock tutorial provides the time for a clock face.


ST7735 Shapes and Colors

The GFX library draws lines, rectangles and circles with a single function call each. The coordinates start at the top-left corner at (0, 0), with X growing to the right and Y growing downward.

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

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

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

void setup() {
  tft.initR(INITR_BLACKTAB);
  tft.fillScreen(ST77XX_BLACK);

  tft.drawLine(0, 0, 127, 159, ST77XX_WHITE);   // Diagonal line
  tft.drawRect(10, 10, 60, 40, ST77XX_RED);     // Rectangle outline
  tft.fillRect(20, 20, 60, 40, ST77XX_BLUE);    // Filled rectangle
  tft.drawCircle(64, 100, 30, ST77XX_YELLOW);   // Circle outline
  tft.fillCircle(64, 100, 20, ST77XX_GREEN);    // Filled circle
}

void loop() {
}

The functions take the following arguments.

  • drawLine(x0, y0, x1, y1, color) draws a line between two points.
  • drawRect(x, y, width, height, color) and fillRect() draw a rectangle outline and a filled rectangle.
  • drawCircle(x, y, radius, color) and fillCircle() draw a circle outline and a filled circle around the center point.
ST7735 display showing a diagonal line, a red rectangle outline, a filled blue rectangle and yellow and green circles

These shapes are the basis for progress bars, gauges, icons and simple charts.

Fill the Screen with a Color

The fillScreen() function fills the whole display with one color. This sketch cycles through three colors.

void loop() {
  tft.fillScreen(ST77XX_BLUE);
  delay(1000);
  tft.fillScreen(ST77XX_RED);
  delay(1000);
  tft.fillScreen(ST77XX_BLACK);
  delay(1000);
}
Animated capture of an ST7735 screen changing between full-screen blue, red and black every second

The library defines the color constants ST77XX_BLACK, ST77XX_WHITE, ST77XX_RED, ST77XX_GREEN, ST77XX_BLUE, ST77XX_YELLOW, ST77XX_CYAN, ST77XX_MAGENTA and ST77XX_ORANGE. Any other color comes from the color565() function, which converts red, green and blue values from 0 to 255 into the 16-bit format of the display.

uint16_t myColor = tft.color565(255, 100, 50);   // Red, green, blue
tft.fillScreen(myColor);

The 16-bit format keeps 5 bits for red, 6 bits for green and 5 bits for blue, which gives 65,536 different colors.


ST7735 Rotation and Brightness

Two more settings change how the display looks in a finished project.

Rotate the Screen

The setRotation() function turns the drawing area in steps of 90 degrees. It is useful when the display is mounted sideways or upside down in an enclosure.

ValueOrientationWidth × height
0Portrait128 × 160
1Landscape160 × 128
2Portrait, upside down128 × 160
3Landscape, upside down160 × 128

Call tft.setRotation(1); right after tft.initR(), and use tft.width() and tft.height() in your code, so that your drawing adjusts to the new size.


Control the Backlight Brightness

The BL pin powers the backlight LED, and a PWM signal on that pin dims it. A backlight can draw more current than an Arduino pin should supply, so drive it through a small NPN transistor or a logic-level MOSFET instead of connecting it directly. Connect the transistor base through a resistor of about 1 kΩ to pin 6, and let it switch the BL line to ground or to the supply, depending on your module. If your module documentation shows that BL is a low-current logic input, a direct connection is possible.

const int backlightPin = 6;   // PWM pin

void setup() {
  pinMode(backlightPin, OUTPUT);
}

void loop() {
  for (int level = 0; level <= 255; level += 5) {
    analogWrite(backlightPin, level);   // 0 is off, 255 is full brightness
    delay(30);
  }
  for (int level = 255; level >= 0; level -= 5) {
    analogWrite(backlightPin, level);
    delay(30);
  }
}

The analogWrite() function accepts values from 0 to 255, and pin 6 supports PWM on the Uno. The Arduino PWM tutorial explains the function in more detail.


ST7735 SD Card BMP Images

The display can show bitmap (BMP) images that are stored on an SD card, which suits logos, icons, menu backgrounds and small photos. The SD card uses SPI as well, so it shares the clock and the data lines with the display and needs only one extra pin for its own chip select. The SD card SPI tutorial explains the card side in more detail.

Wire the SD Card Module

Many ST7735 modules include a microSD slot with its own pins, and a separate SD module works the same way. The SD card pins connect to the same MOSI, MISO and SCK pins as the display, and the card gets a separate chip select on pin 4.

SD card pinArduino pinDescription
VCC5VPower, for modules with an onboard regulator
GNDGNDCommon ground
MOSID11Shared with the display
MISOD12Used only by the SD card
SCKD13Shared with the display
CSD4Chip select of the SD card

The display keeps its own wiring from the earlier section, with CS on D10, DC on D9 and RES on D8. Each device must have its own chip select pin, and both chip select lines should be HIGH whenever a device is not in use.

Arduino Uno wiring with the ST7735 chip select on D10 and the SD card chip select on D4 sharing MOSI D11, MISO D12 and SCK D13

A bare SD card works at 3.3 V, so use a module with an onboard regulator and level shifters when you power it from a 5 V board.


Prepare the BMP Images

The sketch below reads uncompressed 24-bit BMP files. Prepare the card as follows.

  1. Format the card as FAT32, which suits cards up to 32 GB.
  2. Save each image as an uncompressed 24-bit BMP with a program such as Paint or GIMP. JPEG and PNG files do not work.
  3. Resize each image to 128 by 160 pixels or smaller. The sketch also clips images that are larger than the screen.
  4. Copy the files to the root folder of the card with short names, for example image1.bmp and image2.bmp.
FAT32 SD card root folder with the files image1.bmp and image2.bmp ready for the ST7735 display

A 32-bit BMP or a file with compression does not work, because the sketch checks the bit depth and rejects such files.


BMP Display Code

The sketch below draws two images in turn. The function bmpDraw() reads the BMP header, checks the format, sets the drawing window on the display and sends the pixels row by row. BMP files store pixels in blue, green, red order and usually store the bottom row first, so the function reads the rows in reverse and swaps the color order. The helper functions read16() and read32() read little-endian numbers one byte at a time.

#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <SD.h>

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

#define BUFFPIXEL 20   // Pixels read from the card at once

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

void setup() {
  Serial.begin(9600);

  // Keep both chip select lines HIGH before either device starts
  pinMode(TFT_CS, OUTPUT);
  digitalWrite(TFT_CS, HIGH);
  pinMode(SD_CS, OUTPUT);
  digitalWrite(SD_CS, HIGH);

  tft.initR(INITR_BLACKTAB);
  tft.fillScreen(ST77XX_BLACK);

  if (!SD.begin(SD_CS)) {
    Serial.println(F("SD card initialization failed."));
    while (true);
  }
  Serial.println(F("SD card initialized."));
}

void loop() {
  bmpDraw("image1.bmp", 0, 0);
  delay(2000);
  bmpDraw("image2.bmp", 0, 0);
  delay(2000);
}

void bmpDraw(const char *filename, int16_t x, int16_t y) {
  File bmpFile;
  uint8_t sdbuffer[3 * BUFFPIXEL];
  uint8_t buffidx = sizeof(sdbuffer);
  bool flip = true;   // BMP rows are stored bottom to top

  if ((x >= tft.width()) || (y >= tft.height())) return;

  bmpFile = SD.open(filename);
  if (!bmpFile) {
    Serial.print(F("File not found: "));
    Serial.println(filename);
    return;
  }

  if (read16(bmpFile) != 0x4D42) {          // "BM" signature
    Serial.println(F("Not a BMP file."));
    bmpFile.close();
    return;
  }

  read32(bmpFile);                          // File size
  read32(bmpFile);                          // Reserved
  uint32_t imageOffset = read32(bmpFile);   // Start of the pixel data
  read32(bmpFile);                          // Header size
  int32_t bmpWidth  = read32(bmpFile);
  int32_t bmpHeight = read32(bmpFile);

  // Planes must be 1, depth must be 24 bits, compression must be 0
  if (read16(bmpFile) != 1 || read16(bmpFile) != 24 || read32(bmpFile) != 0) {
    Serial.println(F("Use an uncompressed 24-bit BMP."));
    bmpFile.close();
    return;
  }

  uint32_t rowSize = (bmpWidth * 3 + 3) & ~3;   // Rows are padded to 4 bytes
  if (bmpHeight < 0) {                          // Negative height: top to bottom
    bmpHeight = -bmpHeight;
    flip = false;
  }

  // Clip the image to the screen
  int16_t w = bmpWidth;
  int16_t h = bmpHeight;
  if ((x + w - 1) >= tft.width())  w = tft.width()  - x;
  if ((y + h - 1) >= tft.height()) h = tft.height() - y;

  tft.setAddrWindow(x, y, w, h);   // Position, width and height

  for (int16_t row = 0; row < h; row++) {
    uint32_t pos = imageOffset + (flip ? (bmpHeight - 1 - row) : row) * rowSize;

    if (bmpFile.position() != pos) {    // Jump to the start of the row
      bmpFile.seek(pos);
      buffidx = sizeof(sdbuffer);       // Force a new read
    }

    for (int16_t col = 0; col < w; col++) {
      if (buffidx >= sizeof(sdbuffer)) {
        bmpFile.read(sdbuffer, sizeof(sdbuffer));
        buffidx = 0;
      }
      uint8_t b = sdbuffer[buffidx++];
      uint8_t g = sdbuffer[buffidx++];
      uint8_t r = sdbuffer[buffidx++];
      tft.pushColor(tft.color565(r, g, b));
    }
  }

  bmpFile.close();
}

uint16_t read16(File &f) {
  uint16_t low  = f.read();
  uint16_t high = f.read();
  return (high << 8) | low;
}

uint32_t read32(File &f) {
  uint32_t b0 = f.read();
  uint32_t b1 = f.read();
  uint32_t b2 = f.read();
  uint32_t b3 = f.read();
  return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
}

The two images alternate every two seconds. The setAddrWindow() function of the current Adafruit library takes the position, the width and the height of the window, and older code examples that pass the end coordinates instead produce a shifted image. Drawing pixel by pixel is slow, so a full-screen image takes a moment to appear, which is normal for an Uno.

Animated capture of an ST7735 display switching between two BMP images loaded from an SD card

If an image looks mirrored or stretched, check its size and bit depth first. File names on the FAT file system are not case-sensitive in the SD library, but a short name in lowercase, such as image1.bmp, avoids surprises.


ST7735 Troubleshooting

Most ST7735 problems come from wiring, voltage levels or the initialization tab.

The Screen Stays White or Blank

Check the power, the ground and the backlight connection first. Then check that the CS, DC and RES pins match the definitions in the sketch, because a swapped pin produces a white or blank screen. If the pins are correct, try another initialization tab, as described in the test sketch section.


The Colors Are Wrong or Shifted

Red and blue swapped, inverted colors or a shifted picture with noise at one edge usually point to the wrong initialization tab. Change INITR_BLACKTAB to INITR_GREENTAB or INITR_REDTAB until the picture is correct.


SD card initialization failed

The card must be FAT32, the wiring of the SD chip select must match SD_CS, and the module must have a stable supply. The display and the SD card share the bus, so both chip select pins have to be set HIGH before SD.begin() is called, as the sketch above does. Try a second card if the problem continues, because some cards do not work in SPI mode.


The Image Is Blank or Distorted

The file is probably not a 24-bit uncompressed BMP, or it is larger than the screen. Save it again at 24 bits and resize it to 128 by 160 pixels.


The Display Resets or Flickers

A weak supply is the usual cause. The backlight and the SD card draw current together, so use a stable 5 V source and keep the wires short. A shared ground between all modules is also required.


Conclusion

This tutorial showed how to wire the ST7735 TFT to an Arduino, install the Adafruit libraries and confirm the setup with a test sketch. It also covered text, shapes, colors, rotation and backlight brightness, and how to show BMP images from an SD card.

The important points are the 3.3 V logic level of the display, the correct initialization tab for your panel and a separate chip select pin for the SD card. With these basics you can build dashboards, small game screens and image viewers.




About the Author
Arun Rawat
Arun Rawat
Embedded Systems Engineer · Founder, ControllersTech

Arun is an embedded systems engineer with 10+ years of experience in STM32, ESP32, and AVR microcontrollers. He created ControllersTech to share practical tutorials on embedded software, HAL drivers, RTOS, and hardware design — grounded in real industrial automation experience.

Subscribe
Notify of

0 Comments
Newest
Oldest Most Voted
×

Don’t Miss Future STM32 Tutorials

Join thousands of developers getting free guides, code examples, and updates.