จากบทความก่อนหน้านี้ที่ได้ใช้จอแสดงผลขนาด 3.5″ สำหรับบอร์ด Raspberry Pi มาใช้งานกับ ESP32 ไปแล้ว ทางทีมงานเรายังมี Arduino 2.4″ TFT LCD&Touch Shield ที่ใช้กับ Arduino Uno และ Arduino Mega (ดังภาพที่ 1) และต้องการใช้งานกับไมโครคอนโทรลเลอร์ STM32F401RET6 ด้วยบอร์ด NUCLEO-F401RE และ STM32F401CC (ภาพที่ 2) ซึ่งเป็น Cortex-M4 ที่มีหน่วยความจำ 96KB และ 64KB ตามลำดับ ส่วนหน่วยความจำ ROM นั้นเป็น 512KB และ 128KB พร้อมทั้งทำการเชื่อมต่อสวิตช์จำนวน 8 ตัวเข้ากับขาของไมโครคอนโทรลเลอร์ โดยในบทความนี้ใช้บอร์ด ET-TEST 10P/INP (ภาพที่ 3) เพื่อใช้แทนปุ่มซ้าย, บน, ล่าง,ขวา, m1,m2, A และ B ตามลำดับ
Arduino 2.4″ TFT LCD Shield Touch Screen
คุณสมบัติ
คุณสมบัติของโมดูลแสดงผลมีดังนี้
- ความละเอียดในการแสดงผล 320×240 จุดสี
- แสดงสีแบบ 16 บิต หรือ 65,535 สี
- เชื่อมต่อแบบ 8 บิตโดยรับข้อมูลจากไมโครคอนโทรลเลอร์ผ่านขา D0-D1
- มีบัสควบคุมสั่งงานจากไมโครคอนโทรลเลอร์จำนวน 5 ขา
- RD ส่งสัญญาณอ่าน
- WR ส่งสัญญาณเขียน
- DC ส่งสัญญาณว่าเขียนคำสั่ง
- RST ส่งสัญญาณรีเซ็ต
- CS ส่งสัญญาณให้โมดูลรู้ว่าถูกเรียกให้ทำงานหรือไม่ได้ถูกเรียกใช้
- ชิพขับโมดูลเป็น ili9341 (ภาพที่ 3) หรือ ili9481 (ภาพที่ 4)
ผังวงจร
ผังวงจรการเชื่อมต่อระหว่างขาของโมดูล LCD กับ STM32F401กับสวิตช์และลำโพง เป็นดังภาพที่ 5
จากภาพที่ 5 มีการเชื่อมต่อกันดังนี้
- TFT_CS ต่อกับ PB0
- TFT_RST ต่อกับ PB12
- TFT_RD ต่อกับ PA0
- TFT_WR ต่อกับ PA1
- TFT_DC ต่อกับ PA4
- SPK ต่อกับ PA7
- TFT_D0 ต่อเข้ากับ PA9
- TFT_D1 ต่อเข้ากับ PB13
- TFT_D2 ต่อเข้ากับ PA10
- TFT_D3 ต่อเข้ากับ PB3
- TFT_D4 ต่อเข้ากับ PB5
- TFT_D5 ต่อเข้ากับ PB4
- TFT_D6 ต่อเข้ากับ PB10
- TFT_D7 ต่อเข้ากับ PA8
- ET-TEST 10P/INP ต่อเข้ากับขาดังต่อไปนี้
- PC13
- PC14
- PB1
- PB2
- PA2
- PA3
- PA50
- PA6
การตั้งค่า TFT_eSPI
การตั้งค่าในไฟล์ส่วนหัวของ TFT_eSPI กรณีที่โมดูลแสดงผลใช้ ILI9341 เป็นดังนี้
#define STM32
#define TFT_PARALLEL_8_BIT
#define ILI9341_DRIVER
#define TFT_CS PB0
#define TFT_DC PA4
#define TFT_RST PB12
#define TFT_WR PA1
#define TFT_RD PA0
#define TFT_D0 PA9
#define TFT_D1 PB13
#define TFT_D2 PA10
#define TFT_D3 PB3
#define TFT_D4 PB5
#define TFT_D5 PB4
#define TFT_D6 PB10
#define TFT_D7 PA8
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define SMOOTH_FONT
สำหรับกรณีที่ตัวขับโมดูล TFT เป็นชิพ ILI9481 ให้เปลี่ยนไดรเวอร์โดยกำหนดค่าต่าง ๆ เหมือนเดิม ดังนี้
#define STM32
#define TFT_PARALLEL_8_BIT
#define ILI9481_DRIVER
#define TFT_CS PB0 // Chip select control pin
#define TFT_DC PA4 // Data Command control pin
#define TFT_RST PB12 //PC1 // Reset pin ***
#define TFT_WR PA1 // Write strobe control pin
#define TFT_RD PA0 // Read pin
#define TFT_D0 PA9 // 8 bit parallel bus to TFT
#define TFT_D1 PB13 // PC7 // ***
#define TFT_D2 PA10
#define TFT_D3 PB3
#define TFT_D4 PB5
#define TFT_D5 PB4
#define TFT_D6 PB10
#define TFT_D7 PA8
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define SMOOTH_FONT
ตัวอย่างโปรแกรม
ตัวอย่างโปรแกรมทดสอบการแสดงผลโดยใช้งานไลบรารี U8g2_for_TFT_eSPI ซึ่งเป็นไลบรารีที่ทำงานผ่านชั้นของ TFT_eSPI อีกทีหนึ่ง โดยไลบรารีนี้มีจุดเเด่นในเรื่องของฟอนต์ที่มีความหลากหลาย (ดูได้จากที่นี่) และเลือกใช้ตัวอย่าง hello ของไลบรารีมาเพิ่มชุดคำสั่งเพื่อใช้งานได้ผลดังภาพที่ 6
/*
Hello.ino
Demonstrates how to use U8g2_for_TFT_eSPI library.
U8g2_for_TFT_eSPI:
- Use U8g2 fonts with TFT_eSPI
- Supports UTF-8 in print statement
- 90, 180 and 270 degree text direction
List of all U8g2 fonts: https://github.com/olikraus/u8g2/wiki/fntlistall
TFT_eSPI library: https://github.com/Bodmer/TFT_eSPI
U8g2_for_TFT_eSPI library: https://github.com/Bodmer/U8g2_for_TFT_eSPI
*/
#include "SPI.h"
#include "TFT_eSPI.h"
#include "U8g2_for_TFT_eSPI.h"
TFT_eSPI tft = TFT_eSPI(); // tft instance
U8g2_for_TFT_eSPI u8f; // U8g2 font instance
void setup() {
tft.begin();
tft.setRotation(1);
tft.fillScreen(0x3861);
u8f.begin(tft);
}
unsigned long x = 0;
void loop() {
u8f.setFontMode(0);
u8f.setFontDirection(0);
u8f.setForegroundColor(TFT_WHITE);
u8f.setFont(u8g2_font_helvR14_tf);
u8f.setCursor(0,20);
u8f.print("Hello World");
u8f.setCursor(0,40);
u8f.print("Umlaut ÄÖÜ");
u8f.setBackgroundColor(0x3861);
u8f.setForegroundColor(0xe717);
u8f.setFont(u8g2_font_osb21_tf);
u8f.setCursor(40,100);
u8f.print("www.JarutEx.com");
u8f.setForegroundColor(TFT_YELLOW);
u8f.setCursor(20,100);
u8f.print("~");
u8f.setCursor(280,100);
u8f.print("~");
u8f.setFont(u8g2_font_inb63_mn);
u8f.setFontMode(0);
u8f.setForegroundColor(TFT_WHITE);
while (1) {
u8f.setCursor(0,200);
u8f.print(x);
x++;
if (x > 99999) {
x = 0;
}
delay(1000);
}
}
จากโค้ดตัวอย่างมีคำสั่งที่น่าสนใจดังนี้
- begin( tft ) หมายถึง ไลบรารีต้องการ tft ซึ่งเป็นวัตถุแบบ TFT_eSPI เพื่อใช้สำหรับวาดตัวอักษร และเป็นคำสั่งเริ่มต้นทำงานของไลบรารี U8g_for_TFT_eSPI
- setFontMode(0) หมายถึงเป็นการวาดแบบทับพื้นหลัง
- setFontMode(1) หมายถึงวาดแบบลงเฉพาะจุดสีของตัวอักษร
- setFontDirection(x) หมายถึงกำหนดทิศทางการวาดตัวอักษร (ให้ลองเปลี่ยนค่า x จาก 0 เป็นค่าอื่น ๆ)
- setFont( x ) หมายถึงเลือกใช้ตัวอักษร x ซึ่งดูตัวอย่างตัวอักษร และค่าได้จากหน้าเว็บนี้
- setForegroundColor( c ) หมายถึง กำหนดสีของตัวอักษรเป็น c
- setBackgroundColor( c ) หมายถึง กำหนดสีพื้นหลังของตัวอักษรเป็น c
- setCursor( x, y ) หมายถึง กำหนดจุดเริ่มวาดตัวอักษรที่พิกัด (x,y) ซึ่งเป็นตำแหน่งด้านล่างซ้ายของการวาดตัวอักษร
- print(x) หมายถึง แสดงข้อความ x ตามลักษณะอักษร สี สีพื้นหลัง วิธีการวาด และตำแหน่งตามที่กำหนดในคำสั่งก่อนหน้านี้
สรุป
จากบทความนี้จะพบว่าการใช้การเชื่อมต่อแบบ Parallel ต้องการใช้ขามากกว่าการใช้ SPI บัส แต่เมื่อสังเกตที่การตั้งค่าของ TFT_eSPI จะพบว่า ไม่ต้องกำหนดความถี่สัญญาณนาฬิกาในการส่งข้อมูล ทำให้ความเร็วในการส่งโดยภาพรวมนั้นอาจจะได้สูงกว่าแบบ SPI เนื่องจากในความถี่ที่เท่ากัน SPI จะเสียเวลาในการถอดรหัสบิตข้อมูลจากแบบอนุกรมให้เป็นแบบขนาน เนื่องจากส่งมาทีละบิต แต่การนำไปใช้ต้องนำไปใช้ทั้งไบต์ ขณะที่แบบการส่งแบบขนานจะส่งครั้งละไบต์ในคราเดียว
นอกจากนี้ จะพบว่าการใช้ TFT_eSPI ทำให้รองรับการใช้จอแสดงผลที่หลากหลายรุ่นและได้ความเร็วในการทำงานที่อยู่ในระดับที่ดีมาก แต่จุดอ่อนของไลบรารีคือมีตัวอักษรให้เลือกใช้น้อย หรือต้องทำฟอนต์เพื่อมาใช้งานเอง แต่เมื่อเรียกใช้งานไลบรารี U8g_for_TFT_eSPI จะพบว่ามีรูปแบบของฟอนต์ให้ใช้งานมากมาย และหลากหลายรูปแบบ โดยการสั่งงานที่ต้องระมัดระวังคือ ปริมาณหน่วยความจำคงเหลือของระบบ และวิธีการวาดที่จะวาดจากล่างขึ้นบน ด้วยเหตุนี้ค่าที่ส่งให้กับคำสั่ง setCursor(x,y) นั้น ค่า y จะเป็นค่าด้านล่างของการวาดไม่ใช้ด้านบนเหมือนที่เคยใช้มา
สุดท้ายนี้ขอให้สนุกกับการเขียนโปรแกรมครับ
ท่านใดต้องการพูดคุยสามารถคอมเมนท์ได้เลยครับ
(C) 2020-2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2021-10-06, 2021-12-20