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("按钮被点击!");
}

校准方法

  1. 先运行程序,在串口监视器中观察ts.getPoint()返回的原始值。
  2. 触摸屏幕四个角落,记录X和Y的最小/最大值。
  3. 将记录值填入TOUCH_MIN_X/MAX_X/MIN_Y/MAX_Y宏定义中。
  4. 若触摸方向与屏幕显示方向不一致,调整ts.setRotation()参数(0~3)。

验证方法

  • 编译并烧录程序,打开串口监视器(波特率115200)。
  • 用手指或触控笔点击屏幕中央的按钮。
  • 通过条件:按钮视觉上呈现按下效果,且串口输出“按钮被点击!”即表示触摸驱动集成成功。
  • 若点击位置与按钮位置偏移,重新校准触摸范围或调整旋转方向。

常见问题

  • 无触摸响应:检查CS和IRQ引脚接线是否正确,确认ts.begin()返回true。
  • 坐标轴反向:交换对应轴的MIN/MAX值,或调整setRotation()。
  • 触摸漂移:确保触摸屏与屏幕贴合紧密,重新执行两点校准。