WINCE6.0+S3C6410的触摸屏驱动
********************************LoongEmbedded********************************
作者:LoongEmbedded(kandi)
时间:2011.8.13
类别:WINCE 驱动开发
********************************LoongEmbedded********************************
备注:
MSPS(million samples per second)表示每秒采样百万次,是转换速率的单位,而转换速率(conversion rate)是指完成一次从模拟量到数字量的AD转换所需要时间的倒数。我们知道S3C6410的ADC最大的A/D转换时钟频率是5MHZ,所以可以计算出一次A/D转换的时间=5*(1/5MHZ)=1us,所以1s中的采样次数=1s/1us=1MSPS,这就是1MSPS的由来。
1. 电阻式触摸屏的工作原理
四线电阻式触摸屏是电阻式家族中应用最广、最普及的一种。其结构由下线路(玻璃或薄膜材料)导电ITO层和上线路(薄膜材料)导电ITO层组成。中间有细微绝缘点隔开,其中下层的ITO与玻璃基板附着,上层的ITO附着在PET薄膜上。当触摸屏表面没有压力时,上下线路处于开路状态。一旦有压力施加到触摸屏表面。上下线路就会导通,控制器通过下线路导电ITO层在X坐标方向上施加驱动电压,通过上线路导电ITO层上的探针,侦测X方向上的电压,由此推算出触点的X坐标。通过控制器改变施加电压的方向,同理可测出触点的Y坐标,从而明确触点的位置。当有物体接触触摸屏表面并施以一定的压力时,上层的ITO导电层发生形变与下层ITO发生接触,该结构可以等效为相应的电路,如下图
图1
计算触点的X,Y坐标分为如下两步:
⑴. 计算Y坐标,在Y+电极施加驱动电压Vdrive, Y-电极接地,X+做为引出端测量得到接触点的电压,由于ITO层均匀导电,触点电压与Vdrive电压之比等于触点Y坐标与屏高度之比。
⑵. 计算X坐标,在X+电极施加驱动电压Vdrive, X-电极接地,Y+做为引出端测量得到接触点的电压,由于ITO层均匀导电,触点电压与Vdrive电压之比等于触点X坐标与屏宽度之比。
测得的电压通常由ADC转化为数字信号,再进行简单处理就可以做为坐标判断触点的实际位置。
图2
2. WINCE触摸屏驱动模型及接口函数
2.1 WINCE触摸屏驱动模型
WINCE触摸屏驱动模型如下图所示:
图3
在WINCE系统中,触摸屏驱动是一种分为MDD(Model Device Driver,模型设备驱动)层和PDD(Platform Device Drvier,平台设备驱动)层的分层驱动。其中MDD层一般不需要修改就可以直接使用,该部分提供DDI接口给GWES调用,而MDD层通过调用PDD层提供的DDSI函数接口来实现自身的功能。MDD层和PDD层除了DDSI函数接口之外,还要通过一些全局变量来协调者两层的工作,比如gIntrTouch和gIntrTouchChanged全局变量就是在PDD层定义,在MDD层和PDD层都有使用。
我们在触摸屏驱动中的工作主要是修改PDD层提供给MDD层调用的DDSI函数,这部分的工作主要是采样定时器是否需要更改?LCD屏的分辨率变化后的修改?以及抖动的处理等等这些内容。
2.2 MDD层导出的函数接口DDI
下面先大概学习DDI函数集
1) BOOL ErrorAnalysis(
INT32 cCalibrationPoints, //@PARM The number of calibration points
INT32 *pScreenXBuffer, //@PARM List of screen X coords displayed
INT32 *pScreenYBuffer, //@PARM List of screen Y coords displayed
INT32 *pUncalXBuffer, //@PARM List of X coords collected
INT32 *pUncalYBuffer //@PARM List of Y coords collected
);
该函数提供关于触摸屏校准的精确性的信息,在校准触摸屏的时候会调用该函数。它收到一系列的校准屏幕坐标和一个相应的没有校准触点数据(point data),它评估这两个点集数据(屏幕坐标集和校准时候点击时收集的5个触点坐标集,而屏幕坐标集就是注册表中CalibrationData项的内容。)之间的相互关系来决定是否采用当前的触摸数据作为屏幕校准坐标值,也就是说如果当前点击的5个触点的坐标和之前的屏幕坐标值比较接近,那么就采用新的触点坐标作为屏幕校准坐标值。
2) BOOL WINAPI TouchCalibrate(void)
该函数开始触摸屏校准的动作,比如在WINCE的控制面板下,我们点击“笔针”来校准的时候,就会调用该函数来开始触摸屏的校准。
3) Void TouchPanelCalibrateAPoint(
INT32 UncalX, //@PARM The uncalibrated X coordinate
INT32 UncalY, //@PARM The uncalibrated Y coordinate
INT32 *pCalX, //@PARM The calibrated X coordinate
INT32 *pCalY //@PARM The calibrated Y coordinate
)
该函数用于把没有校验的坐标转换为校验的坐标,该函数在计算x和y坐标的时候有4个因子是隐藏的,这里是指全变变量v_CalcParam的成员。这样可以为GWES提供像素以下(sub-pixel)的精确度,可以提供字迹识别的精确度的支持。
4) VOID TouchPanelDisable(VOID)
该函数禁用触摸屏设备,关闭ISR,停止中断和注销事件及其他同步手段,该函数调用了DdsiTouchPanelDisable函数。
5) BOOL TouchPanelEnable(PFN_TOUCH_PANEL_CALLBACK pfnCallback)
该函数启动触摸屏,pfnCallback是指向处理触摸屏回调函数,此回调函数处理触笔事件,包括触笔按下,或抬起,或是定时器中断时触发的事件,该函数调用了DdsiTouchPanelEnable函数。
6) BOOL TouchPanelGetDeviceCaps(
INT iIndex,
LPVOID lpOutput
)
该函数用于返回触摸屏设备支持的具体功能,相关的参数描述如下:
图4
该函数调用了DdsiTouchPanelGetDeviceCaps函数。
7) TouchPanelInitializeCursor函数
该函数提供一个机会给触摸屏驱动在初始化的时候移动光标。
8) Void TouchPanelPowerHandler(BOOL bOff)
该函数处理电源状态改变的通知,bOff若为TRUE,表示关闭电源,为FALSE,表示打开电源,主要是把触摸屏控制器是否设置为没有操作的模式,以及是否开启定时器,该函数调用了DdsiTouchPanelPowerHandler函数来处理。
9) TouchPanelReadCalibrationAbort函数
该函数停止当前对TouchPanelCalibrateAPoint函数的调用。
10) BOOL TouchPanelReadCalibrationPoint(INT *pRawX,INT *pRawY
该函数开始获取一个校准点的处理,pRawX指向没有校准的x坐标值,pRawY指向没有校准的y坐标值。该函数促使设备驱动提交触笔按下和抬起之间最后有效的x和y坐标给校准回调函数
11) )BOOL TouchPanelSetCalibration (
INT32 cCalibrationPoints, //@PARM The number of calibration points
INT32 *pScreenXBuffer, //@PARM List of screen X coords displayed
INT32 *pScreenYBuffer, //@PARM List of screen Y coords displayed
INT32 *pUncalXBuffer, //@PARM List of X coords collected
INT32 *pUncalYBuffer //@PARM List of Y coords collected
)
该函数初始化全局变量v_CalcParam的校准信息,我们可以调用TouchPanelCalibrateAPoint函数使用这些信息来转换非校准点为校准点,该函数会调用ErrorAnalysis函数。
cCalibrationPoints:指示校准点的数量。
pScreenXBuffer:列出(Array)屏幕的x坐标。
pScreenYBuffer:列出(Array)屏幕的y坐标。
pUncalXBuffer:列出(Array)采集的x坐标。
pUncalYBuffer:列出(Array)采集的y坐标。
12) BOOL TouchPanelSetMode(INT iIndex,LPVOID lpInput)
该函数设置触摸屏设备的模式信息,比如设置低采样率还是高采样率,设置触摸屏驱动的IST为高优先级还是正常的优先级。该函数调用了DdsiTouchPanelSetMode函数。
2.3 PDD层导出的函数接口DDSI
1) DdsiTouchPanelAttach函数
当触摸屏驱动的MDD层入口收到DLL_PROCESS_ATTACH消息的时候会调用该函数,该函数在这里直接返回0。
2) DdsiTouchPanelDetach函数
当触摸屏驱动的MDD层入口收到DLL_PROCESS_DETACH消息的时候会调用该函数,该函数在这里直接返回0。
3) DdsiTouchPanelEnable函数
该函数被MDD层的TouchPanelEnable函数调用来做一下的动作
⑴ 为需要用的GPIO、ADC、PWM和中断寄存器分配虚拟内存空间。
⑵ 为触摸屏中断(触笔的按下或抬起)和定时器中断申请对应的逻辑中断号,分别赋值给gIntrTouch和gIntrTouchChanged。
⑶ 配置触摸屏控制器、中断控制器和PWM的寄存器。
4) DdsiTouchPanelDisable函数
该函数禁用触摸屏设备,也就是防止随后的触摸采用的产生,并且关闭对触摸屏硬件的供电,其他必须的动作需要视具体特征的触摸屏硬件来定了。
5) DdsiTouchPanelGetDeviceCaps函数
该函数被TouchPanelGetDeviceCaps函数调用来获取触摸屏设备支持的具体功能,见图4的描述。
6) VOID DdsiTouchPanelGetPoint(
TOUCH_PANEL_SAMPLE_FLAGS *pTipState,
INT *pUncalX,
INT *pUncalY)
该函数返回最新获得的点坐标并且此点的点击状态信息,点击状态的值如下定义:
图5
7) DdsiTouchPanelPowerHandler函数
该函数被TouchPanelPowerHandler函数调用,见上面TouchPanelPowerHandler函数的描述。
8) DdsiTouchPanelSetMode函数
该函数被TouchPanelSetMode函数调用来返回低采样率和高采样率的值。
3. WINCE触摸屏驱动的实现
3.1 触摸屏驱动的工作概述
触摸屏驱动从触摸屏硬件读取用户的输入并且转换这个输入为触摸事件,然后把触摸事件发送给GWES(Graphics,Windowing,and Events Subsystem)。触摸屏驱动也负责把把没有校准的坐标转换为校准的坐标,经过校准的坐标可以补充硬件的异常,比如偏或者倾斜,或者非线性的问题。
为了让触摸屏驱动正确工作,它在用户用手指或是触笔点击触摸屏的时候要提交触点给GWES。当用户手指或是触笔离开触摸屏的时候,触摸屏驱动必须至少提交一个最好的事件来指示用户的手指或是处理离开了触摸屏。并且把校准后的精确度在四分之一像素的坐标
报告给GWES。
3.2 配置触摸屏驱动相关的控制器
主要是通过调用DdsiTouchPanelEnable函数来实现的,此函数的功能见上面的描述,下面来看DdsiTouchPanelEnable函数调用的TSP_PowerOn函数是如何配置相关控制器的寄存器的
图6
现在来学习图6中相关寄存器的一些知识:
1) ADCDL寄存器
ADCDL是ADC开始转换或间隔一段时间的延时寄存器,在正常转换模式、单独的转换模式和顺序转换模式下,指的就是从使能ADC转换到ADC开始采样终端这段时间,这端时间是基于PCLK来计算的;当在等待中断模式下,如果这时触笔按下,将每隔几ms的时间发送发送中断信号INT_PNDNUP用于自动X/Y坐标的转换。如果在系统的STOP模式下触笔按下,将在几ms内产生唤醒信号来使系统退出STOP模式,先看此寄存器的描述
图7
我们接着看在ADC转换模式下,这个DELAY=5000的实际意义,我们来看下图:
图8
我们现在就来计算图8中的B的值,首先系统的PCLK=66.5MHZ,那么依据CPU中给出的参考公式:
图9
结合图6和图9可算出A/D转换频率=PCLK/(prescale value+1)=66.5MHZ/(24+1)=2.66MHZ,一次A/D转换的时间=5*1/2.66MHZ=5*0.3759us=1.8797us。那么B=C=5000*0.3759us+1.8797us=1.8795ms+1.8797us,而A=5000*1/3.68MHZ=1.3587ms
2) ADCCON寄存器
图10
3) ADC触摸屏控制寄存器ADCTSC
图11
4) 清除ADC中断寄存器ADCCLRINT和清除触笔按下或抬起终端寄存器CLEAR_ADCWK_INT
这两个寄存器分别用于清除ADC转换中断和清除触笔按下或抬起的中断,触摸屏驱动的ISR负责在中断服务完成后通过写任何值到这两个寄存器中来清除相关的中断。
5) 定时器3的计数缓冲器TCNTB3
我们采用TSP_TIMER_CNT_LOW对TCNTB3赋值,TSP_TIMER_CNT_LOW的宏定义如下:
图12
图13中TSP_TIMER_CNT_LOW的表示式是怎么来的呢?我们的设计思想是每1秒钟采样50次,也就是说每20ms,定时器3将产生定时器中断来开始采样。而我们知道定时器3的TCNTB3的值在开始定时器3后递减,当递减到0的时候,定时器3产生INT_TIMER3中断,我们借用PWM定时器部分的下面这个图:
图13
结合图12和图13可有1/50=(TCNTB3+1)/定时器3的时钟频率,从而可以推算出TCNTB3=定时器3的时钟频率/50-1=33.25MHZ/50-1=664999,这样定时器3的周期时间就为20ms。
6) 定时器中断控制和状态寄存器
用于控制定时器中断使能和获取中断状态信息。
3.3判断触摸屏是否被触摸及其处理
触摸屏驱动用到了ADC触笔按下或抬起中断和定时器3的定时中断,在DdsiTouchPanelEnable函数中为这两个中断请求IRQ到系统中断的映射,也即申请对应的逻辑中断
图14
申请对应的逻辑中断在MDD层的TouchPanelEnable函数中关联到同一个事件句柄:
图15
在上面的中断产生的时候,TouchPanelpISR会调用PDD层的DdsiTouchPanelGetPoint来获取采样的数据,下面分几部分学习DdsiTouchPanelGetPoint的函数体:
第一部分:
图16
第二部分:
图17
3.4获取稳定和去抖动的触摸坐标
从图17中可知TSP_GetXY函数用于获取稳定的采样数据,而Touch_Pen_Filtering函数在从TSP_GetXY函数返回的数据的基础上进行过滤,下面来学习这两个函数,先看TSP_GetXY函数
图18
接着看Touch_Pen_Filtering函数
图19
3.5 校准触摸屏
我们可以通过下面的步骤来校准触摸屏:
1) 调用TouchPanelEnable函数来开始触摸屏的校准。
2) 调用TouchPanelGetDeviceCaps函数请求采样点的数量,比例是5点式的校准。
3) 对于这5个校准点每个点的校准,要执行下面的步骤:
a. 调用TouchPanelGetDeviceCaps函数来获取一个校准点的坐标,这个坐标是屏幕坐标值,比如LCD屏的分辨率是800*480,校准程序在校准的时候通过获取的第一个校准点就是屏正中间的点,这时候获取的屏幕坐标是,x=800/2=400,y=480/2=240。
b. 在当前校准点处画十字,等待用户的点击。
c. 用户点击十字图形后,调用TouchPanelReadCalibrationPoint函数获取当前校准点处点击触摸屏的坐标数据。
4) 当取完所需要的校准点,调用TouchPanelSetCalibration函数来计算校准系数a1,b1,c1,a2,b2,c2和delta。
该函数将产生校准基准参数。
TouchPanelSetCalibration函数执行的动作是一套数学算法,具体内容为:
在触摸屏数据与其位置偏移关系且屏幕像素与其位置偏移关系同为线性关系假设情况下,触摸屏返回的位置信息与像素位置信息之间成2D坐标变换关系。则对于触摸屏按下点的触摸屏坐标(Tx,Ty)与其在显示设备位置关系上匹配的点的屏幕坐标(Sx,Sy)之间的转换关系,可以通过下述坐标变换表示:
Sx = A1*Tx + B1*Ty + C1
Sy = A2*Tx + B2*Ty + C2
TouchPanelSetCalibration的具体工作就是通过校准的动作获取的屏幕坐标和触摸屏坐标TouchCoordinate来确定A1,B1,C1和A2, B2, C2。这里的计算关系在TouchPanelCalibrateAPoint函数中计算,见下图:
图20
当触摸屏驱动执行了上面的动作之后,任何手指或者触笔的点击采用都会传递给TouchPanelEnable中指定的回调函数,触摸屏驱动会传递校准后的或者没有校准的点给回调函数。如果触摸屏驱动有很有效的校准运算法则,它能够返回校准后的触摸点,但是,如果校准需要集中计算,那么触摸屏驱动也许选择会返回没有经过校准的点,而不是在高优先级的驱动线程(这里是指触摸屏驱动)执行大量的计算,低优先级的线程可以处理由回调函数传递过来的点并且进行校准。
3.6 触摸屏驱动的相关注册表信息
[HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\TOUCH]
"DriverName"="s3c6410_touch.dll"
"MaxCalError"=dword:7 ;800_480 release
"CalibrationData"="520,498 251,630 250,367 787,363 790,625" ;800_480 release
这里的CalibrationData的值是校准程序的5个点的坐标值,分别对应于触摸屏中间、左上角、左下角、右下角和右下角的坐标值,要注意的是这是触摸坐标值,而不是屏幕坐标值,因为对于不同的触摸屏,其电压升降趋势不一定相同,所以CalibrationData的值就不一样了。
3.7 触摸屏驱动的工作流程
这需要结合MDD层的ISR函数TouchPanelpISR来理解,触摸屏驱动的工作流程如下:
图21
WINCE 触摸屏驱动实现的分析
http://www.rosoo.net/a/201010/10255.html
WinCE中触摸屏驱动开发详解
http://www.cnblogs.com/xilentz/archive/2010/05/12/1734111.html
电阻式触摸屏技术的原理及电阻触摸屏分类
http://www.elecfans.com/yuanqijian/dianzuqi/20110209186584.html