原生示例
#include <Arduino.h>
#include <SPI.h>
// ESP-12E (NodeMCU) 引脚定义
#define LED D0 // GPIO16
#define CS D8 // GPIO15
#define RS D1 // GPIO5
#define RESET D2 // GPIO4
void SPI_Init(void)
{
SPI.begin();
SPI.setClockDivider(40000000); // 设置SPI速度为40MHz
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
}
void Lcd_Writ_Bus(uint8_t d) {
SPI.transfer(d);
}
void Lcd_Write_Com(uint8_t VH) {
digitalWrite(RS, LOW); // 使用digitalWrite替代直接端口操作
Lcd_Writ_Bus(VH);
}
void Lcd_Write_Data(uint8_t VH) {
digitalWrite(RS, HIGH); // 使用digitalWrite替代直接端口操作
Lcd_Writ_Bus(VH);
}
void Lcd_Write_Com_Data(uint8_t com, uint8_t dat) {
Lcd_Write_Com(com);
Lcd_Write_Data(dat);
}
void Address_set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
Lcd_Write_Com(0x2a);
Lcd_Write_Data(x1>>8);
Lcd_Write_Data(x1);
Lcd_Write_Data(x2>>8);
Lcd_Write_Data(x2);
Lcd_Write_Com(0x2b);
Lcd_Write_Data(y1>>8);
Lcd_Write_Data(y1);
Lcd_Write_Data(y2>>8);
Lcd_Write_Data(y2);
Lcd_Write_Com(0x2c);
}
void Lcd_Init(void)
{
digitalWrite(RESET,HIGH);
delay(5);
digitalWrite(RESET,LOW);
delay(15);
digitalWrite(RESET,HIGH);
delay(15);
digitalWrite(CS,LOW); //CS
Lcd_Write_Com(0xF7);
Lcd_Write_Data(0xA9);
Lcd_Write_Data(0x51);
Lcd_Write_Data(0x2C);
Lcd_Write_Data(0x82);
Lcd_Write_Com(0xC0);
Lcd_Write_Data(0x11);
Lcd_Write_Data(0x09);
Lcd_Write_Com(0xC1);
Lcd_Write_Data(0x41);
Lcd_Write_Com(0xC5);
Lcd_Write_Data(0x00);
Lcd_Write_Data(0x0A);
Lcd_Write_Data(0x80);
Lcd_Write_Com(0xB1);
Lcd_Write_Data(0xB0);
Lcd_Write_Data(0x11);
Lcd_Write_Com(0xB4);
Lcd_Write_Data(0x02);
Lcd_Write_Com(0xB6);
Lcd_Write_Data(0x02);
Lcd_Write_Data(0x22);
Lcd_Write_Com(0xB7);
Lcd_Write_Data(0xC6);
Lcd_Write_Com(0xBE);
Lcd_Write_Data(0x00);
Lcd_Write_Data(0x04);
Lcd_Write_Com(0xE9);
Lcd_Write_Data(0x00);
Lcd_Write_Com(0x36);
Lcd_Write_Data(0x08);
Lcd_Write_Com(0x3A);
Lcd_Write_Data(0x66);
Lcd_Write_Com(0xE0);
Lcd_Write_Data(0x00);
Lcd_Write_Data(0x07);
Lcd_Write_Data(0x10);
Lcd_Write_Data(0x09);
Lcd_Write_Data(0x17);
Lcd_Write_Data(0x0B);
Lcd_Write_Data(0x41);
Lcd_Write_Data(0x89);
Lcd_Write_Data(0x4B);
Lcd_Write_Data(0x0A);
Lcd_Write_Data(0x0C);
Lcd_Write_Data(0x0E);
Lcd_Write_Data(0x18);
Lcd_Write_Data(0x1B);
Lcd_Write_Data(0x0F);
Lcd_Write_Com(0xE1);
Lcd_Write_Data(0x00);
Lcd_Write_Data(0x17);
Lcd_Write_Data(0x1A);
Lcd_Write_Data(0x04);
Lcd_Write_Data(0x0E);
Lcd_Write_Data(0x06);
Lcd_Write_Data(0x2F);
Lcd_Write_Data(0x45);
Lcd_Write_Data(0x43);
Lcd_Write_Data(0x02);
Lcd_Write_Data(0x0A);
Lcd_Write_Data(0x09);
Lcd_Write_Data(0x32);
Lcd_Write_Data(0x36);
Lcd_Write_Data(0x0F);
Lcd_Write_Com(0x11); //Exit Sleep
delay(120);
Lcd_Write_Com(0x29); //Display on
digitalWrite(CS,HIGH);
}
void H_line(unsigned int x, unsigned int y, unsigned int l, unsigned int c)
{
unsigned int i,j;
digitalWrite(CS,LOW);
Lcd_Write_Com(0x02c); //write_memory_start
//digitalWrite(RS,HIGH);
l=l+x;
Address_set(x,y,l,y);
j=l*2;
for(i=1;i<=j;i++)
{
Lcd_Write_Data((c>>8)&0xF8);
Lcd_Write_Data((c>>3)&0xFC);
Lcd_Write_Data(c<<3);
}
digitalWrite(CS,HIGH);
}
void V_line(unsigned int x, unsigned int y, unsigned int l, unsigned int c)
{
unsigned int i,j;
digitalWrite(CS,LOW);
Lcd_Write_Com(0x02c); //write_memory_start
//digitalWrite(RS,HIGH);
l=l+y;
Address_set(x,y,x,l);
j=l*2;
for(i=1;i<=j;i++)
{
Lcd_Write_Data((c>>8)&0xF8);
Lcd_Write_Data((c>>3)&0xFC);
Lcd_Write_Data(c<<3);
}
digitalWrite(CS,HIGH);
}
void Rect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c)
{
H_line(x , y , w, c);
H_line(x , y+h, w, c);
V_line(x , y , h, c);
V_line(x+w, y , h, c);
}
void Rectf(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c)
{
unsigned int i;
for(i=0;i<h;i++)
{
H_line(x , y , w, c);
H_line(x , y+i, w, c);
}
}
int RGB(int r,int g,int b)
{
return r << 16 | g << 8 | b;
}
void LCD_Clear(unsigned int j)
{
unsigned int i,m;
digitalWrite(CS,LOW);
Address_set(0,0,320,480);
for(i=0;i<320;i++)
for(m=0;m<480;m++)
{
Lcd_Write_Data((j>>8)&0xF8);
Lcd_Write_Data((j>>3)&0xFC);
Lcd_Write_Data(j<<3);
}
digitalWrite(CS,HIGH);
}
void setup() {
// 初始化引脚模式
pinMode(LED, OUTPUT);
pinMode(RS, OUTPUT);
pinMode(RESET, OUTPUT);
pinMode(CS, OUTPUT);
// 设置初始状态
digitalWrite(LED, HIGH); // 背光开启
digitalWrite(CS, HIGH); // 初始不选中
digitalWrite(RS, HIGH); // 初始数据模式
SPI_Init();
Lcd_Init();
}
void loop() {
LCD_Clear(0xf800); // 红色
LCD_Clear(0x07E0); // 绿色
LCD_Clear(0x001F); // 蓝色
LCD_Clear(0x0000); // 黑色
for(int i=0; i<100; i++) { // 减少测试图形数量
Rect(random(300), random(300), random(100), random(100), random(65535));
}
}
GFX示例
/*******************************************************************************
* Start of Arduino_GFX setting
*
* Arduino_GFX try to find the settings depends on selected board in Arduino IDE
* Or you can define the display dev kit not in the board list
* Defalult pin list for non display dev kit:
* Arduino Nano, Micro and more: CS: 9, DC: 8, RST: 7, BL: 6, SCK: 13, MOSI: 11, MISO: 12
* ESP32 various dev board : CS: 5, DC: 27, RST: 33, BL: 22, SCK: 18, MOSI: 23, MISO: nil
* ESP32-C3 various dev board : CS: 7, DC: 2, RST: 1, BL: 3, SCK: 4, MOSI: 6, MISO: nil
* ESP32-S2 various dev board : CS: 34, DC: 38, RST: 33, BL: 21, SCK: 36, MOSI: 35, MISO: nil
* ESP32-S3 various dev board : CS: 40, DC: 41, RST: 42, BL: 48, SCK: 36, MOSI: 35, MISO: nil
* ESP8266 various dev board : CS: 15, DC: 4, RST: 2, BL: 5, SCK: 14, MOSI: 13, MISO: 12
* Raspberry Pi Pico dev board : CS: 17, DC: 27, RST: 26, BL: 28, SCK: 18, MOSI: 19, MISO: 16
* RTL8720 BW16 old patch core : CS: 18, DC: 17, RST: 2, BL: 23, SCK: 19, MOSI: 21, MISO: 20
* RTL8720_BW16 Official core : CS: 9, DC: 8, RST: 6, BL: 3, SCK: 10, MOSI: 12, MISO: 11
* RTL8722 dev board : CS: 18, DC: 17, RST: 22, BL: 23, SCK: 13, MOSI: 11, MISO: 12
* RTL8722_mini dev board : CS: 12, DC: 14, RST: 15, BL: 13, SCK: 11, MOSI: 9, MISO: 10
* Seeeduino XIAO dev board : CS: 3, DC: 2, RST: 1, BL: 0, SCK: 8, MOSI: 10, MISO: 9
* Teensy 4.1 dev board : CS: 39, DC: 41, RST: 40, BL: 22, SCK: 13, MOSI: 11, MISO: 12
******************************************************************************/
#include <Arduino_GFX_Library.h>
// ESP12E 引脚定义
#define TFT_CS 15 // GPIO15
#define TFT_DC 4 // GPIO4
#define TFT_RST 2 // GPIO2
#define TFT_BL 5 // GPIO5(背光控制)
void testDisplay();
// 使用硬件SPI
Arduino_DataBus *bus = new Arduino_ESP8266SPI(TFT_DC, TFT_CS);
Arduino_GFX *gfx = new Arduino_ILI9488_18bit(bus, TFT_RST); // 使用18位模式
void setup(void) {
Serial.begin(115200);
Serial.println("\n\nILI9488 3.5\" Display Test");
// 先控制复位引脚
pinMode(TFT_RST, OUTPUT);
digitalWrite(TFT_RST, LOW);
delay(100);
digitalWrite(TFT_RST, HIGH);
delay(200); // 复位后等待
// 初始化背光(尝试两种逻辑)
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH); // 尝试高电平
delay(100);
digitalWrite(TFT_BL, LOW); // 尝试低电平
delay(100);
Serial.println("Initializing display...");
// 初始化显示屏(降低SPI速度)
if (!gfx->begin(27000000)) { // 27MHz SPI速度
Serial.println("Display init failed!");
} else {
Serial.println("Display init success!");
}
// 执行硬件测试
testDisplay();
Serial.println("Setup complete");
}
void testDisplay() {
// 测试背光
Serial.println("Testing backlight...");
for (int i = 0; i < 3; i++) {
digitalWrite(TFT_BL, HIGH);
delay(300);
digitalWrite(TFT_BL, LOW);
delay(300);
}
digitalWrite(TFT_BL, HIGH); // 保持开启
// 颜色填充测试
Serial.println("Color fill test...");
gfx->fillScreen(RED);
delay(1000);
gfx->fillScreen(GREEN);
delay(1000);
gfx->fillScreen(BLUE);
delay(1000);
// 显示文本
gfx->fillScreen(BLACK);
gfx->setTextColor(WHITE, BLACK);
gfx->setTextSize(2, 2);
gfx->setCursor(30, 140);
gfx->println("ILI9488 3.5\"");
gfx->setCursor(50, 180);
gfx->println("480x320");
gfx->setCursor(80, 220);
gfx->setTextColor(YELLOW, BLACK);
gfx->println("WORKING!");
}
void loop() {
// 显示动态内容
static int counter = 0;
gfx->fillRect(0, 0, 480, 40, BLACK); // 清空顶部区域
gfx->setTextSize(2, 2);
gfx->setCursor(10, 10);
gfx->setTextColor(random(0xFFFF), BLACK);
gfx->printf("Counter: %d", counter++);
delay(500);
}
GFX结合LVGL
/*******************************************************************************
* [原有Arduino_GFX设置代码保持不变]
******************************************************************************/
#include <Arduino_GFX_Library.h>
#include <lvgl.h> // 添加LVGL库
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p);
void create_test_ui();
// ESP12E 引脚定义
#define TFT_CS 15 // GPIO15
#define TFT_DC 4 // GPIO4
#define TFT_RST 2 // GPIO2
#define TFT_BL 5 // GPIO5(背光控制)
// 使用硬件SPI
Arduino_DataBus *bus = new Arduino_ESP8266SPI(TFT_DC, TFT_CS);
Arduino_GFX *gfx = new Arduino_ILI9488_18bit(bus, TFT_RST); // 使用18位模式
/* LVGL配置 */
#define LV_HOR_RES_MAX 480 // 水平分辨率
#define LV_VER_RES_MAX 320 // 垂直分辨率
#define LV_BUF_SIZE (LV_HOR_RES_MAX * 2) // 缓冲区大小(行数)
static lv_disp_draw_buf_t draw_buf; // LVGL绘制缓冲区
static lv_color_t buf1[LV_BUF_SIZE]; // 第一缓冲区
static lv_color_t buf2[LV_BUF_SIZE]; // 第二缓冲区(双缓冲)
// 测试界面相关变量
static lv_obj_t *main_screen;
static lv_obj_t *time_label;
static lv_obj_t *counter_label;
static lv_obj_t *anim_bar;
static lv_obj_t *arc;
static uint32_t counter = 0;
void setup(void) {
Serial.begin(115200);
Serial.println("\n\nILI9488 with LVGL Integration");
// 复位显示屏
pinMode(TFT_RST, OUTPUT);
digitalWrite(TFT_RST, LOW);
delay(100);
digitalWrite(TFT_RST, HIGH);
delay(200);
// 初始化背光
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH); // 保持常亮
// 初始化显示屏
if (!gfx->begin(27000000)) { // 27MHz SPI速度
Serial.println("Display init failed!");
while(1); // 停止执行
}
// 设置横屏模式
gfx->setRotation(1); // 1表示90度旋转,通常是横屏
Serial.println("Display init success!");
/* 初始化LVGL */
lv_init();
/* 初始化双缓冲区 */
lv_disp_draw_buf_init(&draw_buf, buf1, buf2, LV_BUF_SIZE);
/* 注册显示驱动 */
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = LV_HOR_RES_MAX;
disp_drv.ver_res = LV_VER_RES_MAX;
disp_drv.flush_cb = my_disp_flush; // 注册刷新回调
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register(&disp_drv);
/* 创建测试界面 */
create_test_ui();
Serial.println("LVGL test interface initialized");
}
/* 显示刷新回调函数 */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
uint32_t w = (area->x2 - area->x1 + 1);
uint32_t h = (area->y2 - area->y1 + 1);
gfx->draw16bitRGBBitmap(
area->x1, // x起始位置
area->y1, // y起始位置
(uint16_t *)color_p, // 数据指针
w, // 宽度
h // 高度
);
lv_disp_flush_ready(disp); // 通知LVGL刷新完成
}
/* 创建测试界面 */
void create_test_ui() {
// 创建主屏幕
main_screen = lv_scr_act();
lv_obj_set_style_bg_color(main_screen, lv_color_hex(0x003060), 0);
// 标题
lv_obj_t *title = lv_label_create(main_screen);
lv_label_set_text(title, "LVGL Test Interface");
// 移除字体设置,使用默认字体
lv_obj_set_style_text_color(title, lv_color_white(), 0);
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 10);
// 时间显示标签
time_label = lv_label_create(main_screen);
lv_label_set_text(time_label, "Time: 0s");
// 移除字体设置,使用默认字体
lv_obj_set_style_text_color(time_label, lv_color_white(), 0);
lv_obj_align(time_label, LV_ALIGN_TOP_MID, 0, 50);
// 计数器显示标签
counter_label = lv_label_create(main_screen);
lv_label_set_text(counter_label, "Counter: 0");
// 移除字体设置,使用默认字体
lv_obj_set_style_text_color(counter_label, lv_color_white(), 0);
lv_obj_align(counter_label, LV_ALIGN_TOP_MID, 0, 80);
// 弧形进度条
arc = lv_arc_create(main_screen);
lv_obj_set_size(arc, 150, 150);
lv_arc_set_rotation(arc, 180);
lv_arc_set_bg_angles(arc, 0, 360);
lv_arc_set_value(arc, 0);
lv_obj_align(arc, LV_ALIGN_CENTER, 0, -20);
// 弧形标签
lv_obj_t *arc_label = lv_label_create(main_screen);
lv_label_set_text(arc_label, "Arc Progress");
lv_obj_set_style_text_color(arc_label, lv_color_white(), 0);
lv_obj_align_to(arc_label, arc, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
// 进度条
anim_bar = lv_bar_create(main_screen);
lv_obj_set_size(anim_bar, 300, 20);
lv_obj_align(anim_bar, LV_ALIGN_BOTTOM_MID, 0, -50);
lv_bar_set_range(anim_bar, 0, 100);
lv_bar_set_value(anim_bar, 0, LV_ANIM_ON);
// 进度条标签
lv_obj_t *bar_label = lv_label_create(main_screen);
lv_label_set_text(bar_label, "Animated Bar");
lv_obj_set_style_text_color(bar_label, lv_color_white(), 0);
lv_obj_align_to(bar_label, anim_bar, LV_ALIGN_OUT_TOP_MID, 0, -5);
// 创建动画
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, anim_bar);
lv_anim_set_values(&a, 0, 100);
lv_anim_set_time(&a, 3000);
lv_anim_set_playback_time(&a, 3000);
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_bar_set_value);
lv_anim_start(&a);
}
void loop() {
// 更新时间显示
static uint32_t last_update = 0;
uint32_t current_time = millis() / 1000;
if (current_time != last_update) {
last_update = current_time;
char time_buf[32];
sprintf(time_buf, "Time: %ds", (int)current_time);
lv_label_set_text(time_label, time_buf);
// 更新计数器
counter++;
char counter_buf[32];
sprintf(counter_buf, "Counter: %d", (int)counter);
lv_label_set_text(counter_label, counter_buf);
// 更新弧形进度条
lv_arc_set_value(arc, counter % 101);
}
lv_timer_handler(); // 处理LVGL任务
delay(5); // 短暂延时
}
触摸屏驱动解决方案 (ILI9488 + MSP3520)
有问题
#include <Arduino_GFX_Library.h>
#include <XPT2046_Touchscreen.h> // MSP3520兼容XPT2046库
// 显示屏引脚配置
#define TFT_CS 15 // GPIO15
#define TFT_DC 4 // GPIO4
#define TFT_RST 2 // GPIO2
#define TFT_BL 5 // GPIO5
// 触摸屏引脚配置
#define TOUCH_CS 16 // GPIO16 (触摸片选)
#define TOUCH_IRQ -1 // 不使用中断
// 使用硬件SPI
Arduino_DataBus *bus = new Arduino_ESP8266SPI(TFT_DC, TFT_CS);
Arduino_GFX *gfx = new Arduino_ILI9488_18bit(bus, TFT_RST);
// 触摸屏对象
XPT2046_Touchscreen touch(TOUCH_CS, TOUCH_IRQ);
// 触摸校准参数 (根据实际调整)
const int TS_MINX = 200;
const int TS_MINY = 200;
const int TS_MAXX = 3800;
const int TS_MAXY = 3800;
void setup() {
Serial.begin(115200);
Serial.println("\nILI9488 + MSP3520 Test");
// 显示屏复位
pinMode(TFT_RST, OUTPUT);
digitalWrite(TFT_RST, LOW);
delay(50);
digitalWrite(TFT_RST, HIGH);
delay(150);
// 背光初始化(固定高电平)
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH); // 保持常亮
// 降低SPI速度确保稳定性
if (!gfx->begin(15000000)) { // 15MHz
Serial.println("Display init failed!");
while(1); // 卡死检测
}
Serial.println("Display ready");
// 触摸屏初始化
touch.begin();
touch.setRotation(1); // 根据屏幕方向调整
Serial.println("Touch ready");
// 显示初始界面
gfx->fillScreen(BLACK);
gfx->setTextSize(2, 2);
gfx->setTextColor(WHITE);
gfx->setCursor(60, 140);
gfx->print("TOUCH TEST");
}
void loop() {
// 触摸检测
if (touch.touched()) {
TS_Point p = touch.getPoint();
// 坐标转换 (480x320)
int x = map(p.y, TS_MINY, TS_MAXY, 0, 479);
int y = map(p.x, TS_MINX, TS_MAXX, 319, 0);
Serial.printf("Touch: X=%d, Y=%d, Pressure=%d\n", x, y, p.z);
// 视觉反馈:触摸点
gfx->fillCircle(x, y, 5, RED);
delay(50);
gfx->fillCircle(x, y, 5, BLACK);
}
// 显示帧率计数器
static uint32_t lastUpdate = 0;
static int counter = 0;
if (millis() - lastUpdate > 1000) {
gfx->fillRect(0, 0, 100, 30, BLACK);
gfx->setCursor(10, 10);
gfx->setTextColor(GREEN);
gfx->printf("FPS:%2d", counter);
counter = 0;
lastUpdate = millis();
}
counter++;
}
使用TFT_eSPI库驱动
需要配置TFT_eSPI
- 打开Arduino库文件夹中的
TFT_eSPI目录 - 编辑
User_Setup.h文件 - 确保有以下配置:
#define USER_SETUP_INFO "User_Setup"
#define TFT_DRIVER ILI9488
// ESP8266引脚配置
#define TFT_CS 15 // GPIO15
#define TFT_DC 4 // GPIO4
#define TFT_RST 2 // GPIO2
// 使用SPI
#define TFT_SPI_FREQUENCY 27000000
// 屏幕尺寸
#define TFT_WIDTH 480
#define TFT_HEIGHT 320
// 颜色格式
#define TFT_RGB_ORDER TFT_BGR
// 字体设置
#define LOAD_GLCD
#define LOAD_FONT2
#define LOAD_FONT4
#define LOAD_FONT6
#define LOAD_FONT7
#define LOAD_FONT8
#define LOAD_GFXFF
#include <TFT_eSPI.h> // 包含TFT_eSPI库
#include <SPI.h> // SPI通信库
#include <XPT2046_Touchscreen.h> // MSP3520触摸屏驱动
// 屏幕尺寸定义
#define SCREEN_WIDTH 480
#define SCREEN_HEIGHT 320
// 触摸屏引脚定义
#define TOUCH_CS 16 // GPIO16 (触摸片选)
#define TOUCH_IRQ -1 // 不使用中断
// 创建TFT和触摸对象
TFT_eSPI tft = TFT_eSPI(); // 创建TFT对象
XPT2046_Touchscreen touch(TOUCH_CS, TOUCH_IRQ); // 创建触摸对象
// 触摸校准参数 (根据实际情况调整)
const int TS_MINX = 250;
const int TS_MINY = 280;
const int TS_MAXX = 3750;
const int TS_MAXY = 3780;
// 颜色定义
#define BACKGROUND_COLOR 0x18E3 // 深蓝色背景
#define UI_COLOR 0x07FF // 青色UI元素
#define TEXT_COLOR 0xFFFF // 白色文本
#define BUTTON_COLOR 0xF800 // 红色按钮
#define BUTTON_TEXT 0xFFFF // 白色按钮文本
// 按钮结构
struct Button {
int x, y, width, height;
String label;
};
// 创建按钮数组
Button buttons[] = {
{50, 120, 120, 50, "Button 1"},
{190, 120, 120, 50, "Button 2"},
{330, 120, 120, 50, "Button 3"}
};
const int buttonCount = sizeof(buttons) / sizeof(Button);
void setup() {
Serial.begin(115200);
Serial.println("\nILI9488 + MSP3520 with TFT_eSPI");
// 初始化显示屏
tft.init();
tft.setRotation(1); // 设置屏幕方向 (0-3)
tft.fillScreen(TFT_BLACK);
// 初始化背光 (如果连接了背光引脚)
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH); // 开启背光
// 初始化触摸屏
touch.begin();
touch.setRotation(1); // 设置触摸方向与屏幕一致
// 创建UI界面
createUI();
Serial.println("Setup complete");
}
void createUI() {
// 绘制背景
tft.fillScreen(BACKGROUND_COLOR);
// 绘制标题
tft.setTextColor(TEXT_COLOR, BACKGROUND_COLOR);
tft.setTextSize(3);
tft.setTextDatum(TC_DATUM); // 顶部居中
tft.drawString("TFT_eSPI Demo", SCREEN_WIDTH / 2, 20);
// 绘制子标题
tft.setTextSize(2);
tft.drawString("ILI9488 + MSP3520", SCREEN_WIDTH / 2, 60);
// 绘制按钮
for (int i = 0; i < buttonCount; i++) {
drawButton(buttons[i]);
}
// 绘制触摸状态区域
tft.fillRoundRect(50, 200, SCREEN_WIDTH - 100, 80, 10, TFT_DARKGREY);
tft.setTextColor(TEXT_COLOR, TFT_DARKGREY);
tft.setTextSize(2);
tft.drawString("Touch Status", SCREEN_WIDTH / 2, 210);
tft.setTextSize(1);
tft.drawString("Touch screen to see coordinates", SCREEN_WIDTH / 2, 240);
}
void drawButton(Button btn) {
// 绘制按钮背景
tft.fillRoundRect(btn.x, btn.y, btn.width, btn.height, 10, BUTTON_COLOR);
// 绘制按钮边框
tft.drawRoundRect(btn.x, btn.y, btn.width, btn.height, 10, TFT_WHITE);
// 绘制按钮文本
tft.setTextColor(BUTTON_TEXT, BUTTON_COLOR);
tft.setTextSize(2);
tft.setTextDatum(MC_DATUM); // 居中
tft.drawString(btn.label, btn.x + btn.width / 2, btn.y + btn.height / 2);
}
void processTouch() {
static int lastX = -1, lastY = -1;
if (touch.touched()) {
TS_Point p = touch.getPoint();
// 映射触摸坐标到屏幕坐标
int x = map(p.y, TS_MINY, TS_MAXY, 0, SCREEN_WIDTH - 1);
int y = map(p.x, TS_MINX, TS_MAXX, SCREEN_HEIGHT - 1, 0);
// 限制坐标在屏幕范围内
x = constrain(x, 0, SCREEN_WIDTH - 1);
y = constrain(y, 0, SCREEN_HEIGHT - 1);
// 显示触摸坐标
tft.fillRect(60, 250, 360, 20, TFT_DARKGREY);
tft.setTextColor(TFT_YELLOW, TFT_DARKGREY);
tft.setTextSize(2);
tft.drawString("X: " + String(x) + " Y: " + String(y), SCREEN_WIDTH / 2, 250);
// 检查按钮点击
for (int i = 0; i < buttonCount; i++) {
if (isPointInButton(x, y, buttons[i])) {
buttonPressed(i);
break;
}
}
// 绘制触摸点
if (lastX != -1 && lastY != -1) {
tft.fillCircle(lastX, lastY, 4, BACKGROUND_COLOR);
}
tft.fillCircle(x, y, 4, TFT_YELLOW);
lastX = x;
lastY = y;
}
else if (lastX != -1) {
// 清除触摸点
tft.fillCircle(lastX, lastY, 4, BACKGROUND_COLOR);
lastX = lastY = -1;
}
}
bool isPointInButton(int x, int y, Button btn) {
return (x >= btn.x && x < (btn.x + btn.width) &&
y >= btn.y && y < (btn.y + btn.height));
}
void buttonPressed(int index) {
// 视觉反馈:按钮按下效果
Button btn = buttons[index];
// 绘制按下的按钮
tft.fillRoundRect(btn.x, btn.y, btn.width, btn.height, 10, TFT_DARKGREEN);
tft.drawRoundRect(btn.x, btn.y, btn.width, btn.height, 10, TFT_WHITE);
tft.setTextColor(TFT_WHITE, TFT_DARKGREEN);
tft.setTextSize(2);
tft.drawString(btn.label, btn.x + btn.width / 2, btn.y + btn.height / 2);
// 在串口显示按下的按钮
Serial.println("Button pressed: " + btn.label);
delay(100); // 短暂显示按下的状态
// 恢复按钮原始状态
drawButton(btn);
}
void updateCounter() {
static uint32_t lastUpdate = 0;
static int counter = 0;
if (millis() - lastUpdate > 1000) {
// 更新计数器显示
tft.fillRect(SCREEN_WIDTH - 100, 10, 90, 25, BACKGROUND_COLOR);
tft.setTextColor(TEXT_COLOR, BACKGROUND_COLOR);
tft.setTextSize(2);
tft.setTextDatum(TR_DATUM); // 右上角对齐
tft.drawString("Time: " + String(counter) + "s", SCREEN_WIDTH - 10, 10);
counter++;
lastUpdate = millis();
}
}
void loop() {
processTouch(); // 处理触摸事件
updateCounter(); // 更新计数器
delay(10); // 短暂延迟
}