Touch 驱动

基于 lisa_device 框架的 Touch 设备驱动,为 ARCS 平台提供统一的触摸屏接口。

功能特性

  • 多芯片支持: 支持 CST328、AXS15231B、FT5336、CST816D、ST77921、BL6133 等触摸芯片

  • 总线接口: I2C 接口通信,自动配置 I2C 总线参数

  • 工作模式: 支持轮询模式和中断模式

  • 中断优化: 中断模式下使用驱动内部任务处理 I2C 读取,回调在任务上下文中安全执行

  • 线程安全: 内部使用互斥锁保护并发访问,自动判断线程和中断上下文

  • 灵活配置: 通过 Kconfig 选择启用的芯片,节省资源

配置选项

prj.conf 中启用驱动并选择芯片:

CONFIG_LISA_TOUCH_DEVICE=y
CONFIG_LISA_TOUCH_ARCS_CST328=y       # 启用 CST328 芯片
# CONFIG_LISA_TOUCH_ARCS_AXS15231B=y  # 启用 AXS15231B 芯片
# CONFIG_LISA_TOUCH_ARCS_FT5336=y     # 启用 FT5336 芯片
# CONFIG_LISA_TOUCH_ARCS_CST816D=y    # 启用 CST816D 芯片
# CONFIG_LISA_TOUCH_ARCS_ST77921=y    # 启用 ST77921 芯片
# CONFIG_LISA_TOUCH_ARCS_BL6133=y     # 启用 BL6133 芯片

CONFIG_LISA_I2C=y                     # 依赖 I2C 驱动
CONFIG_LISA_GPIO_DEVICE=y             # 依赖 GPIO 驱动

根据需要选择启用一个或多个触摸芯片。每个芯片注册为独立设备,可同时使用。

支持的芯片

芯片型号

设备名称

I2C地址

分辨率

状态

CST328

touch_cst328

0x1D

240x320

✅ 已验证

AXS15231B

touch_axs15231b

0x3B

390x390

⚠️ 待验证

FT5336

touch_ft5336

0x38

480x272

⚠️ 待验证

CST816D

touch_cst816d

0x15

240x240

⚠️ 待验证

ST77921

touch_st77921

0x55

480x480

⚠️ 待验证

BL6133

touch_bl6133

0x2C

320x386

⚠️ 待验证

API 接口

总线配置

int lisa_touch_attach_bus(lisa_device_t *dev, const lisa_touch_bus_config_t *bus_config);

配置触摸设备的总线接口(I2C)。I2C 总线将自动配置为标准速度(100kHz)。

触摸控制

int lisa_touch_enable(lisa_device_t *dev);
int lisa_touch_disable(lisa_device_t *dev);
int lisa_touch_get_capabilities(lisa_device_t *dev, lisa_touch_capabilities_t *caps);

启用/禁用触摸设备,获取设备能力信息(分辨率、最大触摸点数等)。

事件读取

int lisa_touch_read_event(lisa_device_t *dev, lisa_touch_event_t *event);

读取触摸事件(按下、释放、坐标等)。

事件类型说明:

  • LISA_TOUCH_EVENT_NONE: 无事件

  • LISA_TOUCH_EVENT_PRESS: 按下事件(检测到触摸时返回,包含坐标信息)

  • LISA_TOUCH_EVENT_RELEASE: 释放事件(检测到释放时返回)

行为说明:

  • 检测到触摸时返回 PRESS 事件,包含当前坐标

  • 检测到释放时返回 RELEASE 事件

  • 轮询模式下,每次读取时如果触摸状态为按下,都会返回 PRESS 事件(坐标可能更新)

返回值:

  • LISA_DEVICE_OK (0): 成功读取事件

  • LISA_DEVICE_ERR_INVALID: 参数无效

  • LISA_DEVICE_ERR_NOT_READY: 设备未启用或 I2C 未就绪

  • LISA_DEVICE_ERR_NOT_SUPPORT: 当前处于中断模式,不支持轮询读取

  • LISA_DEVICE_ERR_IO: 读取失败(无有效触摸数据)

重要提示:

  • ⚠️ 中断模式下禁止调用此函数:如果已通过 lisa_touch_set_int_mode(INTERRUPT) 设置为中断模式,再调用 lisa_touch_read_event() 将返回 LISA_DEVICE_ERR_NOT_SUPPORT

  • 这是为了避免轮询读取与中断任务产生资源竞争,导致状态混乱

  • 中断模式下请使用回调函数接收触摸事件

中断模式

int lisa_touch_set_callback(lisa_device_t *dev, lisa_touch_callback_t callback, void *user_data);
int lisa_touch_set_int_mode(lisa_device_t *dev, lisa_touch_int_mode_t mode);

设置触摸中断回调函数和中断模式(中断模式/轮询模式)。

使用方法

基本步骤

  1. 配置引脚: 将对应的 GPIO 引脚配置为 I2C 和 GPIO 功能

  2. 获取设备: 通过 lisa_device_get() 获取触摸设备、I2C 设备和 GPIO 设备

  3. 配置总线: 调用 lisa_touch_attach_bus() 配置 I2C 总线

  4. 设置模式: 调用 lisa_touch_set_int_mode() 设置工作模式(轮询/中断)

  5. 启用设备: 调用 lisa_touch_enable() 启用设备

  6. 读取事件: 调用 lisa_touch_read_event() 读取触摸事件(轮询模式)或设置回调(中断模式)

轮询模式

#include "lisa_touch.h"
#include "lisa_gpio.h"
#include "IOMuxManager.h"
#include "board.h"
#include "pinmux.h"

// 1. 配置 I2C 和 GPIO 引脚(通过 pinmux 重定向或直接配置)
#ifdef CONFIG_BOARD_ARCS_EVB
void lisa_i2c0_pinmux()
{
    IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 22, 8);  // SDA
    IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 23, 8);  // SCL
}

void lisa_gpioa_pinmux()
{
    IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 25, 0);  // RST
    IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 24, 0);  // INT
}
#endif

// 2. 获取设备
lisa_device_t *touch = lisa_device_get("touch_cst328");
lisa_device_t *i2c_dev = lisa_device_get("i2c0");
lisa_device_t *gpio_dev = lisa_device_get("gpioa");

if (!touch || !i2c_dev || !gpio_dev) {
    return -1;
}

// 3. 配置总线
lisa_touch_bus_config_t bus_config = {
    .bus_type = LISA_TOUCH_BUS_I2C,
    .config = {
        .i2c = {
            .i2c_dev = i2c_dev,
            .int_gpio = gpio_dev,
            .int_pin = 24,
            .rst_gpio = gpio_dev,
            .rst_pin = 25,
        }
    }
};
lisa_touch_attach_bus(touch, &bus_config);

// 4. 设置轮询模式(可选,默认就是轮询模式)
lisa_touch_set_int_mode(touch, LISA_TOUCH_INT_MODE_POLLING);

// 5. 启用设备
lisa_touch_enable(touch);

// 6. 获取设备能力
lisa_touch_capabilities_t caps;
lisa_touch_get_capabilities(touch, &caps);
printf("Touch: max_x=%d, max_y=%d, max_points=%d\n",
       caps.max_x, caps.max_y, caps.max_points);

// 7. 循环读取触摸事件
while (1) {
    lisa_touch_event_t event;
    int ret = lisa_touch_read_event(touch, &event);
    
    if (ret == LISA_DEVICE_OK) {
        switch (event.type) {
            case LISA_TOUCH_EVENT_PRESS:
                // 按下事件
                if (event.point_count > 0) {
                    printf("Touch: x=%4d, y=%4d, type=PRESS\n",
                           event.points[0].x, event.points[0].y);
                }
                break;
            case LISA_TOUCH_EVENT_RELEASE:
                printf("Touch: RELEASE\n");
                break;
        }
    }
    
    vTaskDelay(pdMS_TO_TICKS(50));  // 50ms 采样间隔
}

中断模式

// 触摸事件回调函数(在任务上下文中调用,由驱动内部任务触发)
void touch_event_callback(const lisa_touch_event_t *event, void *user_data)
{
    (void)user_data;
    
    // 此回调在驱动内部的任务上下文中调用,可以安全使用 printf
    switch (event->type) {
        case LISA_TOUCH_EVENT_PRESS:
            // 按下事件
            if (event->point_count > 0) {
                printf("Touch: x=%4d, y=%4d, type=PRESS\n",
                       event->points[0].x, event->points[0].y);
            }
            break;
        case LISA_TOUCH_EVENT_RELEASE:
            // 释放事件
            printf("Touch: type=RELEASE\n");
            break;
    }
}

int main(void)
{
    // ... 配置引脚和总线(同上)...
    
    // 设置触摸事件回调函数
    lisa_touch_set_callback(touch, touch_event_callback, NULL);
    
    // 设置中断模式
    lisa_touch_set_int_mode(touch, LISA_TOUCH_INT_MODE_INTERRUPT);
    
    // 启用设备
    lisa_touch_enable(touch);

    // 主循环:触摸事件通过回调自动处理
    while (1) {
        vTaskDelay(pdMS_TO_TICKS(1000));
        printf("System running, waiting for touch events...\n");
    }
}

中断模式说明:

  • 驱动内部创建专用任务处理 I2C 读取

  • GPIO 中断回调只发送任务通知,不执行耗时操作

  • 用户回调在任务上下文中调用,可以安全使用 printfmalloc 等操作

  • 回调直接收到完整的触摸数据(包括坐标),无需再次读取

  • ⚠️ 中断模式下不能调用 lisa_touch_read_event(),会返回 LISA_DEVICE_ERR_NOT_SUPPORT 错误

模式切换

轮询模式和中断模式可以动态切换,但同一时间只能使用一种模式:

// 从轮询模式切换到中断模式
lisa_touch_set_callback(touch, touch_event_callback, NULL);  // 先设置回调
lisa_touch_set_int_mode(touch, LISA_TOUCH_INT_MODE_INTERRUPT);  // 切换到中断模式
// 此后不能再调用 lisa_touch_read_event()

// 从中断模式切换回轮询模式
lisa_touch_set_int_mode(touch, LISA_TOUCH_INT_MODE_POLLING);  // 切换到轮询模式
// 此后可以调用 lisa_touch_read_event(),回调不再触发

重要提示:

  • 中断模式下禁止调用 lisa_touch_read_event(),避免资源竞争

  • 轮询模式下回调函数不会被调用(即使已设置)

  • 切换模式前无需禁用设备,可以动态切换

硬件配置

引脚复用配置

Touch 驱动依赖 I2C 和 GPIO 驱动,引脚复用配置由 I2C 和 GPIO 驱动在初始化时自动完成。

配置位置:

  • I2C 引脚: boards/<板型名>/pinmux.c 中的 lisa_i2c0_pinmux()lisa_i2c1_pinmux() 函数

  • GPIO 引脚: boards/<板型名>/pinmux.c 中的 lisa_gpioa_pinmux()lisa_gpiob_pinmux() 函数

  • 调用时机: I2C 和 GPIO 设备初始化时自动调用

示例 (参考 boards/arcs_evb/pinmux.c):

void lisa_i2c0_pinmux()
{
    /* I2C0: PA22=SDA, PA23=SCL, 功能码 8 */
    IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 22, 8);
    IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 23, 8);
}

void lisa_gpioa_pinmux()
{
    /* GPIO: PA25=RST, PA24=INT, 功能码 0 */
    IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 25, 0);
    IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 24, 0);
}

注意:

  • 该函数由板型相关代码实现,不同板型的引脚配置可能不同

  • 如需自定义引脚配置,可在 sample 中重写 pinmux 函数(参考 samples/drivers/devices/lisa_touch/interrupt_mode/src/main.c

  • 触摸驱动需要以下引脚:

    • I2C SDA/SCL:用于 I2C 通信

    • INT:触摸中断引脚(中断模式需要)

    • RST:芯片复位引脚

芯片特性

不同芯片的 I2C 地址、分辨率、触发方式可能不同,请参考具体芯片手册和”支持的芯片”表格。

工作模式对比

特性

轮询模式

中断模式

响应速度

取决于轮询间隔(通常 50ms)

立即响应(< 1ms)

CPU 占用

高(持续轮询)

低(事件驱动)

功耗

实现复杂度

简单

中等

适用场景

简单应用、对响应时间不敏感

需要快速响应、低功耗应用

回调上下文

任务上下文(安全)

任务上下文(安全)

注意事项

  1. I2C 自动配置: lisa_touch_attach_bus() 会自动配置 I2C 总线为标准速度(100kHz),无需手动调用 lisa_i2c_configure()

  2. 引脚配置: 使用前需配置对应的 GPIO 引脚,驱动初始化时会自动调用 pinmux 函数,或通过 pinmux 重定向自定义引脚

  3. 设备依赖: 需要确保 I2C 和 GPIO 设备已就绪(通过 lisa_device_ready() 检查)

  4. 中断回调: 中断模式下,用户回调在驱动内部任务上下文中调用,可以安全使用 printfmalloc 等操作

  5. 线程安全: 驱动内部已实现线程保护,可在多线程环境中使用

  6. 芯片特性: 不同芯片的坐标系、分辨率、触发方式可能不同,请参考具体芯片手册

  7. 设备选择: 使用前需在 prj.conf 中启用对应的触摸芯片和依赖驱动(I2C、GPIO)

  8. 多芯片使用: 每个芯片注册为独立设备,可同时使用多个触摸芯片

文件说明

  • lisa_touch.h - 驱动头文件,包含所有 API 和类型定义

  • lisa_touch_cst328.c - CST328 芯片驱动实现

  • lisa_touch_axs15231b.c - AXS15231B 芯片驱动实现

  • lisa_touch_ft5336.c - FT5336 芯片驱动实现

  • lisa_touch_cst816d.c - CST816D 芯片驱动实现

  • lisa_touch_st77921.c - ST77921 芯片驱动实现

  • lisa_touch_bl6133.c - BL6133 芯片驱动实现

  • Kconfig - 主配置选项

  • Kconfig.arcs.* - 各芯片配置选项

  • CMakeLists.txt - 构建配置

  • README.md - 驱动使用说明