最近在wince 6.0调试了多款电容屏驱动,参考了很多前辈的代码,发现基本上有2种做法。一种是直接另外写个流驱动,自己在中断线程中读取坐标和状态,然后用mouse_move等wince api模拟鼠标点击,实现触摸功能。另外一种就是利用是s3c 6410自带的触摸屏驱动,在其中实现读取坐标的方法。我最早是采用第一种方法,因为网上很多代码,拿下来就可以直接用,但是发现有个问题,就是鼠标移动的时候有点慢(在wince桌面画框框可以看出来),单纯的点击倒是没啥问题。后面经过测试,发现去掉mouse_move的调用,1秒钟可以接收处理30个左右的中断.但是加上mouse_move之后,就变成只有几个了。后面尝试不直接在中断线程里面调用,而是采用消息队列的方式,即接收到中断并读取坐标数据后,发送到消息队列,然后在另外的线程去处理。但是并没有太大改善,可能是消息队列也不是很高效吧(对中断处理来说)。如果直接自己写个队列,去保存到此队列(都是纯内存操作),然后通过事件通知其他线程处理,可能是可以解决的。但是后面因为时间问题就没有尝试这种方案了。想到之前的电阻屏是6410自带的,效果也挺好,所以就用第二种方式来做了。其实用第二种方法来做,改动并不太大。把第一种方法的初始化代码,加到s3c6410_touch里面,一般就是初始化IIC,有可能也需要初始化GPIO。然后重点是DdsiTouchPanelGetPoint方法,这个方法是在有触摸中断时,wince会自动调用的。只需要在这个方法里面实现读取触摸屏的坐标以及状态就OK了。读取的具体代码和触摸屏ic有关,基本上就是通过IIC读取一片地址的数据,芯片手册上会有写,最多支持几点触摸,根据你需要支持的触摸点数来读取就好了。把读取的坐标设置到pUncalX, pUncalY,要注意pTipState ,因为电容屏读取的坐标已经就是校准过的,所以需要设置pTipState |= TouchSampleIsCalibratedFlag;这个标志,否则wince会重新再校准一边坐标,导致触摸不准。
有一点比较有趣的是,6410自带的驱动是采用定时器的方式,去轮询查询触摸屏的状态的,比如按下触摸屏后,启用定时器,开始轮询,检测到手指抬起后,停止定时器。其实,很多电容屏不推荐采用轮询的方式,因为本身按下和抬起都是有中断的,move也有,完全不需要采用定时器去查。采用定时器的做法,不仅代码逻辑的相当复杂,效率也很低。下面是我改过之后的方法的代码
VOID
DdsiTouchPanelGetPoint(TOUCH_PANEL_SAMPLE_FLAGS *pTipState, INT *pUncalX, INT *pUncalY)
{
static int PrevX=0;
static int PrevY=0;
DWORD InterruptType = SYSINTR_NOP;
PrevX = *pUncalX;
PrevY = *pUncalY;
if(PDDSampleTouchScreen(pTipState,pUncalX,pUncalY))
{
*pUncalX = *pUncalX*X_SCALE_FACTOR;
*pUncalY = *pUncalY*Y_SCALE_FACTOR;
}
else
{
*pTipState = TouchSampleIgnore;
*pUncalX = PrevX;
*pUncalY = PrevY;
}
RETAILMSG(TOUCH_DEBUG_MSG,(_T("[TSP] Point(%d,%d,%d) \r\n"),*pUncalX,*pUncalY,*pTipState));
InterruptType = gIntrTouch;
L1: InterruptDone(InterruptType); // Not handled in MDD
}
PDDSampleTouchScreen就是和芯片有关的读取坐标和状态的方法咯,代码就不贴了。希望能给大家起到一点参考的作用,如果有问题,欢迎指正。