1. 从点亮第一块TFT彩屏开始
如果你玩Arduino有一段时间了,点亮过LED,驱动过舵机,也玩过1602、2004这类字符液晶屏,那么下一步,你大概率会想搞一块TFT彩屏来玩玩。这几乎是所有Arduino爱好者进阶路上的必经一站。原因很简单,一块能显示彩色图片、绘制图形、甚至播放简单动画的屏幕,能让你的项目瞬间“活”起来,从简单的数据监控,升级为拥有直观人机交互界面的智能设备。
我第一次接触Arduino TFT彩屏,是为了做一个环境监测站。当时用字符屏只能显示几行温度和湿度数字,枯燥得很。换上TFT屏后,我就能画一个温度计图标,用颜色条表示湿度,甚至把历史数据做成曲线图,整个项目的观感和实用性提升了好几个档次。市面上常见的Arduino兼容TFT彩屏,比如基于ILI9341、ST7735、ILI9488等驱动芯片的模块,价格已经非常亲民,接线也相对标准化,但真正上手时,从库的选择、引脚定义到性能优化,每一步都可能藏着新手容易掉进去的“坑”。
这篇文章,我就结合自己多次折腾不同型号TFT屏的经验,从最基础的接线、库安装,到显示图片、优化刷新率,再到实际项目中如何稳定驱动,为你梳理出一条清晰的路径。无论你是想用TFT屏做个游戏机、仪表盘,还是智能家居的中控界面,这里的内容都能帮你少走弯路。
2. 核心硬件选型与接线:避开第一个大坑
当你决定使用TFT彩屏时,面对的第一个问题就是:该买哪一款?市面上有1.8寸、2.4寸、3.5寸甚至更大的屏幕,驱动芯片也各不相同。我的建议是,对于Arduino Uno这类AVR核心的开发板,从2.4寸ILI9341驱动的屏幕开始是最佳选择。原因有三:首先,ILI9341是经过市场充分验证的经典驱动,社区支持极其完善,各种图形库对其兼容性最好;其次,2.4寸这个尺寸在分辨率和功耗、驱动难度上取得了很好的平衡(常见分辨率240x320);最后,它的价格通常是最具性价比的。
这些屏幕模块与Arduino的连接方式主要分为两大类:并行8位/16位接口和SPI串行接口。对于初学者和大多数应用,我强烈推荐使用SPI接口的模块。
注意:很多商家会卖两种版本的ILI9341屏,一种是带SD卡槽的“合体”模块,另一种是单纯的屏幕。对于入门,买带SD卡槽的版本更方便,因为你可以通过SD卡加载图片素材,而无需将图片数据硬编码到程序里,大大简化了开发。
为什么推荐SPI而不是并行?并行接口虽然理论刷新率更高,但它需要占用大量的IO口(通常需要8根或16根数据线,外加控制线),对于IO资源本就紧张的Arduino Uno来说简直是灾难,你会发现自己没剩几个引脚给其他传感器了。而SPI接口通常只需要4-6根线,极大地节省了IO资源。实际上,对于240x320这种分辨率的动画和界面,优化得当的SPI接口完全够用。
下面是一个典型的2.4寸ILI9341 SPI模块与Arduino Uno的接线表。这里需要特别注意“引脚标号”问题:模块上的引脚名称(如DC、CS)是固定的,但它们连接到Arduino的哪个数字引脚,是可以由你定义的(除了SCK、MISO、MOSI这组SPI硬件引脚)。
| TFT模块引脚 | Arduino Uno引脚 | 作用说明 |
|---|---|---|
| VCC | 5V | 电源正极。务必确认你的屏幕是5V逻辑电平,有些3.3V屏接5V会烧毁。 |
| GND | GND | 电源地。 |
| CS | Digital 10 | 片选引脚。此引脚可以接其他数字口,但在代码中需相应修改。 |
| RST | Digital 8 | 复位引脚。此引脚可以接其他数字口,也可接Arduino的RESET,但独立控制更灵活。 |
| DC(或 AO) | Digital 9 | 数据/命令选择引脚。这是SPI通信中区分发送的是命令还是显示数据的关键引脚。 |
| MOSI(SDI) | Digital 11 | SPI数据输入引脚。这是Arduino的硬件SPI主输出从输入引脚,固定为11。 |
| SCK(CLK) | Digital 13 | SPI时钟引脚。硬件SPI时钟,固定为13。 |
| MISO(SDO) | 未连接 | SPI数据输出引脚。仅当屏幕支持读操作或模块集成了SD卡读卡器需要读取SD卡时才连接。 |
| LED | 3.3V 或 通过电阻接5V | 背光控制。这是第一个大坑。很多模块的LED脚是背光阳极,需要接正极。有些可以直接接5V,但更安全的做法是串联一个100-220欧姆的电阻后接5V,或者接一个PWM引脚(如Digital 3)来实现亮度调节。 |
接线时最容易出错的就是背光。我曾有一次直接将LED脚接到5V,屏幕亮了一下就再也不亮了,后来发现是背光LED过流烧毁。所以,要么按说明书操作,要么先串联电阻。另一个坑是MISO线,如果你不需要从屏幕或SD卡读取数据,这根线可以不接,但如果你买了带SD卡槽的模块并想读取卡里的图片,就必须将模块的MISO接回Arduino的Digital 12引脚。
3. 驱动库的选择与基础图形编程
硬件连接妥当后,下一步就是让代码驱动屏幕。Arduino社区有几个强大的TFT库,最主流的是Adafruit_GFX图形核心库配合具体的硬件驱动库(如Adafruit_ILI9341)。这是Adafruit公司维护的一套库,文档齐全,例子丰富,是大多数人的首选。
安装方法很简单,打开Arduino IDE,点击“工具” -> “管理库…”,在库管理器中搜索“Adafruit ILI9341”,找到并安装。安装过程中,它会提示你同时安装依赖库Adafruit GFX Library和Adafruit BusIO,一定要全部安装。
安装好后,我们就可以开始第一个测试程序了。这个程序的目标是在屏幕上显示一些基本图形和文字,确认硬件和库工作正常。
// 引入必要的库 #include <SPI.h> #include <Adafruit_GFX.h> #include <Adafruit_ILI9341.h> // 定义我们接线时使用的引脚 #define TFT_CS 10 // 片选引脚 #define TFT_DC 9 // 数据/命令选择引脚 #define TFT_RST 8 // 复位引脚 // 初始化TFT对象,传入引脚定义和SPI接口(硬件SPI) Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); void setup() { Serial.begin(9600); Serial.println("ILI9341 测试开始!"); // 启动TFT屏幕 tft.begin(); // 将屏幕旋转180度(根据你的模块安装方向调整,参数可以是0,1,2,3) tft.setRotation(3); // 用黑色清空屏幕(RGB565格式:0x0000是黑色,0xFFFF是白色) tft.fillScreen(ILI9341_BLACK); // 1. 画一个矩形 tft.drawRect(10, 10, 100, 50, ILI9341_RED); // (起点x, 起点y, 宽, 高, 颜色) // 2. 画一个填充的圆 tft.fillCircle(200, 100, 30, ILI9341_GREEN); // (圆心x, 圆心y, 半径, 颜色) // 3. 画一条线 tft.drawLine(10, 150, 230, 150, ILI9341_BLUE); // 4. 显示文字 tft.setCursor(20, 200); // 设置文字起始坐标(左下角为起点) tft.setTextColor(ILI9341_WHITE); // 设置文字颜色 tft.setTextSize(2); // 设置文字大小(1为最小,整数倍放大) tft.println("Hello, TFT World!"); // 5. 显示一个三角形 tft.drawTriangle(60, 250, 100, 290, 20, 290, ILI9341_YELLOW); } void loop() { // 主循环暂时空置 }将代码上传到Arduino,如果一切正常,你应该能看到屏幕上绘制出了红色边框矩形、绿色实心圆、蓝色横线、白色文字和一个黄色三角形。这个测试涵盖了最基本的图形元素,验证了库函数工作正常。
这里有几个关键的实操心得:
setRotation()函数:它决定了屏幕的“零点”坐标在哪里。参数0、1、2、3分别对应0度、90度、180度、270度旋转。如果你的文字是横着显示的,但你想竖着用,调整这个参数即可。我通常通过试错来确定哪个值符合我的物理安装方向。- 颜色格式:
Adafruit_GFX库使用RGB565颜色格式。这是一个16位的颜色编码,用16位二进制数表示一个像素的颜色:高5位是红色,中间6位是绿色,低5位是蓝色。所以ILI9341_RED实际上是0xF800(二进制1111100000000000)。你也可以用tft.color565(255, 0, 0)来将通用的RGB值(每个0-255)转换为RGB565格式。 - 坐标系统:原点
(0,0)默认在屏幕的左上角。X轴向右增加,Y轴向下增加。这点和许多计算机图形学系统一致,但和数学坐标系不同,需要注意。
4. 显示位图图片:从SD卡与程序内存两种方式
静态图形和文字满足基础需求,但让项目出彩的往往是自定义的图片、图标和界面元素。在Arduino上显示图片,主要有两种途径:从SD卡读取和将图片数据直接编译进程序。
4.1 从SD卡读取并显示图片(动态加载)
这是最灵活的方式,你可以随时更换SD卡里的图片,而无需修改和重新上传程序。前提是你的TFT模块集成了SD卡槽,并且你已经正确连接了MISO线(到Arduino的Pin 12)。
首先需要安装SD卡库。Arduino IDE自带了一个SD库,但Adafruit推荐使用它们优化的SdFat库,性能更好。同样在库管理中搜索“SdFat - Adafruit Fork”并安装。
接下来,你需要将图片转换成Arduino TFT屏可以识别的格式。这里推荐一个非常强大的工具:Img2Code或LCD Image Converter。我个人常用后者,它支持将常见的PNG、BMP等图片转换为C语言数组(即.h头文件),并且可以选择输出为RGB565原始数据格式,这正是我们需要的。
但是,对于从SD卡读取,我们不需要将图片转成C数组,而是需要将图片保存为原始的RGB565位图文件。你可以用LCD Image Converter软件,载入图片后,在“转换”设置里选择输出为“Binary”(二进制),并选择RGB565格式。这样会生成一个.bin文件,将这个文件重命名为一个简单的名字(如test.bin),并拷贝到SD卡的根目录。
下面是一个从SD卡读取RGB565原始文件并显示的函数:
#include <SPI.h> #include <Adafruit_GFX.h> #include <Adafruit_ILI9341.h> #include <SdFat.h> // 使用性能更好的SD库 #define TFT_CS 10 #define TFT_DC 9 #define TFT_RST 8 #define SD_CS 4 // 假设SD卡槽的片选引脚接在Arduino的Pin 4上 Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); SdFat SD; void setup() { Serial.begin(9600); tft.begin(); tft.setRotation(3); tft.fillScreen(ILI9341_BLACK); // 初始化SD卡 if (!SD.begin(SD_CS)) { Serial.println("SD卡初始化失败!"); while (1); // 卡住 } Serial.println("SD卡初始化成功。"); // 显示图片 drawRGBBitmapFromSD("test.bin", 0, 0, 240, 320); // 假设图片是240x320全屏 } void loop() {} // 核心函数:从SD卡读取RGB565原始文件并显示 void drawRGBBitmapFromSD(const char *filename, int16_t x, int16_t y, int16_t w, int16_t h) { File file = SD.open(filename, FILE_READ); if (!file) { Serial.print("无法打开文件: "); Serial.println(filename); return; } // 设置TFT显示窗口为我们要绘制的区域 tft.setAddrWindow(x, y, x + w - 1, y + h - 1); // 计算需要读取的数据总量 (宽度 * 高度 * 2字节每像素) uint32_t totalPixels = (uint32_t)w * h; uint32_t bytesToRead = totalPixels * 2; // 一次性分配缓冲区(对于Uno,内存有限,需要分块读取) const uint16_t bufferSize = 512; // 每次读取512字节(256个像素) uint8_t readBuffer[bufferSize]; uint32_t bytesRead = 0; while (bytesRead < bytesToRead) { // 计算本次读取的字节数 uint16_t toRead = min((uint32_t)bufferSize, bytesToRead - bytesRead); uint16_t actuallyRead = file.read(readBuffer, toRead); if (actuallyRead != toRead) { Serial.println("读取文件出错!"); break; } // 将读取到的数据通过SPI发送到TFT屏幕 // 这里使用SPI传输函数,Adafruit库内部处理了数据发送 // 对于大量数据,我们直接操作底层SPI以获得更快速度 SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); // 设置SPI参数 digitalWrite(TFT_DC, HIGH); // 拉高DC,表示后面是显示数据 digitalWrite(TFT_CS, LOW); // 选中TFT for (uint16_t i = 0; i < actuallyRead; i++) { SPI.transfer(readBuffer[i]); } digitalWrite(TFT_CS, HIGH); // 取消选中TFT SPI.endTransaction(); bytesRead += actuallyRead; } file.close(); Serial.print("图片显示完成。总字节数:"); Serial.println(bytesRead); }这个函数的关键在于setAddrWindow和分块读取。由于Arduino Uno的内存只有2KB,无法一次性加载一张240x320的图片(约150KB),我们必须分块从SD卡读取,并立即发送到屏幕。setAddrWindow函数告诉屏幕,接下来发送的像素数据应该填充到哪个矩形区域。
4.2 将图片数据编译进程序(静态存储)
如果你的项目图片不多,且不经常更换,或者你的模块没有SD卡槽,那么将图片数据直接放在程序里是更简单可靠的选择。缺点是图片会占用大量的程序存储空间(Flash),可能导致Uno的32KB空间紧张。
同样使用LCD Image Converter软件,但这次我们选择输出为“C array”或“Source code”。软件会生成一个.c和.h文件。我们将.h文件的内容(一个巨大的数组声明)复制到Arduino项目的标签页里,或者直接保存为一个头文件。
例如,转换后得到一个bitmap.h文件,里面包含:
const uint16_t myBitmap[76800] = { 0xFFFF, 0xFFFF, 0xF800, ... }; // 240*320=76800个元素在Arduino主程序中:
#include "bitmap.h" #include <Adafruit_GFX.h> #include <Adafruit_ILI9341.h> #define TFT_CS 10 #define TFT_DC 9 #define TFT_RST 8 Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); void setup() { tft.begin(); tft.setRotation(3); // 使用drawRGBBitmap函数直接显示内存中的数组 tft.drawRGBBitmap(0, 0, myBitmap, 240, 320); } void loop() {}这种方式代码极其简洁,但drawRGBBitmap函数在底层依然需要将整个数组通过SPI发送出去。对于全屏图片,Uno的RAM可能放不下这么大的数组(76800 * 2字节 ≈ 150KB),但Flash空间可以容纳。Adafruit_GFX库的drawRGBBitmap函数会自动从程序存储空间(通过PROGMEM)读取数据,所以我们需要确保图片数组被定义在Flash中。在bitmap.h中,应该这样定义:
const uint16_t myBitmap[76800] PROGMEM = { ... };重要提示:使用
PROGMEM时,必须使用库提供的drawRGBBitmap函数或其变体,它们知道如何从Flash中正确读取数据。直接使用SPI.transfer发送PROGMEM数组会得到错误的数据。
5. 性能优化与高级技巧:让动画流畅起来
当你尝试在TFT屏上制作动画或快速更新数据时,可能会发现屏幕刷新很慢,甚至有闪烁感。这是因为SPI的传输速度有限,且每次全屏刷新都要传输大量数据。优化性能是TFT项目进阶的必修课。
5.1 提升SPI时钟频率
默认的SPI速度可能比较保守。你可以在初始化时尝试提高SPI时钟频率。在Adafruit_ILI9341库的begin()函数内部,或者在你自己的传输函数中(如之前SD卡显示的例子里),使用SPI.beginTransaction(SPISettings(...))来设置更高的速度。对于ILI9341,在5V电压下,通常可以稳定运行在30MHz甚至更高。但在Uno的16MHz主频下,实际SPI时钟会被分频。一个安全的、能显著提升速度的设置是SPISettings(8000000, MSBFIRST, SPI_MODE0)(8MHz)。
// 在需要高速传输数据的地方,包裹SPI事务 SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); // ... 执行数据传输 ... SPI.endTransaction();5.2 局部刷新与双缓冲(在Uno上的变通)
真正的双缓冲(在内存中准备一整帧图像,然后一次性切换显示)在Arduino Uno上几乎不可能,因为内存太小。但我们有变通方案:局部刷新。只更新屏幕上发生变化的部分,而不是重绘整个屏幕。
例如,你在做一个仪表盘,只有中间的数字需要每秒变化。那么你可以在第一次绘制时,画出静态的背景、表盘、刻度。然后每次更新时,只在数字区域用背景色“覆盖”旧的数字,再绘制新的数字。这样可以避免重绘整个屏幕,极大提升刷新率。
// 假设在坐标(100,100)处显示一个数字 int oldValue = -1; void updateDisplay(int newValue) { if (newValue == oldValue) return; // 值未变化,无需更新 // 1. 用背景色清除旧数字的区域(假设背景是黑色) tft.setTextColor(ILI9341_BLACK); // 设置文字颜色为背景色 tft.setCursor(100, 100); tft.setTextSize(3); if (oldValue >= 0) { // 第一次oldValue为-1,不执行清除 tft.print(oldValue); } // 2. 绘制新数字 tft.setTextColor(ILI9341_WHITE); // 设置文字颜色为前景色 tft.setCursor(100, 100); // 光标位置不变 tft.print(newValue); oldValue = newValue; // 更新旧值 }5.3 使用fillRect替代fillScreen进行清屏
如果你需要清屏,但又不是整个屏幕,使用fillRect指定区域比用fillScreen重绘整个屏幕要快得多。fillScreen本质上就是调用一个覆盖全屏的fillRect。
5.4 避免在loop()中频繁执行setRotation、setTextSize等设置函数
这些设置函数内部可能会与屏幕进行多次通信。应该在setup()中或状态改变时才调用它们,而不是在每帧动画中都调用。例如,如果文字大小不变,就在初始化时设置一次tft.setTextSize(2),之后在loop()中只调用setCursor()和print()。
5.5 升级硬件:使用ESP32或Teensy
如果经过以上优化,性能仍无法满足你的动画或UI需求,那么最终的解决方案是升级主控芯片。像ESP32或Teensy 4.0这类MCU,拥有更快的CPU、更多的内存,甚至硬件加速的SPI,驱动同样的TFT屏,流畅度会有质的飞跃。ESP32还可以利用其双核特性,一核处理传感器逻辑,另一核专负责刷新显示,互不干扰。
6. 实战项目构想:打造一个TFT环境信息显示器
掌握了基础显示和图片加载后,我们可以将这些知识整合起来,做一个实用的项目。这里我规划一个桌面环境信息显示器,它能够从传感器读取温湿度、气压数据,并在TFT屏上以图形化的方式美观地展示出来,同时显示一张自定义的背景图。
所需材料清单:
- Arduino Uno(或ESP32,性能更好)
- 2.4寸 ILI9341 TFT触摸屏模块(带SD卡槽)
- DHT22温湿度传感器
- BMP280气压传感器
- 面包板、杜邦线若干
- 一张microSD卡,存入背景图片
bg.bin
接线示意图(叠加在之前TFT接线基础上):
- DHT22:
VCC-> 5V,GND-> GND,DATA-> Digital 2 - BMP280:
VCC-> 3.3V,GND-> GND,SCL-> A5,SDA-> A4 (使用I2C接口)
软件设计思路:
- 初始化:在
setup()中,初始化TFT、SD卡、DHT22、BMP280。从SD卡加载背景图片并全屏显示。 - 绘制静态UI:在背景图上,用绘图函数画出固定的文字标签(如“温度:”、“湿度:”、“气压:”)和装饰性元素(如图标框)。这些只需要绘制一次。
- 动态数据更新:在
loop()中,每隔2秒读取一次传感器数据。使用前面提到的局部刷新技巧,只更新显示数值的区域。为了更直观,可以用fillRect画一个简单的柱状图或曲线图来表示历史趋势(例如,保留最近10个温度值,在屏幕一角连成线)。 - 背光控制:可以增加一个光敏电阻,根据环境光线自动调节屏幕背光亮度(通过PWM控制
LED引脚),或者设置一个物理按键来开关背光以省电。
核心代码片段(数据更新部分):
#include <DHT.h> #include <Adafruit_BMP280.h> // ... 其他必要的库和定义 DHT dht(DHTPIN, DHTTYPE); Adafruit_BMP280 bmp; float oldTemp = -100; float oldHum = -1; float oldPres = -1; void loop() { // 每2秒更新一次 static unsigned long lastUpdate = 0; if (millis() - lastUpdate > 2000) { lastUpdate = millis(); float newTemp = dht.readTemperature(); // 读取温度 float newHum = dht.readHumidity(); // 读取湿度 float newPres = bmp.readPressure() / 100.0F; // 读取气压并转换为百帕 // 更新温度显示(局部刷新) updateValueDisplay(50, 100, oldTemp, newTemp, "C", 1); // 更新湿度显示 updateValueDisplay(50, 140, oldHum, newHum, "%", 0); // 更新气压显示 updateValueDisplay(50, 180, oldPres, newPres, "hPa", 1); // 更新历史数据图表(假设有一个函数drawGraph) // addToGraphHistory(newTemp); // drawGraph(); // 保存旧值 oldTemp = newTemp; oldHum = newHum; oldPres = newPres; } } // 通用的局部刷新显示函数 void updateValueDisplay(int x, int y, float oldVal, float newVal, const char* unit, int decimals) { // 如果值无效(传感器读取失败),跳过 if (isnan(newVal)) return; // 1. 清除旧值 tft.setTextColor(BACKGROUND_COLOR); // 背景色 tft.setCursor(x, y); tft.setTextSize(2); if (!isnan(oldVal)) { tft.print(oldVal, decimals); tft.print(unit); } // 2. 绘制新值 tft.setTextColor(VALUE_COLOR); // 数据颜色,如白色 tft.setCursor(x, y); tft.print(newVal, decimals); tft.print(unit); }在这个项目中,你将综合运用硬件连接、库函数调用、图片显示、局部刷新优化等多种技能。当项目完成后,你会得到一个外观专业、反应灵敏的桌面摆件,这远比简单的串口打印数据有成就感得多。
7. 常见问题排查与经验总结
即使按照教程操作,你也可能会遇到屏幕白屏、花屏、颜色错乱等问题。下面是我总结的一些常见故障和解决方法:
1. 屏幕白屏或完全不亮:
- 检查电源和背光:这是最常见的问题。用万用表测量
VCC和GND之间是否有5V电压。检查LED背光引脚是否已正确连接(串联电阻后接5V或PWM引脚)。 - 检查复位信号:确保
RST引脚没有被意外拉低。可以尝试在setup()最开始手动复位:digitalWrite(TFT_RST, LOW); delay(10); digitalWrite(TFT_RST, HIGH); delay(100);。 - 检查SPI引脚:确认
SCK(13),MOSI(11),CS(10),DC(9)的接线无误,没有虚焊。
2. 屏幕显示花屏、错位或颜色异常:
- 检查
setRotation():不同的旋转设置会导致显示方向不对,可能被误认为是花屏。尝试0,1,2,3四个参数。 - 检查颜色格式:确保你发送的数据格式是屏幕驱动的RGB565。如果你自己生成图片数据,转换工具的输出格式必须选对。
- SPI速度过快:尝试降低
SPISettings中的时钟频率,比如从8000000降到4000000。长导线或干扰可能导致高速通信出错。 - 库不匹配或初始化顺序:确保你使用的
Adafruit_ILI9341库版本与Adafruit_GFX库兼容。有时需要在tft.begin()之前调用SPI.begin()。
3. 显示图片时出现内存不足(Arduino Uno):
- 症状:编译通过,但上传后运行异常,或图片显示不全。
- 解决方案:
- 优化代码,减少全局变量。
- 使用
F()宏将常量字符串存到Flash中,如Serial.println(F("Hello"))。 - 对于SD卡图片,确保分块读取的缓冲区不要太大(如示例中的512字节)。
- 如果图片数据存在程序内(
PROGMEM),确认图片尺寸是否过大。全屏240x320的RGB565图片约150KB,Uno的32KB Flash可能装不下。可以考虑降低图片色彩深度(如降至256色),或缩小图片尺寸。
4. 刷新速度太慢:
- 实施前面第5章提到的所有优化策略。
- 审查你的代码,是否在
loop()中做了不必要的全屏清除(fillScreen)或大量绘制。 - 考虑升级到更快的开发板,如ESP32。
最后一点经验:给整个项目提供一个稳定、足额的电源。TFT屏在点亮背光时功耗不小,特别是大尺寸屏幕。使用电脑USB口或手机充电器给Arduino供电时,可能因为电流不足导致屏幕工作不稳定或单片机重启。建议使用能提供5V/2A以上的独立电源适配器。我在做一个3.5寸屏的项目时,就因为电源问题调试了半天,屏幕时而正常时而乱码,最后换了一个电源就彻底解决了。