电容触摸屏驱动分析

更新时间:
2024-01-09
下载文档

电容触摸屏驱动分析

电容触摸屏硬件原理

电容触摸屏利用人体电流感应现象,在手指和屏幕之间形成一个电容,手指触摸时吸走一个微小电流,这个电流会导致触摸板上 4 个电极上发生电流流动,控制器通过计算这 4 个电流的比例就能算出触摸点的坐标。

电容触摸屏代码分析

电容触摸屏设备是一个字符设备,以 GT9xx 系列的电容触摸屏为例,该电容触摸屏常见采用 I2C 接口连接到主控芯片。

应用程序只需通过 read 函数读取触摸屏设备,即可获取到填充有触摸坐标信息的 mouse_event_notify 结构体。

电容触摸屏初始化

安装触摸屏驱动的逻辑如下:

INT  touchDrv (VOID)
{
    struct file_operations      fileOper;
    INT                         iDrvNum;
    lib_memset(&fileOper, 0, sizeof(struct file_operations));
    fileOper.owner         = THIS_MODULE;
    fileOper.fo_create     = __touchOpen;
    fileOper.fo_open       = __touchOpen;
    fileOper.fo_close      = __touchClose;
    fileOper.fo_read       = __touchRead;
    fileOper.fo_lstat      = __touchLstat;
    fileOper.fo_ioctl      = __touchIoctl;
    iDrvNum = iosDrvInstallEx2(&fileOper, LW_DRV_TYPE_NEW_1);
    return  (iDrvNum);
}

创建触摸屏设备的逻辑如下:

iError = iosDevAddEx(&pTouchDev->TOUCH_devHdr, pcName, iDrvNum, DT_CHR);
if (iError) {
    _ErrorHandle(ERROR_SYSTEM_LOW_MEMORY);
    __SHEAP_FREE(pTouchDev);
    printk(KERN_ERR "Failed to create touch device %s!\n", pcName);
    return  (PX_ERROR);
}

最终,调用 GT9xx 硬件初始化操作:

  • 通过 I2C 接口设置触摸屏扫描数据间隔寄存器、最大支持 TOUCH 点数寄存器。
  • 初始化 GT9xx 中断,其采用 GPIO 作为外部中断,当手指触摸到屏幕时,会产生 GPIO 中断。

电容触摸屏事件上抛线程

GT9xx 的触摸事件提交分为上下半程处理,下半程线程会阻塞等待触摸中断事件产生。当产生了触摸中断时,会调用 __touchHandleEvents 获取坐标值,并将获取到的坐标值填入 mouse_event_notify 结构体,最终通过消息队列传送到触摸屏定义的 read 函数中。用户调用触摸驱动的 read 函数时,即可获取到触摸事件信息。

GT9xx 的下半程线程逻辑如下:

static PVOID  __touchThread (PVOID  pvArg)
{
    INT                iEventNum;
    PTOUCH_DEV         pTouchDev  = (PTOUCH_DEV)pvArg;
    while (!pTouchDev->TOUCH_bQuit) {
        API_SemaphoreBPend(pTouchDev->TOUCH_hSignal, LW_OPTION_WAIT_INFINITE);
        if (pTouchDev->TOUCH_bQuit) {
            break;
        }
        iEventNum = __touchHandleEvents(pTouchDev);
        if (iEventNum == PX_ERROR) {
            printk(KERN_ERR "touch: handle touch event fail!\n");
        } else if (iEventNum > 0) {
            SEL_WAKE_UP_ALL(&pTouchDev->TOUCH_selList, SELREAD);
        }
    }
    return  (LW_NULL);
}

__touchHandleEvents 获取坐标值时会调用到 GT9xx 定义的 getevent 函数,在其中读取 GT9xx 的坐标寄存器,并填充为 mouse_event_notify 结构体。当用户手指离开屏幕时,GT9xx 产生 release 事件,getevent 返回值为 TOUCH_RELEASE_NUM ,其实现如下:

static INT  __touchHandleEvents (PTOUCH_DEV  pTouchDev)
{
    mouse_event_notify  events[TOUCH_MAX_INPUT_POINTS];
    INT                    iEvents;
    INT                    i = 0;
    iEvents = pTouchDev->pDrvFunc->getevent(pTouchDev, events);
    if (iEvents == TOUCH_RELEASE_NUM) {                                 
        API_MsgQueueSend(pTouchDev->TOUCH_hEventQueue,
                         (PVOID)&events[0],
                         (ULONG)sizeof(mouse_event_notify));
        i = 1;                                                        
    } else {
        if (iEvents > TOUCH_MAX_INPUT_POINTS) {
            iEvents = TOUCH_MAX_INPUT_POINTS;
        }
        for (i=0; i<iEvents; i++) {
            API_MsgQueueSend(pTouchDev->TOUCH_hEventQueue,
                             (PVOID)&events[i],
                             (ULONG)sizeof(mouse_event_notify));
        }
    }
    return  (i);
}

电容触摸屏触摸中断产生

手指触摸时中断处理逻辑如下:

static irqreturn_t  __touchIsr (PTOUCH_DEV  pTouchDev, ULONG  ulVector)
{
    irqreturn_t     irqreturn;

    irqreturn = API_GpioSvrIrq(pTouchDev->TOUCH_data.T_uiIrq);
    if (irqreturn == LW_IRQ_HANDLED) {
        API_GpioClearIrq(pTouchDev->TOUCH_data.T_uiIrq);
        API_SemaphoreBPost(pTouchDev->TOUCH_hSignal);
    }
    return  (irqreturn);
}
文档内容是否对您有所帮助?
有帮助
没帮助