wince触摸屏
驱动功能简介
触摸屏驱动是一个典型的分层驱动, 分为模型设备驱动程序Model Device Driver简称MDD层和平台独立驱动Platform Dependent Driver简称PDD层。MDD层向上提供了DDI函数接口,如:TouchPanelAttach()、TouchPanelDetach()、TouchPanelGetDeviceCaps()等;PDD向下提供了访问硬件的DDSI函数接口,如:DdsiTouchPanelEnable()、DdsiTouchPanelDisable()、DdsiTouchPanelGetPoint()等。从而能够实现对系统界面触摸控制。
2、驱动功能需求
1) 触摸屏 实现系统界面触摸控制,并能准确定位,有效采集触摸点坐标(支持单双击)。
2)每秒采样的点数能够达到60(即灵敏度功能)。
3)触摸屏按下时,向APP发送状态消息,通知其或其获取触摸点的坐标。
4)支持校正、保存校验数据,支持平滑功能(轨迹圆滑,流畅)。
5)触摸屏占用资源控制在尽可能小的范围之内。
3、驱动总体设计
采用电阻屏,通过四根线控制触摸屏的X 方向与Y方向,根据电阻值的大小确定触摸点相应的坐标。通过ADC采样和转换,每次采集8个点,通过(POS[k].xp>100&&(POS[k].ypos*POS[k].ym/(POS[k].xp+1)-POS[k].ypos<1000)过滤掉一些无效点,取4个有效点,然后通过冒泡排序,然后对这4个点求平均值,把这个平均值作为触摸点的坐标值。
4、详细设计
MDD层
1)TouchPanelAttach()
创建触摸屏中断事件、和触摸屏校验事件:
hTouchPanelEvent = CreateEvent();
hCalibrationSampleAvailable = CreateEvent();
调用DdsiTouchPanelDisable(),设置校验TouchPanelSetCalibration()。
2)TouchPanelGetPriority()
获取触摸屏优先级别。
3)TouchPanelGetDeviceCaps()
调用DdsiTouchPanelGetDeviceCaps创建获取DisplayWidth和DisplayHeight.
4)TouchPanelSetMode()
设置中断线程优先级CeSetThreadPriority(hThread,gThreahHighPriority/ gThreahPriority),默认调用DdsiTouchPanelSetMode()一些参数。
5)TouchPanelPowerHandler()
调用DdsiTouchPanelPowerHandler()进行电源设置。
6)TouchPanelEnable()
将触摸屏中断gIntrTouch和定时器gIntrTouchChanged和事件绑定并初始化。如果初始化失败,则清除相应中断。同时在这里调用TouchPanelGetPriority()获取普通优先级和高优先级,通过CeSetThreadPriority(hTread,gThreadPriority)设置hTread优先级。
7)TouchPanelDisable()
禁用触摸屏,调用DdsiTouchPanelDisable()。
InterruptDone(gIntrTouch/gIntrTouchChanged)中断,
InterruptDisable(gIntrTouch/gIntrTouchChanged)中断 ,CloseHandle(hTouchPanelEvent/hCalibrationSampleAvailable)事件。
8)TouchPanelReadCalibrationPoint()
读取校验点
9)TouchPanelReadbrationAbort()
校验异常时,终止校验。
PDD层
1)DdsiTouchPanelGetDeviceCaps()获取PDD层一些参数:
TPDC_SAMPLE_RATE_ID 采样速率
CurrentSampleRateSetting设置为1,为高速率模式;设置为0,则为低速率模式。
TPDC_CALIBRATION_POINT_COUNT_ID 校验点的个数,5个点。
TPDC_CALIBRATION_POINT_ID 校验点的坐标,这里调用TSP_CalibrationPointGet()函数。
2)DdsiTouchPanelSetMode()设置模式
TPSM_SAMPLERATE_LOW_ID: 低速率
TPSM_SAMPLERATE_HIGH_ID:高速率
3)DdsiTouchPanelEnable()使能触摸屏
在这里打开ADC,通过ghTSADC=CreateFile()打开。触摸屏中断和内核通信,读取ADC采样值:
KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,&IRQ,sizeof(DWORD),&gIntrTouch,sizeof(UINT32),NULL),返回gIntrTouch(即return gIntrTouch)。
触摸屏中断(gIntrTouch)和定时器中断(gIntrTouchChanged=SYSINTR_NOP)(每隔一段时间进行一次采样)
在DdsiTouchPanelEnable()中与硬件关联,在DdsiTouchPanelGetPoint()中清除触摸屏中断。
BITSET(pPIC->POL0,HW5) 让中断极性控制寄存器POL0第6位EI2置位,IRQ=IRQ_EI2(将IRQ_EI2赋给IRQ)。
4)DdsiTouchPanelDisable()禁用触摸屏
5)DdsiTouchPanelAttach()连接触摸屏
打开LCD_Width 读取m_nScreenWidth;
打开LCD_Height 读取m_nScreenHeight;
打开TouchI2C 读取gI2CchNum。
分配地址:pGPIO、g_pADCReg。
6)DdsiTouchPanelDetach()断开触摸屏
简单返回。
7)DdsiTouchPanelGetPoint(pTipStateFlags,*pUncalX,*pUncalY)获取点的坐标并判断是否有效
调用tca_getrawdata()获取点的坐标,sleep(15)休眠让出时间给其它线程用,retFlag进行判断,Valid:prevX=posX,prevY=posY;invalid:posX=prexX,posY=preY。InterruptDone(gIntrTouch)。
*pUncalX=posX,*pUncalY=posY供校准。
8)DdsiTouchPanelPowerHandler()电源管理(略)
几个重要的函数和参数:
1)TouchPanelpISR()中断
整个触摸屏唯一的一个事件中断源,主要有作用:响应触摸事件、循环与等待、坐标校准、判断触摸笔UP和DOWN状态、校验时间和误差点的个数的判断等。它在TouchPanelEnable()函数中调用,创建线程 :hThread = CreateThread(NULL,0,TouchPanelISR,0,0,NULL)。调用DdsiTouchPanelGetPoint()获取点的坐标。
2)tca_getrawdata()获取点的坐标
利用DeviceIoControl(ghTSADC,IOCTL_TSADC_TOUCHSCREEN_GPIO,NULL,0,POS,sizeof(TSXYPOS)*8,NULL,NULL)调用IOCTL_TSADC_TOUCHSCREEN_GPIO接口,读取ADC采样值到数组POS[8],满足POS[k].xp>100&&(POS[k].ypos*POS[k].ym/(POS[k].xp+1)-POS[k].ypos<1000)为有效点,for(i=index;i<(index+4);++i)中的4个点(其中index=(validcnt-4)/2)求平均值。
3)tca_touchbubblesort()和求平均值
利用tca_touchbubblesort(r_x/r_y,validcnt)对有效的点进行冒泡排序,然后对for(i=index;i<(index+4);++i)中的4个点(其中index=(validcnt-4)/2)求平均值。
4)输出到屏幕上
If (*x<=MAX_X && *x>=MIN_X) && (*y <=MAX_Y && *y>=MIN_Y)
else
if(*x>MAX_X)
*x=MAX_X;
else if(*x<MIN_X)
*x=MIN_X;
If(*y>MAX_Y)
*y=MAX_Y;
else if(*y<MIN_Y)
*y=MIN_Y;
5、测试项设计
(1)校正测试
开机校正时,通过串口打印校正点设置的坐标和触摸屏上采样取到点的坐标,然后对二者进行分析和对比。
(2)触摸点及其采样稳定性测试
点击触摸屏,在某一个时间范围内保持一个近似力度,打印输出采样值,查看打印信息,观察各个点的坐标及其变化情况,是否有采样失败,是否存在误差。然后校正后再进行相同的测试。
(3)坐标个数测试
通过测试工具,测试每秒采样坐标的个数,参考标准暂为60/s。点击触摸屏,在触摸屏上显示每秒坐标个数。
(4)资源占用测试
通过ActiveSync同步设备和PC,利用VS2005 Remote Tool下的PerformanceMonitor工具测试触摸屏驱动占系统资源的情况。
(5)飞点现象测试
通过测试工具,测试触摸屏是否存在飞点现象。
(6)MAX_X、MAX_Y,MIN_X、MIN_Y的调整
在触摸屏上,从左上角向右下角拉一个虚线框,观察触摸笔与虚线框坐标情况。若触笔的坐标点在虚线框外面,则增大MIN_X、MIN_Y,减少MAX_X、MAX_Y。若触摸笔的坐标在虚线框里面,则减小MIN_X、MIN_Y,增大MAX_X、MAX_Y。
(7)校验数据保存问题
每次开机检查HARDWARE\\DEVICEMAP\\TOUCH下是否有数据,如果有数据,则退出校验;如果没有数据则通过RegistySet.cpp下的CalibrationDataFileToRegisty ()函数进行开机校验,并将校验后的数据保存到\\Data\\touch.ini下,下一次开机就不需要再进行校验。
(8)边缘及其四角稳定性
测试触摸屏边缘和四个角,打印信息,查看采样值,观察稳定性,若不准,则进行调整。
(9)其它全面的、系统性的测试项待设计……(5至10例)。
(1) 采样稳定性问题
中央区域没有问题,四个角上采样严重不准,为0情况较多,采样数据相差较大,通过调整MIN_X,MIN_Y,MAX_X,MAX_Y的大小,调整后基本满足需求。
(2) 灵敏度问题
1)采样速率要求每秒60个以上,通过修改TouchPanel.cpp文件下DdsiTouchPanelGetPoint函数中Sleep(20)的参数,现在将其改为15,稍微缩短休眠时间,提高采样的频率。
2)修改ADC延时时间,Tca_adconv.c文件中,由原来的ADC_DELAY(300)改为ADC_DELAY(180)。
3)通过修改寄存器,设置……………………
4)减少每次采样点的个数,由原来采16个点取8个改为采8个取4个点。提高采样效率,节省时间,提高灵敏度。
5)while循环…………………………………………
(3)MAX_X、MAX_Y,MIN_X、MIN_Y的调整
MAX_X 3980
MIN_X 150 //230
MAX_Y 3690
MIN_Y 420 //440
(4)飞点问题调整
“前进”、“后退”按钮出现飞点现象,校验后不出现该现象,但重新开机又会出现。解决办法是:通过加载RegistySet驱动,实现开机校验判断和校验数据保存,即如果是第一次开机,则驱动触摸屏校验,并将校验数据保存,下次开机就不需要再进行校验,因保存了校验数据,经过校正之后就不会出现“前进”、“后退”按钮飞点现象。
(5)资源占用情况
开机时基本保持在8%左右,10%以下,当TCCAPP进程运行时占用20%左右。
(6) 开机校验原理及描述
StartCalibrationThread()函数创建一个线程,并把CalibrationThread作为起始地址。其中,CalibrationThread()函数中,通过RegOpenKeyEx()RegQueryValueEx()函数打开注册表、操作注册表。查找“HARDWARE\\DEVICEMAP\\TOUCH”(宏名为 RK_TOUCH)路径下的“CalibrationData”(宏名为 RV_DATA)是否有校验数据。有则Exist Calibration Data,即退出校验;反之则开始校验(TouchCalibrate())。
(7)RegistySet驱动原理及描述
CalibrationDataFileToRegisty()会读“\\Data\\touch.ini”(宏为CAL_DATA_FILE)到文件hFile,如果不为空,则通过fgetws()读到ptStr数组中,再通过swscanf读prStr到nField,如果nField不等于10(5个点,x、y值),则认为是无效;如果有效,则保存校验数据。用ResOpenKeyEx()打开“HARDWARE\\DEVICEMAP\\TOUCH”路径,再通过RetSetValueEx()将CalibrationData的值设置为prStr数组里的