Tutorial: How to use 2.4 TFT Display | SPFD5408 | ILI9341

Introduction

Display modules is commonly use to show text, shapes, images, or animation to convey necessary information to the user. In this tutorial, we will learn to use the 2.4 inch TFT display.

Video Demonstration

Call To Action

If you have any question, please do not hesitate to write it in the comment box and I am happy to answer it.

If you find this tutorial as helpful, please consider supporting me by Subscribing TechToTinker Youtube channel. Click this to subscribe.

Thank you and keep tinkering.

Source Code

Example 1: Displaying text:

 1// Modified for SPFD5408 Library by Joao Lopes
 2
 3#include "SPFD5408_Adafruit_GFX.h"    // Core graphics library
 4#include "SPFD5408_Adafruit_TFTLCD.h" // Hardware-specific library
 5#include "SPFD5408_TouchScreen.h"
 6
 7// Pin assignments for the TFT touch screen
 8#define YP    A1
 9#define XM    A2
10#define YM    7
11#define XP    6
12
13// Calibrated values for the TFT touch screen  
14#define TS_MINX   178
15#define TS_MINY   75
16#define TS_MAXX   931
17#define TS_MAXY   895
18
19// Instantiate the ts object
20TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
21
22#define LCD_RD    A0
23#define LCD_WR    A1
24#define LCD_CD    A2
25#define LCD_CS    A3
26#define LCD_RESET A4
27
28// Instantiate the tft object
29Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
30
31// Assign human-readable names to some common 16-bit color values:
32#define	BLACK   0x0000
33#define	BLUE    0x001F
34#define	RED     0xF800
35#define	GREEN   0x07E0
36#define CYAN    0x07FF
37#define MAGENTA 0xF81F
38#define YELLOW  0xFFE0
39#define WHITE   0xFFFF
40
41void setup(void) {
42  Serial.begin(9600);
43  Serial.println(F("Paint!"));
44  
45  tft.reset();
46  tft.begin(0x9341);      // SPFD5408 compatible
47  tft.setRotation(2);     // This settings works for me with correct orientation
48                          // tft.setRotation(2);
49  tft.fillScreen(BLACK);  //Set Background Color with BLACK
50
51  tft.setTextColor(WHITE);
52  tft.setTextSize(1);
53  tft.setCursor(10, 10);
54  tft.println("Hello from TechToTinker");
55
56  tft.setTextColor(RED);
57  tft.setTextSize(2);
58  tft.setCursor(10, 30);
59  tft.println("2.4 TFT Display");
60}
61
62void loop() {}

Example 2: Displaying Shapes:

 1// Modified for SPFD5408 Library by Joao Lopes
 2
 3#include "SPFD5408_Adafruit_GFX.h"    // Core graphics library
 4#include "SPFD5408_Adafruit_TFTLCD.h" // Hardware-specific library
 5#include "SPFD5408_TouchScreen.h"
 6
 7// Pin assignments for the TFT touch screen
 8#define YP    A1
 9#define XM    A2
10#define YM    7
11#define XP    6
12
13// Calibrated values for the TFT touch screen  
14#define TS_MINX   178
15#define TS_MINY   75
16#define TS_MAXX   931
17#define TS_MAXY   895
18
19// Instantiate the ts object
20TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
21
22#define LCD_RD    A0
23#define LCD_WR    A1
24#define LCD_CD    A2
25#define LCD_CS    A3
26#define LCD_RESET A4
27
28// Instantiate the tft object
29Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
30
31// Assign human-readable names to some common 16-bit color values:
32#define	BLACK   0x0000
33#define	BLUE    0x001F
34#define	RED     0xF800
35#define	GREEN   0x07E0
36#define CYAN    0x07FF
37#define MAGENTA 0xF81F
38#define YELLOW  0xFFE0
39#define WHITE   0xFFFF
40
41void setup(void) {
42  Serial.begin(9600);
43  Serial.println(F("Paint!"));
44  
45  tft.reset();
46  tft.begin(0x9341);      // SPFD5408 compatible
47  tft.setRotation(2);     // This settings works for me with correct orientation
48                          // tft.setRotation(2);
49  tft.fillScreen(BLACK);  //Set Background Color with BLACK
50
51  tft.setTextColor(WHITE);
52  tft.setTextSize(1);
53  tft.setCursor(10, 10);
54  tft.println("Hello from TechToTinker");
55
56  tft.setTextColor(RED);
57  tft.setTextSize(2);
58  tft.setCursor(10, 30);
59  tft.println("2.4 TFT Display");
60
61  tft.drawCircle(120, 160, 20, YELLOW);
62  tft.fillCircle(120, 160, 10, GREEN);
63  tft.drawTriangle(10,70,80,70,60,90,CYAN);
64}
65
66void loop() {}

Example 3: Using Touch Screen:

 1// Modified for SPFD5408 Library by Joao Lopes  
 2 #include <SPFD5408_Adafruit_GFX.h>  // Core graphics library  
 3 #include <SPFD5408_Adafruit_TFTLCD.h> // Hardware-specific library  
 4 #include <SPFD5408_TouchScreen.h>  
 5 // Pin assignments for the TFT touch screen  
 6 #define YP  A1  
 7 #define XM  A2  
 8 #define YM  7  
 9 #define XP  6  
10 // Calibrated values for the TFT touch screen   
11 #define TS_MINX  178  
12 #define TS_MINY  75  
13 #define TS_MAXX  931  
14 #define TS_MAXY  895  
15 // Instantiate the ts object  
16 TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);  
17 #define LCD_RD  A0  
18 #define LCD_WR  A1  
19 #define LCD_CD  A2  
20 #define LCD_CS  A3  
21 #define LCD_RESET A4  
22 // Instantiate the tft object  
23 Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);  
24 // Assign human-readable names to some common 16-bit color values:  
25 #define BLACK  0x0000  
26 #define BLUE  0x001F  
27 #define RED   0xF800  
28 #define GREEN  0x07E0  
29 #define CYAN  0x07FF  
30 #define MAGENTA 0xF81F  
31 #define YELLOW 0xFFE0  
32 #define WHITE  0xFFFF  
33 #define BOXSIZE   40  
34 #define PENRADIUS  3  
35 #define MINPRESSURE 10  
36 #define MAXPRESSURE 1000  
37 #define LED_PIN   A5  
38 int touch = 0;  
39 void setup() {  
40  pinMode(LED_PIN, OUTPUT);  
41  digitalWrite(LED_PIN, LOW);  
42  Serial.begin(9600);  
43  tft.reset();  
44  tft.begin(0x9341);  
45  tft.setRotation(2); // This settings works for me with correct orientation  
46            // tft.setRotation(2);  
47  tft.setTextColor(WHITE);  
48  tft.setTextSize(2);  
49  tft.fillScreen(BLACK);  
50  tft.fillRect(0, 0, 120, 120, GREEN);  
51  tft.fillRect(120, 0, 120, 120, RED);  
52  tft.setCursor(15, 45);  
53  tft.println("LED ON");  
54  tft.setCursor(128, 45);  
55  tft.println("LED OFF");  
56  tft.setTextColor(WHITE, BLACK);  
57  tft.setTextSize(8);  
58 }  
59 void loop() {  
60  // Get the touch points  
61  TSPoint p = ts.getPoint();  
62  // Restore the mode  
63  pinMode(XM, OUTPUT);  
64  pinMode(YP, OUTPUT);  
65  if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {  
66   p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());  
67   p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());  
68   // Touch area for box 1  
69   if (p.x > 0 && p.x < 120) {  
70    if (p.y > 0 && p.y < 120) {  
71     touch = 1;  
72    }  
73   }  
74   // Touch area for box 2  
75   if (p.x > 120 && p.x < 240) {  
76    if (p.y > 0 && p.y < 120) {  
77     touch = 2;  
78    }  
79   }  
80  }  
81  // Process the touch in box 1  
82  if (touch == 1) {  
83   digitalWrite(LED_PIN, HIGH);  
84   tft.setCursor(100,200);  
85   tft.print("1");  
86   touch = 0;  
87   delay(100);  
88  }  
89  // Process the touch in box 2  
90  if (touch == 2) {  
91   digitalWrite(LED_PIN, LOW);  
92   tft.setCursor(100,200);  
93   tft.print("0");  
94   touch = 0;  
95   delay(100);  
96  }  
97 }  

Example 4: Accessing the microSD card:

 1// Load the libraries for microSD  
 2 #include <SPI.h>  
 3 #include <SD.h>  
 4 // Load the libraries for the TFT display  
 5 #include <SPFD5408_Adafruit_GFX.h>  // Core graphics library  
 6 #include <SPFD5408_Adafruit_TFTLCD.h> // Hardware-specific library  
 7 #include <SPFD5408_TouchScreen.h>  
 8 #if defined(__SAM3X8E__)  
 9   #undef __FlashStringHelper::F(string_literal)  
10   #define F(string_literal) string_literal  
11 #endif  
12 // Pin assignments for the touch screen  
13 #define YP A1  
14 #define XM A2  
15 #define YM 7  
16 #define XP 6  
17 // Calibrate values    
18 #define TS_MINX 178  
19 #define TS_MINY 75  
20 #define TS_MAXX 931  
21 #define TS_MAXY 895  
22 // For better pressure precision, we need to know the resistance  
23 // between X+ and X- Use any multimeter to read it  
24 // For the one we're using, its 300 ohms across the X plate  
25 TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);  
26 #define LCD_RD  A0  
27 #define LCD_WR  A1  
28 #define LCD_CD  A2  
29 #define LCD_CS  A3  
30 #define LCD_RESET A4  
31 // Assign human-readable names to some common 16-bit color values:  
32 #define  BLACK  0x0000  
33 #define  BLUE  0x001F  
34 #define  RED   0xF800  
35 #define  GREEN  0x07E0  
36 #define CYAN  0x07FF  
37 #define MAGENTA 0xF81F  
38 #define YELLOW 0xFFE0  
39 #define WHITE  0xFFFF  
40 Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);  
41 File myFile;  
42 void setup(void) {  
43  tft.reset();  
44  tft.begin(0x9341); // SDFP5408  
45  tft.setRotation(2); // This settings works for me with correct orientation  
46            // tft.setRotation(2);  
47  tft.fillScreen(BLACK); //Set Background Color with BLACK  
48  tft.setTextColor(WHITE);  
49  tft.setTextSize(2);  
50  tft.println("MicroSD Read Write");  
51  tft.println("");  
52  tft.println("Initializing SD card...");  
53  if (!SD.begin(10)) {  
54   tft.println("initialization failed!");  
55   while (1);  
56  }  
57  tft.println("initialization done.");  
58  // open the file. note that only one file can be open at a time,  
59  // so you have to close this one before opening another.  
60  myFile = SD.open("test.txt", FILE_WRITE);  
61  // if the file opened okay, write to it:  
62  if (myFile) {  
63   tft.println("Writing to test.txt...");  
64   myFile.println("testing 1, 2, 3.");  
65   // close the file:  
66   myFile.close();  
67   tft.println("Done.");  
68  } else {  
69   // if the file didn't open, print an error:  
70   tft.println("error opening test.txt");  
71  }  
72  // re-open the file for reading:  
73  myFile = SD.open("test.txt");  
74  if (myFile) {  
75   tft.println("test.txt:");  
76   // read from the file until there's nothing else in it:  
77   while (myFile.available()) {  
78    tft.write(myFile.read());  
79   }  
80   // close the file:  
81   myFile.close();  
82  } else {  
83   // if the file didn't open, print an error:  
84   tft.println("error opening test.txt");  
85  }  
86  tft.println("");  
87  tft.println("Done");  
88 }  
89 void loop()  
90 {  
91 }  

Example 5: Displaying BMP Pictures:

  1// Modified for SPFD5408 Library by Joao Lopes  
  2 #include <SPFD5408_Adafruit_GFX.h>  // Core graphics library  
  3 #include <SPFD5408_Adafruit_TFTLCD.h> // Hardware-specific library  
  4 #include <SPFD5408_TouchScreen.h>  
  5 #include <SPI.h>  
  6 #include <SD.h>  
  7 #define LCD_RD  A0  
  8 #define LCD_WR  A1  
  9 #define LCD_CD  A2  
 10 #define LCD_CS  A3  
 11 #define LCD_RESET A4  
 12 // Instantiate the tft object  
 13 Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);  
 14 #define SD_CS 10  
 15 void setup()  
 16 {  
 17  Serial.begin(9600);  
 18  tft.reset();  
 19  tft.begin(0x9341);  
 20  tft.setRotation(3);  
 21  progmemPrint(PSTR("Initializing SD card..."));  
 22  if (!SD.begin(SD_CS)) {  
 23   progmemPrintln(PSTR("failed!"));  
 24   return;  
 25  }  
 26  progmemPrintln(PSTR("OK!"));  
 27 }  
 28 void loop() {  
 29  bmpDraw("Youtube.bmp", 0, 0);  
 30  delay(4000);  
 31  bmpDraw("Logo.bmp", 0, 0);  
 32  delay(4000);  
 33  bmpDraw("Subs.bmp", 0, 0);  
 34  delay(4000);   
 35  bmpDraw("TTT.bmp", 0, 0);  
 36  delay(4000);  
 37  bmpDraw("CLSS.bmp", 0, 0);  
 38  delay(4000);   
 39 }  
 40 // This function opens a Windows Bitmap (BMP) file and  
 41 // displays it at the given coordinates. It's sped up  
 42 // by reading many pixels worth of data at a time  
 43 // (rather than pixel by pixel). Increasing the buffer  
 44 // size takes more of the Arduino's precious RAM but  
 45 // makes loading a little faster. 20 pixels seems a  
 46 // good balance.  
 47 #define BUFFPIXEL 20  
 48 void bmpDraw(char *filename, int x, int y) {  
 49  File   bmpFile;  
 50  int   bmpWidth, bmpHeight;  // W+H in pixels  
 51  uint8_t bmpDepth;       // Bit depth (currently must be 24)  
 52  uint32_t bmpImageoffset;    // Start of image data in file  
 53  uint32_t rowSize;        // Not always = bmpWidth; may have padding  
 54  uint8_t sdbuffer[3*BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)  
 55  uint16_t lcdbuffer[BUFFPIXEL]; // pixel out buffer (16-bit per pixel)  
 56  uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer  
 57  boolean goodBmp = false;    // Set to true on valid header parse  
 58  boolean flip  = true;    // BMP is stored bottom-to-top  
 59  int   w, h, row, col;  
 60  uint8_t r, g, b;  
 61  uint32_t pos = 0, startTime = millis();  
 62  uint8_t lcdidx = 0;  
 63  boolean first = true;  
 64  if((x >= tft.width()) || (y >= tft.height())) return;  
 65  Serial.println();  
 66  progmemPrint(PSTR("Loading image '"));  
 67  Serial.print(filename);  
 68  Serial.println(''');  
 69  // Open requested file on SD card  
 70  if ((bmpFile = SD.open(filename)) == NULL) {  
 71   progmemPrintln(PSTR("File not found"));  
 72   return;  
 73  }  
 74  // Parse BMP header  
 75  if(read16(bmpFile) == 0x4D42) { // BMP signature  
 76   progmemPrint(PSTR("File size: ")); Serial.println(read32(bmpFile));  
 77   (void)read32(bmpFile); // Read & ignore creator bytes  
 78   bmpImageoffset = read32(bmpFile); // Start of image data  
 79   progmemPrint(PSTR("Image Offset: ")); Serial.println(bmpImageoffset, DEC);  
 80   // Read DIB header  
 81   progmemPrint(PSTR("Header size: ")); Serial.println(read32(bmpFile));  
 82   bmpWidth = read32(bmpFile);  
 83   bmpHeight = read32(bmpFile);  
 84   if(read16(bmpFile) == 1) { // # planes -- must be '1'  
 85    bmpDepth = read16(bmpFile); // bits per pixel  
 86    progmemPrint(PSTR("Bit Depth: ")); Serial.println(bmpDepth);  
 87    if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed  
 88     goodBmp = true; // Supported BMP format -- proceed!  
 89     progmemPrint(PSTR("Image size: "));  
 90     Serial.print(bmpWidth);  
 91     Serial.print('x');  
 92     Serial.println(bmpHeight);  
 93     // BMP rows are padded (if needed) to 4-byte boundary  
 94     rowSize = (bmpWidth * 3 + 3) & ~3;  
 95     // If bmpHeight is negative, image is in top-down order.  
 96     // This is not canon but has been observed in the wild.  
 97     if(bmpHeight < 0) {  
 98      bmpHeight = -bmpHeight;  
 99      flip   = false;  
100     }  
101     // Crop area to be loaded  
102     w = bmpWidth;  
103     h = bmpHeight;  
104     if((x+w-1) >= tft.width()) w = tft.width() - x;  
105     if((y+h-1) >= tft.height()) h = tft.height() - y;  
106     // Set TFT address window to clipped image bounds  
107     tft.setAddrWindow(x, y, x+w-1, y+h-1);  
108     for (row=0; row<h; row++) { // For each scanline...  
109      // Seek to start of scan line. It might seem labor-  
110      // intensive to be doing this on every line, but this  
111      // method covers a lot of gritty details like cropping  
112      // and scanline padding. Also, the seek only takes  
113      // place if the file position actually needs to change  
114      // (avoids a lot of cluster math in SD library).  
115      if(flip) // Bitmap is stored bottom-to-top order (normal BMP)  
116       pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;  
117      else   // Bitmap is stored top-to-bottom  
118       pos = bmpImageoffset + row * rowSize;  
119      if(bmpFile.position() != pos) { // Need seek?  
120       bmpFile.seek(pos);  
121       buffidx = sizeof(sdbuffer); // Force buffer reload  
122      }  
123      for (col=0; col<w; col++) { // For each column...  
124       // Time to read more pixel data?  
125       if (buffidx >= sizeof(sdbuffer)) { // Indeed  
126        // Push LCD buffer to the display first  
127        if(lcdidx > 0) {  
128         tft.pushColors(lcdbuffer, lcdidx, first);  
129         lcdidx = 0;  
130         first = false;  
131        }  
132        bmpFile.read(sdbuffer, sizeof(sdbuffer));  
133        buffidx = 0; // Set index to beginning  
134       }  
135       // Convert pixel from BMP to TFT format  
136       b = sdbuffer[buffidx++];  
137       g = sdbuffer[buffidx++];  
138       r = sdbuffer[buffidx++];  
139       lcdbuffer[lcdidx++] = tft.color565(r,g,b);  
140      } // end pixel  
141     } // end scanline  
142     // Write any remaining data to LCD  
143     if(lcdidx > 0) {  
144      tft.pushColors(lcdbuffer, lcdidx, first);  
145     }   
146     progmemPrint(PSTR("Loaded in "));  
147     Serial.print(millis() - startTime);  
148     Serial.println(" ms");  
149    } // end goodBmp  
150   }  
151  }  
152  bmpFile.close();  
153  if(!goodBmp) progmemPrintln(PSTR("BMP format not recognized."));  
154 }  
155 // These read 16- and 32-bit types from the SD card file.  
156 // BMP data is stored little-endian, Arduino is little-endian too.  
157 // May need to reverse subscript order if porting elsewhere.  
158 uint16_t read16(File f) {  
159  uint16_t result;  
160  ((uint8_t *)&result)[0] = f.read(); // LSB  
161  ((uint8_t *)&result)[1] = f.read(); // MSB  
162  return result;  
163 }  
164 uint32_t read32(File f) {  
165  uint32_t result;  
166  ((uint8_t *)&result)[0] = f.read(); // LSB  
167  ((uint8_t *)&result)[1] = f.read();  
168  ((uint8_t *)&result)[2] = f.read();  
169  ((uint8_t *)&result)[3] = f.read(); // MSB  
170  return result;  
171 }  
172 // Copy string from flash to serial port  
173 // Source string MUST be inside a PSTR() declaration!  
174 void progmemPrint(const char *str) {  
175  char c;  
176  while(c = pgm_read_byte(str++)) Serial.print(c);  
177 }  
178 // Same as above, with trailing newline  
179 void progmemPrintln(const char *str) {  
180  progmemPrint(str);  
181  Serial.println();  
182 }  

References And Credits





No comments yet!

GitHub-flavored Markdown & a sane subset of HTML is supported.