微波EDA网,见证研发工程师的成长!
首页 > 应用设计 > 工业电子 > 基于μClinux的触摸屏软硬件关键技术分析

基于μClinux的触摸屏软硬件关键技术分析

时间:12-06 来源:互联网 点击:
触摸屏驱动程序的流程及关键函数

在本设计中,我们使用μClinux2.4内核。驱动程序主要设计思想是:驱动程序在初始化结束后,进入空闲状态,等待中断的到来。一旦笔中断(pen_irq)发生,则进入中断处理程序,进行数据采样、转换和传输,同时,程序对各种不同的情况进行鉴别和异常处理。

触摸屏软件流程如图3所示。在驱动程序中设定了触摸屏所处的7个不同状态,分别用从-1到5的数字表征,这7个状态构成了一个触摸屏状态机,系统根据当前状态做出下一步的处理,如表1所示。整个软件设计根据功能可以划分为5个部分,分别是初始化、设备打开、读操作、中断处理以及I/O控制,下面具体介绍每一部分。





驱动程序初始化

在mc68328digi_init()中向内核注册设备驱动函数:err=misc_register(&mc68328_digi),在init_ts_settings()中设定触摸屏的当前参数:内核版本号、笔移动判别阈值、采样时间、消除抖动开关、消除抖动时间等参数,这些均由用户根据自己的液晶屏以及精度要求来定制,也可以在应用程序中用I/O控制函数ioctl()来设定,本文将在参数分析中具体分析这些参数的意义。

打开设备

在ts_open()函数中,驱动程序向内核注册中断。中断也可以在系统初始化的时候向内核注册,但是一般不建议这样做,因为在加载的设备比较多时,这样做有可能造成中断的冲突。打开一个设备,才让该设备占用中断,是一个较好的策略。向内核注册中断处理程序主要实现两个功能,一是注册中断号,二是注册中断处理函数。

本程序中,向内核注册了两个中断处理程序,分别是:

request_irq(PEN_IRQ_NUM, handle_pen_irq,IRQ_FLG_STD,

“touch_screen”,NULL)和request_ irq(SPI_IRQ_NUM,handle_spi_irq, IRQ_FLG_STD,“spi_irq”,NULL);

在前者中,PEN_IRQ_NUM是中断号,可以指定,也可以动态分配。在该驱动程序中,指定笔中断分配中断号为19;handle_pen_irq是中断处理函数,IRQ_FLG_STD是申请时的选项,它决定中断处理程序的一些特性,这里表示由系统内部占用;touch_ screen是设备名。在后者中,程序向内核注册SPI中断,用来在CPU和外设间传递数据,分配的中断号是0,handle_spi_irq是SPI中断处理函数。

此外,在触摸屏驱动初始化子函数init_ts_drv()中,进行了如下工作:

(1)触摸屏状态的初始化;

(2)笔信息(pen_values)的初始化;

(3)初始化定时器并设置超时函数handle_timeout();

(4)初始化寄存器。初始化等待队列,等待队列是由等待触摸事件发生的进程组成的一个队列,它包括头尾指针和一个正在睡眠进程的链表;

(5)设置触摸屏状态为空闲。

由于这里的初始化会占用一部分系统资源,所以把它们放在了打开设备时处理,而不是最初的设备初始化部分,这样也是出于节省资源的考虑。

读函数ts_read()

一旦用户程序调用read()对触摸屏进行读操作,则驱动程序调用入口点函数ts_read()进行处理。如果此时没有数据到来,且驱动程序选择阻塞型操作,则调用interruptible_sleep_on(&queue->proc_list)将进程阻塞,并进入等待队列,同时设置触摸屏状态为等待;如果选择了非阻塞型操作,则程序在没有数据到达的时候立即返回,然后用异步触发fasync()来通知数据的到来。

在等待数据到来的过程中,如果有触摸动作(笔中断pen_irq)发生,则进入中断处理程序。在中断处理程序中对数据进行采样和转化,把当前坐标信息放入队列中。在进程被唤醒后(使用wake_up_interruptible(&queue->proc_list)来唤醒进程),程序把位置坐标信息、事件序列信息等从队列中取出,放入用户空间(put_user),从而可以被用户程序使用,避免了用户直接和硬件打交道。

驱动程序的中断处理函数

当笔中断发生,程序进入中断处理函数。在中断处理函数中,将完成对两个中断进行处理,分别是外部的触摸中断(笔中断)和SPI数据转换中断。与这两个中断对应的中断处理函数,是触摸屏软件设计的关键所在。

驱动程序在中断处理函数中使用定时器处理时间相关操作。定义函数set_timer_irq(),如下:

staticvoidset_timer_irq(structtimer_list*timer,intdelay){

del_timer(timer);

timer->expires=jiffies+delay;

add_timer(timer);

}

jiffies是一个表征系统自从启动以来到当前为止所运行时钟数的变量,delay是设定的延长时间(用时钟数作为计数单位)。一旦时钟数超过设定值,则触发超时函数,在本程序中是handle_timeout( )。引入定时器的目的有两个:一是可以较为精确地控制系统由于消除电平升降造成信号抖动所需要时间,二是能够有效控制采样坐标的数量,而不必引入占用大量系统资源的简单延时函数。使用SPI中断而产生大量坐标数据这一问题在文献中没有很好的解决办法,只是简单地降低SPI时钟频率以取较少的数据量。本设计中引入定时器,可以很好地解决上述问题。

在handle_timeout()函数中,程序利用条件选择语句,对触摸屏状态值(ts_drv_state)进行判断,如果是非Error状态,则使能SPI,进入handle_spi_irq(),与ADS7843进行数据通讯。在handle_spi_irq()中,程序利用条件选择语句,根据触摸屏状态值(ts_drv_state)来进行数据转换操作,通过向触摸屏控制芯片发送前文中提到的控制字,来得到X和Y方向的坐标。具体逻辑可参见程序流程图。一旦一次转换完成,程序将根据点击状态信息(state_counter)来鉴别点击的性质,在cause_event()函数中,分别对点击和移动做出了判断。判定方法较为简单,只需将前后两次采样坐标之差与移动阈值比较即可得出结论。此外,还区分了信号误差和由于笔移动造成的坐标改变,判别阈值可以由用户自己设定。

I/O控制

对于硬件各个参数,包括采样时间、消除抖动开关、消除抖动时间,都可以通过I/O控制函数ioctl()在用户程序里进行设定,避免每次都直接改变驱动程序,并重新编译内核所带来的时间开销。本程序中对I/O控制函数的定义是:staticintts_ioctl(structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg);其中,参数cmd有两个值,分别为:TS_PARAMS_GET和TS_PARAMS_SET,它们用来指出是获取参数还是设定参数。用户在调用这个函数的时候,只需要对这个参数按照事先约定的格式赋值,就可以方便地获取或者改变触摸屏当前参数,arg是指向所传递参数的指针。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top