3. 触摸驱动集成
任务目标
在ESP32与LVGL智能家居面板中,集成XPT2046电阻触摸驱动,完成触摸坐标校准,并实现点击事件响应,使LVGL界面能够通过触摸进行交互。
硬件与依赖
- ESP32开发板 + XPT2046触摸芯片(通常与ILI9341等SPI屏幕集成)
- LVGL v8.x(已初始化显示驱动)
- Arduino平台库:
XPT2046_Touchscreen(或等效驱动库)
关键实现
核心逻辑分为三部分:触摸芯片初始化、坐标校准映射、LVGL输入设备注册。校准采用两点线性映射,将触摸原始值转换为屏幕像素坐标。
#include <XPT2046_Touchscreen.h>
#include <lvgl.h>
// --- XPT2046引脚配置(根据实际接线修改)---
#define TOUCH_CS 5
#define TOUCH_IRQ 36
XPT2046_Touchscreen ts(TOUCH_CS, TOUCH_IRQ);
// --- 校准参数(两点校准法)---
// 触摸原始值范围(通过串口打印获取)
#define TOUCH_MIN_X 200
#define TOUCH_MAX_X 3800
#define TOUCH_MIN_Y 200
#define TOUCH_MAX_Y 3800
// 屏幕分辨率(与显示驱动一致)
#define SCREEN_W 320
#define SCREEN_H 240
// --- LVGL触摸读取回调 ---
void touch_read_cb(lv_indev_drv_t *drv, lv_indev_data_t *data) {
if (!ts.touched()) {
data->state = LV_INDEV_STATE_REL;
return;
}
TS_Point p = ts.getPoint();
// 坐标映射:触摸原始值 → 屏幕像素坐标
int16_t x = map(p.x, TOUCH_MIN_X, TOUCH_MAX_X, 0, SCREEN_W - 1);
int16_t y = map(p.y, TOUCH_MIN_Y, TOUCH_MAX_Y, 0, SCREEN_H - 1);
// 边界裁剪
x = constrain(x, 0, SCREEN_W - 1);
y = constrain(y, 0, SCREEN_H - 1);
data->point.x = x;
data->point.y = y;
data->state = LV_INDEV_STATE_PR;
}
// --- 触摸初始化(在lv_init()之后调用)---
void touch_init() {
ts.begin();
ts.setRotation(1); // 与屏幕旋转方向一致
static lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = touch_read_cb;
lv_indev_drv_register(&indev_drv);
}
// --- 使用示例:在setup()中调用 ---
void setup() {
Serial.begin(115200);
lv_init();
// ... 显示驱动初始化 ...
touch_init();
// 创建一个可点击的按钮用于验证
lv_obj_t *btn = lv_btn_create(lv_scr_act());
lv_obj_set_size(btn, 120, 50);
lv_obj_center(btn);
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL);
}
void btn_event_cb(lv_event_t *e) {
Serial.println("按钮被点击!");
}
校准方法
- 先运行程序,在串口监视器中观察
ts.getPoint()返回的原始值。 - 触摸屏幕四个角落,记录X和Y的最小/最大值。
- 将记录值填入
TOUCH_MIN_X/MAX_X/MIN_Y/MAX_Y宏定义中。 - 若触摸方向与屏幕显示方向不一致,调整
ts.setRotation()参数(0~3)。
验证方法
- 编译并烧录程序,打开串口监视器(波特率115200)。
- 用手指或触控笔点击屏幕中央的按钮。
- 通过条件:按钮视觉上呈现按下效果,且串口输出“按钮被点击!”即表示触摸驱动集成成功。
- 若点击位置与按钮位置偏移,重新校准触摸范围或调整旋转方向。
常见问题
- 无触摸响应:检查CS和IRQ引脚接线是否正确,确认
ts.begin()返回true。 - 坐标轴反向:交换对应轴的MIN/MAX值,或调整
setRotation()。 - 触摸漂移:确保触摸屏与屏幕贴合紧密,重新执行两点校准。