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 |
|
0x1D |
240x320 |
✅ 已验证 |
AXS15231B |
|
0x3B |
390x390 |
⚠️ 待验证 |
FT5336 |
|
0x38 |
480x272 |
⚠️ 待验证 |
CST816D |
|
0x15 |
240x240 |
⚠️ 待验证 |
ST77921 |
|
0x55 |
480x480 |
⚠️ 待验证 |
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);
设置触摸中断回调函数和中断模式(中断模式/轮询模式)。
使用方法
基本步骤
配置引脚: 将对应的 GPIO 引脚配置为 I2C 和 GPIO 功能
获取设备: 通过
lisa_device_get()获取触摸设备、I2C 设备和 GPIO 设备配置总线: 调用
lisa_touch_attach_bus()配置 I2C 总线设置模式: 调用
lisa_touch_set_int_mode()设置工作模式(轮询/中断)启用设备: 调用
lisa_touch_enable()启用设备读取事件: 调用
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 中断回调只发送任务通知,不执行耗时操作
用户回调在任务上下文中调用,可以安全使用
printf、malloc等操作回调直接收到完整的触摸数据(包括坐标),无需再次读取
⚠️ 中断模式下不能调用
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 占用 |
高(持续轮询) |
低(事件驱动) |
功耗 |
高 |
低 |
实现复杂度 |
简单 |
中等 |
适用场景 |
简单应用、对响应时间不敏感 |
需要快速响应、低功耗应用 |
回调上下文 |
任务上下文(安全) |
任务上下文(安全) |
注意事项
I2C 自动配置:
lisa_touch_attach_bus()会自动配置 I2C 总线为标准速度(100kHz),无需手动调用lisa_i2c_configure()引脚配置: 使用前需配置对应的 GPIO 引脚,驱动初始化时会自动调用 pinmux 函数,或通过 pinmux 重定向自定义引脚
设备依赖: 需要确保 I2C 和 GPIO 设备已就绪(通过
lisa_device_ready()检查)中断回调: 中断模式下,用户回调在驱动内部任务上下文中调用,可以安全使用
printf、malloc等操作线程安全: 驱动内部已实现线程保护,可在多线程环境中使用
芯片特性: 不同芯片的坐标系、分辨率、触发方式可能不同,请参考具体芯片手册
设备选择: 使用前需在
prj.conf中启用对应的触摸芯片和依赖驱动(I2C、GPIO)多芯片使用: 每个芯片注册为独立设备,可同时使用多个触摸芯片
文件说明
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- 驱动使用说明