2.4 TFT LCD Shield Arduino Tutorial

Posted on

2.4 TFT LCD Arduino Tutorial – TFT LCD (Thin-Film Transistor Liquid Crystal Display) is an LCD screen made of a set of transistors, where one transistor will control one pixel. Pixels are the smallest point of the LCD which represents a color block. This is a 2.4 ″ TFT Arduino LCD Shield module with a screen resolution format of 320 * 240 pixels. This LCD is capable of displaying RGB color display. Resolution 320 * 240 means that there are 76,800 pixels, which are arranged vertically 320 pixels and horizontally 240 pixels. These pixels are formed by liquid crystal pixels which will change light when given an electric voltage.

This 2.4 TFT LCD is also equipped with an SD Card which is useful for storing or displaying images on the SD Card. Equipped with a touch screen feature, this LCD is increasingly suitable for use as a replacement button interface. Using the Arduino, you can make many projects using this LCD. Example Mini television, Digital clock, Speedometer, Handphone screen, Home control system, Mini game station, Pocket camera, Calculator, GPS location display, Weather display, and more.

The 2.4 TFT LCD in this tutorial is 2.4 ″ TFT LCD which has ID 0x2035. With I2C HC245 as Octal Bus Transceiver, this LCD is able to buffer and transmit data at high speed. Transceiver means that this IC is capable of conducting two-way communication, transmitter (sending) and receiver (receiving). The higher the speed, the more data can be sent. This TFT LCD cannot communicate via SPI, so the SPI pin is available only for SD Card. For pin configuration shown as in the following picture:



  • Pins 5V, 3.3V and Gnd are useful for supplying electrical current to the LCD
  • LCD_RST is an LCD Reset pin
  • LCD_CS is a Chip Select pin
  • LCD_RS is the Register Select pin
  • LCD_WR is the Write Data pin
  • LCD_RD is the Read Data pin
  • LCD_D0 – D8 is a pin that is useful for sending 8-bit data to the TFT LCD in parallel. Pin D0 as LSB and D8 as MSB.
  • SD_SS is pin Select Slave (SPI)
  • SD_DI is a MOSI (SPI) pin
  • SD_DO is MISO (SPI) pin
  • SD_SCK is Clock (SPI) pin



A. Display Font

This next we will test the 2.4 TFT LCD. We will try to display the writing on the LCD screen. There are several steps that we must learn, namely, the coordinate system on the LCD, the library used and the type of font used.

A1. LCD coordinate system


Look at the picture above. The LCD is composed of pixels. each pixel has a location address. when we want to activate one pixel, we have to activate the pixel by including the location coordinates of the pixel. Writing coordinates starts from the letter “x” then “y”. Examples of pixels (x, y) are pixels (9.8). In the picture above I give an example of turning on 3 pixels, namely at coordinates (9.8), (36, 3) and (46, 22).

A2. Library

In this step we use the library to make the program easier. There are two libraries that we use. The first library that contains LCD and Oled functions provided by Adafruit Indusrty. The library name is Adrafruit GFX. The second is a library that contains LCD and OLED hardware configurations such as ID, screen resolution, etc. The Library name is MCUFRIEND. For the Adafruit GFX library, please install it through the Arduino IDE library manager. Or please visit this website. Download the MCUFRIEND library below:


Then attach the 2.4 TFT LCD module to Arduino and upload the following program:


#include <Adafruit_GFX.h>    // Library that contains LCD and OLED functions
#include <MCUFRIEND_kbv.h>   // Library that contains the hardware configuration of the LCD
MCUFRIEND_kbv tft;

#include <FreeDefaultFonts.h> //Using Standart Font

//Color definition RGB565
#define BLACK    0x0000 
#define RED      0xF800 
#define GREEN    0x07E0 
#define WHITE    0xFFFF 
#define GREY     0x8410 
#define BLUE     0x001F
#define CYAN     0x07FF
#define MAGENTA  0xF81F
#define YELLOW   0xFFE0 

void setup(void)
    uint16_t ID = tft.readID(); 
    if (ID == 0xD3) ID = 0x9481;
    tft.setRotation(0);           //0 for potrait and 1 for landscape
    showmsgXY(80, 40, 1, NULL, "Selamat Datang");  //show "Selamat Datang" 
    showmsgXY(30, 80, 2, NULL, "Hambo Elektronik");//show "Hambo Elektronik" 

void loop(void)

void showmsgXY(int x, int y, int sz, const GFXfont *f, const char *msg) //fungsi tampilan
    tft.setFont(f);          // Because the font is the default, NULL is written
    tft.setCursor(x, y);     // set the cursor or the initial coordinates of the writing
    tft.setTextColor(GREEN); // green color for text
    tft.setTextSize(sz);     // size of font 1 dan 2px
    tft.print(msg);          // show on LCD

You will see the results of the 2.4 TFT LCD connected to Arduino as follows:

Read other articles  How To Program ATTiny13 / ATTiny13A using Arduino

2.4 tft lcd arduino

A3. Font Type

Library Adafruit has provided 48 fonts divided into 3 font categories ie, Serif, Sans and Mono. The fonts are as follows:


how to use it? use the #include <font.h> command. look the following program


#include <Adafruit_GFX.h>   // Library that contains LCD and OLED functions
#include <MCUFRIEND_kbv.h>  // Library that contains the hardware configuration of the LCD
MCUFRIEND_kbv tft;

#include <FreeDefaultFonts.h>
#include <Fonts/FreeMono12pt7b.h> 
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeSerif12pt7b.h>

//color in RGB565
#define BLACK    0x0000 
#define RED      0xF800 
#define GREEN    0x07E0 
#define WHITE    0xFFFF 
#define GREY     0x8410 
#define BLUE     0x001F
#define CYAN     0x07FF
#define MAGENTA  0xF81F
#define YELLOW   0xFFE0 

void setup(void)
    uint16_t ID = tft.readID();   //read ID Hardware 
    if (ID == 0xD3) ID = 0x9481;
    tft.setRotation(0);           //0 for potrait dan 1 for landscape

    showmsgXY(10, 10, 2, NULL, "Hambo Elektronik");  
    showmsgXY(10, 50, 1, &FreeMono12pt7b, "Hambo Elektronik");
    showmsgXY(10, 80, 1, &FreeSans12pt7b, "Hambo Elektronik"); 
    showmsgXY(10, 110, 1, &FreeSerif12pt7b, "Hambo Elektronik"); 

void loop(void)

void showmsgXY(int x, int y, int sz, const GFXfont *f, const char *msg) 
    tft.setCursor(x, y);

Then it looks like this:

tft arduino tutorial


B. Display Bitmap / Image

B1. Display Image from Arduino Memory

Display Image from Arduino memory means to read image from SRAM ATmega328. Image must be convert into an array first. Then we program the array into Arduino. This array can be RGB565 or Black and White image data. I use Image converter 565 software for converting image to array. Download image converter 565 software below.

DOWNLOAD Image Converter 565 

Then Run the Application. Follow this method:

a. Click > Open Image. In this example I want to display a picture of Doraemon.

doraemontft bitmap arduino

b. After entering the image, then Adjust Resolution as shown below:

tft arduino tutorial

c. Click Save with the extension .c file and the Arduino Board (AVR) target.

d. After saving, you will get the doraemon.c file with entries like this:

2.4 tft arduino tutorial ilibrary

e. Open the Arduino IDE, then use the following program:


#include "MCUFRIEND_kbv.h"
MCUFRIEND_kbv tft;

#define LOWFLASH (defined(__AVR_ATmega328P__) && defined(MCUFRIEND_KBV_H_))

#include "bitmap.h"    

//color definition RGB565
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
#define GREY    0x8410
#define ORANGE  0xE880

void setup()
  uint16_t ID = tft.readID(); D

  int x = 5, y, w = 240, h = 320; 
  const int SZ = w * h ;
  uint8_t sram[SZ];

  y = 0; 
  tft.drawRGBBitmap(x, y, doraemon, 100, 82); 

void loop(void)


f. Then create a new tab and write it with the name bitmap.h. Look at the picture below:

2.4 tft arduino tutorial library 2.4 tft arduino tutorial library

g. copy all the data in the doraemon.c file, then paste it into the bitmap.h. Then replace the word unsigned short to uint16_t. Seen in the following picture.

2.4 tft arduino tutorial library

h. Click Upload, then the image will appear as shown in 2.4 TFT LCD below:

Read other articles  Arduino Nano Port Not Detected Chip CH340

2.4 tft arduino tutorial library2.4 tft arduino tutorial library


B2. Display Image from memory card

Reading images from memory card is better because it doesn’t use SRAM. So, the image displayed can be resolution of 320 * 240 pixels. In this tutorial, an example will display an image with the image format is .bmp. Follow the steps below:

a. In this tutorial I use the image “doraemon.png”, and I convert it to “doraemon.bmp” using the application “Paint” which is the default Windows application. This image has a resolution of 290 × 238 px.

tft arduino tutorial library

b. Place the image into the memory card and insert the memory card on the 2.4 TFT LCD.

c. Use the following program:


#include <SPI.h>
#include <SD.h>
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

#if defined(ESP32)
#define SD_CS     5
#define SD_CS     10

#define NAMEMATCH "doraemon"   // doraemon.bmp
#define PALETTEDEPTH   0
#define BUFFPIXEL      20

char namaBuffer[32] = "/";   // character "/" means root
//char namaBuffer[32] = "/namaFolder/";  // if the image is in a folder then write "/ Folder name / doraemon.bmp
int bmpWidth, bmpHeight;    // width and height of the image in pixels
uint8_t bmpDepth;
uint32_t bmpImageoffset;    // start image data on file
uint32_t rowSize;
uint8_t sdbuffer[3 * BUFFPIXEL];    // pixels in buffer (R + G + B per pixel)
uint16_t lcdbuffer[(1 << PALETTEDEPTH) + BUFFPIXEL], *palette = NULL;
uint8_t bitmask, bitshift;
boolean flip = true;       // The image file array will then be saved from the bottom row to the top
// If the value is "false" then the display will start from the bottom up of the image
// If the value is "true" then the display will start from top to bottom
int w, h, row, col, lcdbufsiz = (1 << PALETTEDEPTH) + BUFFPIXEL, buffidx;
uint32_t pos;
boolean is565 = false;
uint16_t bmpID;
uint16_t n;
uint8_t ret;
int pjgPath;
char *nm = namaBuffer + pjgPath;
uint32_t start;

File root;
File f;

void setup()
  uint16_t ID;
  ID = tft.readID();
  tft.setRotation(1);     // landscape, if "0" will be portrait
  tft.fillScreen(0x001F); // set the background color before loading the image

  // check if there is a memory card
  bool ada = SD.begin(SD_CS);
  if (!ada) {                                   // if it's not there
    Serial.print(F("SD tidak terdeteksi"));     // show in the serial monitorr
    while (1);

  root =;
  pjgPath = strlen(namaBuffer); // calculate the length of a string from the name Buffer

void loop()
  f = root.openNextFile();
  if (f != NULL) {
#ifdef USE_SDFAT
    f.getName(nm, 32 - pjgPath);
    strcpy(nm, (char *);
    if (strstr(nm, ".bmp") != NULL && strstr(nm, NAMEMATCH) != NULL) {
      Serial.print(F(" - "));
      start = millis();
      ret = showBMP(namaBuffer, 5, 5);
  else root.rewindDirectory();


uint16_t read16(File& f) {
  uint16_t result;*)&result, sizeof(result));
  return result;

uint32_t read32(File& f) {
  uint32_t result;*)&result, sizeof(result));
  return result;

uint8_t showBMP(char *nm, int x, int y)
  File bmpFile;
  if ((x >= tft.width()) || (y >= tft.height()))
    return 1;               // matikan layar

  bmpFile =;      // BMP file parsing
  bmpID = read16(bmpFile);    // BMP signature
  (void) read32(bmpFile);     // Read and ignore file size
  (void) read32(bmpFile);     // Read and ignore author bytes
  bmpImageoffset = read32(bmpFile);       // Starting from image data
  (void) read32(bmpFile);     // Read & ignore the DIB header size
  bmpWidth = read32(bmpFile);
  bmpHeight = read32(bmpFile);
  n = read16(bmpFile);
  bmpDepth = read16(bmpFile); // bits per pixel
  pos = read32(bmpFile);      // format
  if (bmpID != 0x4D42) ret = 2; //Bad ID
  else if (n != 1) ret = 3;
  else if (pos != 0 && pos != 3) ret = 4; // format: 0 = uncompressed, 3 = 565
  else if (bmpDepth < 16 && bmpDepth > PALETTEDEPTH) ret = 5; // palette
  else {
    bool first = true;
    is565 = (pos == 3);               // Already in 16-bit format?
    // The BMP line is filled (if necessary) up to a 4-byte limit
    rowSize = (bmpWidth * bmpDepth / 8 + 3) & ~3;
    if (bmpHeight < 0) {              // If negative, the image is in the top-down order.
      bmpHeight = -bmpHeight;
      flip = false;

    w = bmpWidth;
    h = bmpHeight;
    if ((x + w) >= tft.width())      // Crop the area to be loaded
      w = tft.width() - x;
    if ((y + h) >= tft.height())
      h = tft.height() - y;

    if (bmpDepth <= PALETTEDEPTH) {  // This mode has a separate palette; // the palette is always @ 54
      bitmask = 0xFF;
      if (bmpDepth < 8)
        bitmask >>= bmpDepth;
      bitshift = 8 - bmpDepth;
      n = 1 << bmpDepth;
      lcdbufsiz -= n;
      palette = lcdbuffer + lcdbufsiz;
      for (col = 0; col < n; col++) {
        pos = read32(bmpFile);    // palette map to 5-6-5
        palette[col] = ((pos & 0x0000F8) >> 3) | ((pos & 0x00FC00) >> 5) | ((pos & 0xF80000) >> 8);

    // Set the TFT address window to cut the image boundary
    tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
    for (row = 0; row < h; row++) { // For each scanning line ...
      uint8_t r, g, b, *sdptr;
      int lcdidx, lcdleft;
      if (flip)
        pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
        pos = bmpImageoffset + row * rowSize;
      if (bmpFile.position() != pos) {;
        buffidx = sizeof(sdbuffer); // Forced to reload the buffer

      for (col = 0; col < w; ) {  // pixels in rows
        lcdleft = w - col;
        if (lcdleft > lcdbufsiz) lcdleft = lcdbufsiz;
        for (lcdidx = 0; lcdidx < lcdleft; lcdidx++) { // buffer at once
          uint16_t color;
          // Time to read more pixel data?
          if (buffidx >= sizeof(sdbuffer)) { // Indeed
  , sizeof(sdbuffer));
            buffidx = 0; // Set index for starting
            r = 0;

          switch (bmpDepth) {         // Pixel conversion from BMP to TFT format
            case 1:
            case 4:
            case 8:
              if (r == 0)
                b = sdbuffer[buffidx++], r = 8;
              color = palette[(b >> bitshift) & bitmask];
              r -= bmpDepth;
              b <<= bmpDepth;
            case 24:
              b = sdbuffer[buffidx++];
              g = sdbuffer[buffidx++];
              r = sdbuffer[buffidx++];
              color = tft.color565(r, g, b);
            case 16:
              b = sdbuffer[buffidx++];
              r = sdbuffer[buffidx++];
              if (is565)
                color = (r << 8) | (b);
                color = (r << 9) | ((b & 0xE0) << 1) | (b & 0x1F);
          lcdbuffer[lcdidx] = color;
        tft.pushColors(lcdbuffer, lcdidx, first);
        first = false;
        col += lcdidx;
      }           // ends the column
    }               // ends the rows
    tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1); // restore full screen
    ret = 0;
  return (ret);

d. Upload the program above to Arduino.

Read other articles  How To Use Nokia LCD 5110 With Arduino

e. The results is like this:



C. Arduino TFT Touch Screen Library

Now I have provided a program which is used for touch screen interactions. I have prepared the program below. This program is for LCD 2.4  TFT LCD with ID = 0x2035. If you use TFT with a different ID, please refer to this link to see the settings that match the TFT.  Please download arduino tft touch screen library below.

Download TouchScreen Library

#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#include <TouchScreen.h>
#define MINPRESSURE 10
#define MAXPRESSURE 1000

const int XP=7,XM=A1,YP=A2,YM=6;
const int TS_LEFT = 130, TS_RT = 910, TS_TOP = 100, TS_BOT = 905;

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

Adafruit_GFX_Button blueBtn, redBtn, greenBtn, yellowBtn;

int piksel_x, piksel_y;
bool Touch_getXY(void)
TSPoint p = ts.getPoint();
pinMode(YP, OUTPUT);
pinMode(XM, OUTPUT);
digitalWrite(YP, HIGH);
digitalWrite(XM, HIGH);
bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
if (pressed) {
piksel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width());
piksel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
return pressed;

// color definition uses the RGB565 format
#define BLACK 0x0000
#define BLUE 0x001F
#define NAVY_BLUE 0x16DD
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF

void setup(void)
uint16_t ID = tft.readID();
blueBtn.initButton(&tft, 60, 130, 80, 40, WHITE, NAVY_BLUE, BLACK, "1", 2);
redBtn.initButton (&tft, 180, 130, 80, 40, WHITE, RED, BLACK, "2", 2);
yellowBtn.initButton (&tft, 60, 200, 80, 40, WHITE, YELLOW, BLACK, "3", 2);
greenBtn.initButton (&tft, 180, 200, 80, 40, WHITE, GREEN, BLACK, "4", 2);
tft.fillRect(00, 0, 240, 80, WHITE);

void loop(void)
bool detect = Touch_getXY(); && blueBtn.contains(piksel_x, piksel_y)); (detect && redBtn.contains(piksel_x, piksel_y)); (detect && yellowBtn.contains(piksel_x, piksel_y)); (detect && greenBtn.contains(piksel_x, piksel_y));

if (blueBtn.justReleased())
if (redBtn.justReleased())
if (yellowBtn.justReleased())
if (greenBtn.justReleased())

if (blueBtn.justPressed()) {
tft.fillRect(00, 0, 240, 80, NAVY_BLUE);
if (redBtn.justPressed()) {
tft.fillRect(00, 0, 240, 80, RED);
if (yellowBtn.justPressed()) {
tft.fillRect(00, 0, 240, 80, YELLOW);
if (greenBtn.justPressed()) {
tft.fillRect(00, 0, 240, 80, GREEN);


One thought on “2.4 TFT LCD Shield Arduino Tutorial

Leave a Reply

Your email address will not be published. Required fields are marked *