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!