ESP32-CYD(2432S028)液晶2.8寸屏开发板使用ESP32-WROOM-32模块作为主控,主控是一款双核MCU,集成了Wi-Fi和蓝牙功能,主频可达240MHz,具有520KB的SRAM、448KB的ROM,闪存容量为4MB+4MB,显示分辨率为240x320,采用电阻式触控式屏幕。该模块包括LCD显示器、背光控制电路、触控式屏幕控制电路、扬声器驱动电路、光敏电路和RGB LED控制电路。支持TF卡界面、序列界面、温湿度感测器界面(DHT11界面)和保留的IO口界面,该模块支持在Arduino IDE、ESP IDE、MicroPython和Mixly中进行开发。
安装TFT_eSPI、XPT2046_Touchscreen和LVGL库
网址:
TFT_eSPI库的网址:https://github.com/Bodmer/TFT_eSPI
XPT2046_Touchscreen库的网址: https://github.com/PaulStoffregen/XPT2046_Touchscreen
通杀需要根据不同开发板与TFT屏幕正确配置User_Setup.h和lv_conf.h文件。
LVGL (Light and Versatile Graphics Library) 是一个免费的开源图形库,可为需要图形用户界面 (GUI) 的微控制器项目提供各种易于使用的图形元素。
以下是它的一些主要功能:
块:按钮、图表、列表、滑块、图像等......
具有动画、抗锯齿、不透明度、平滑滚动的高级图形;
各种输入设备,如触摸板、鼠标、键盘、编码器等......
UTF-8 编码的多语言支持;
多显示器支持,即同时使用多个 TFT 单色显示器;
具有类似 CSS 样式的完全可定制的图形元素;
独立于硬件:与任何微控制器或显示器一起使用;
可扩展:能够在很少的内存下运行(64 kB 闪存,16 kB RAM);
用 C 语言编写,以实现最大的兼容性(C++ 兼容)并绑定到 MicroPython。
它的文档中还有大量可供您使用的代码示例:文本、按钮、滑块、输入字段、键盘、自定义样式、图像、弧线、线条、动画、菜单、选项卡、布局、表格等等......
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百三十八:ESP32开发板WiFi蓝牙2.8寸240*320智能液晶显示屏带触摸屏TFT模块
项目实验之十九:ESP32 CYD液晶2.8寸开发板尝试LVGL(轻量级和多功能图形库)
实验开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百三十八:ESP32开发板WiFi蓝牙2.8寸240*320智能液晶显示屏带触摸屏TFT模块
项目实验之十九:ESP32 CYD液晶2.8寸开发板尝试LVGL(轻量级和多功能图形库)
*/
#include <lvgl.h> // 引入LVGL图形库
#include <TFT_eSPI.h> // 引入TFT_eSPI库,用于驱动TFT显示屏
#include <XPT2046_Touchscreen.h> // 引入XPT2046触摸屏库
// 触摸屏引脚定义
#define XPT2046_IRQ 36 // T_IRQ引脚
#define XPT2046_MOSI 32 // T_DIN引脚
#define XPT2046_MISO 39 // T_OUT引脚
#define XPT2046_CLK 25 // T_CLK引脚
#define XPT2046_CS 33 // T_CS引脚
SPIClass touchscreenSPI = SPIClass(VSPI); // 实例化一个SPI类,用于触摸屏通信
XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ); // 创建触摸屏对象
#define SCREEN_WIDTH 240 // 屏幕宽度定义
#define SCREEN_HEIGHT 320 // 屏幕高度定义
// 触摸屏坐标:(x, y) 和压力(z)
int x, y, z;
#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8)) // 绘图缓冲区大小定义
uint32_t draw_buf[DRAW_BUF_SIZE / 4]; // 绘图缓冲区
// 如果启用了日志记录,它将告知用户库中发生了什么
void log_print(lv_log_level_t level, const char* buf) {
LV_UNUSED(level); // LVGL中未使用的宏
Serial.println(buf); // 打印日志信息
Serial.flush(); // 清空串口缓冲区
}
// 获取触摸屏数据
void touchscreen_read(lv_indev_t* indev, lv_indev_data_t* data) {
// 检查触摸屏是否被触摸,并打印X, Y和压力(Z)
if (touchscreen.tirqTouched() && touchscreen.touched()) {
// 获取触摸屏坐标点
TS_Point p = touchscreen.getPoint();
// 使用map函数校准触摸屏坐标点到正确的宽度和高度
x = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
y = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
z = p.z;
data->state = LV_INDEV_STATE_PRESSED; // 设置状态为按下
// 设置坐标点
data->point.x = x;
data->point.y = y;
// 在串口监视器上打印触摸屏信息关于X, Y和压力(Z)
/* Serial.print("X = ");
Serial.print(x);
Serial.print(" | Y = ");
Serial.print(y);
Serial.print(" | Pressure = ");
Serial.print(z);
Serial.println();*/
} else {
data->state = LV_INDEV_STATE_RELEASED; // 设置状态为释放
}
}
int btn1_count = 0; // 按钮1的计数器
// 当按钮1被点击时触发的回调函数
static void event_handler_btn1(lv_event_t* e) {
lv_event_code_t code = lv_event_get_code(e); // 获取事件代码
if (code == LV_EVENT_CLICKED) {
btn1_count++; // 按钮计数器加1
LV_LOG_USER("Button clicked %d", (int)btn1_count); // 用户日志记录按钮点击次数
}
}
// 当按钮2被点击/切换时触发的回调函数
static void event_handler_btn2(lv_event_t* e) {
lv_event_code_t code = lv_event_get_code(e); // 获取事件代码
lv_obj_t* obj = (lv_obj_t*)lv_event_get_target(e); // 获取事件目标对象
if (code == LV_EVENT_VALUE_CHANGED) {
LV_UNUSED(obj); // LVGL中未使用的宏
LV_LOG_USER("Toggled %s", lv_obj_has_state(obj, LV_STATE_CHECKED) ? "on" : "off"); // 用户日志记录开关状态
}
}
static lv_obj_t* slider_label; // 滑块标签对象
// 回调函数,用于在TFT显示屏和串口监视器上打印当前滑块值,用于调试目的
static void slider_event_callback(lv_event_t* e) {
lv_obj_t* slider = (lv_obj_t*)lv_event_get_target(e); // 获取事件目标对象(滑块)
char buf[8]; // 缓冲区
lv_snprintf(buf, sizeof(buf), "%d%%", (int)lv_slider_get_value(slider)); // 获取滑块值并格式化为字符串
lv_label_set_text(slider_label, buf); // 设置滑块标签文本
lv_obj_align_to(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); // 将滑块标签对齐到滑块下方
LV_LOG_USER("Slider changed to %d%%", (int)lv_slider_get_value(slider)); // 用户日志记录滑块值
}
void lv_create_main_gui(void) {
// 创建一个文本标签,居中显示在顶部("Hello, world!")
lv_obj_t* text_label = lv_label_create(lv_screen_active());
lv_label_set_long_mode(text_label, LV_LABEL_LONG_WRAP); // 自动换行
lv_label_set_text(text_label, "Hello, world!");
lv_obj_set_width(text_label, 150); // 设置较小的宽度以使文本换行
lv_obj_set_style_text_align(text_label, LV_TEXT_ALIGN_CENTER, 0);
lv_obj_align(text_label, LV_ALIGN_CENTER, 0, -90);
lv_obj_t* btn_label;
// 创建一个按钮(btn1)
lv_obj_t* btn1 = lv_button_create(lv_screen_active());
lv_obj_add_event_cb(btn1, event_handler_btn1, LV_EVENT_ALL, NULL);
lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -50);
lv_obj_remove_flag(btn1, LV_OBJ_FLAG_PRESS_LOCK);
btn_label = lv_label_create(btn1);
lv_label_set_text(btn_label, "Button");
lv_obj_center(btn_label);
// 创建一个切换按钮(btn2)
lv_obj_t* btn2 = lv_button_create(lv_screen_active());
lv_obj_add_event_cb(btn2, event_handler_btn2, LV_EVENT_ALL, NULL);
lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 10);
lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
lv_obj_set_height(btn2, LV_SIZE_CONTENT);
btn_label = lv_label_create(btn2);
lv_label_set_text(btn_label, "Toggle");
lv_obj_center(btn_label);
// 在TFT显示屏底部居中创建一个滑块
lv_obj_t* slider = lv_slider_create(lv_screen_active());
lv_obj_align(slider, LV_ALIGN_CENTER, 0, 60);
lv_obj_add_event_cb(slider, slider_event_callback, LV_EVENT_VALUE_CHANGED, NULL);
lv_slider_set_range(slider, 0, 100);
lv_obj_set_style_anim_duration(slider, 2000, 0);
// 在滑块下方创建一个标签以显示当前滑块值
slider_label = lv_label_create(lv_screen_active());
lv_label_set_text(slider_label, "0%");
lv_obj_align_to(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
}
void setup() {
String LVGL_Arduino = String("LVGL Library Version: ") + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
Serial.begin(115200); // 初始化串口通信,波特率为115200
Serial.println(LVGL_Arduino); // 打印LVGL库版本信息
// 启动LVGL
lv_init();
// 注册打印函数用于调试
lv_log_register_print_cb(log_print);
// 启动触摸屏的SPI并初始化触摸屏
touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
touchscreen.begin(touchscreenSPI);
// 设置触摸屏旋转为横屏模式
// 注意:在某些显示屏上,触摸屏可能是倒置的,因此可能需要将旋转设置为0:touchscreen.setRotation(0);
touchscreen.setRotation(2);
// 创建一个显示对象
lv_display_t* disp;
// 使用TFT_eSPI库初始化TFT显示屏
disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);
// 初始化一个LVGL输入设备对象(触摸屏)
lv_indev_t* indev = lv_indev_create();
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
// 设置回调函数以读取触摸屏输入
lv_indev_set_read_cb(indev, touchscreen_read); // 注册触摸屏读取回调函数
// 绘制GUI(文本、按钮和滑块)
lv_create_main_gui();
}
void loop() {
lv_task_handler(); // 让GUI执行其任务
lv_tick_inc(5); // 告诉LVGL已经过去了多少时间
delay(5); // 让这段时间过去
}
代码解读
这段代码是一个用于Arduino的示例,它结合了LVGL图形库和TFT_eSPI库以及XPT2046触摸屏库,用于在TFT显示屏上创建一个简单的图形用户界面(GUI)。下面是代码的主要功能和组件的解释:
1;包含库:
lvgl.h:LVGL图形库的头文件。
TFT_eSPI.h:用于驱动TFT显示屏的TFT_eSPI库。
XPT2046_Touchscreen.h:用于驱动XPT2046触摸屏的库。
2、触摸屏引脚定义:
定义了连接XPT2046触摸屏的Arduino引脚。
3、SPI类实例化:
实例化了一个SPI类touchscreenSPI,用于与触摸屏通信。
4、触摸屏对象:
创建了一个XPT2046_Touchscreen对象touchscreen,用于管理触摸屏。
5、屏幕和缓冲区定义:
定义了屏幕的宽度和高度。
定义了一个缓冲区draw_buf,用于LVGL的绘图操作。
6、日志打印函数:
log_print函数用于将LVGL的日志信息打印到串口。
7、触摸屏读取函数:
touchscreen_read函数用于读取触摸屏的数据,并将其转换为LVGL可以理解的坐标。
8、按钮和滑块事件处理函数:
event_handler_btn1、event_handler_btn2和slider_event_callback函数分别用于处理按钮点击、切换和滑块值变化的事件。
9、GUI创建函数:
lv_create_main_gui函数用于创建GUI界面,包括文本标签、按钮和滑块。
10、setup函数:
初始化串口通信。
初始化LVGL库。
初始化触摸屏。
创建显示对象和输入设备对象。
调用lv_create_main_gui函数来绘制GUI。
11、loop函数:
包含LVGL的任务处理和时间增量,以保持GUI的响应。
这段代码展示了如何使用LVGL在TFT显示屏上创建一个基本的GUI,包括文本显示、按钮和滑块,并通过触摸屏进行交互。
实验串口返回情况
实验场景图
评论