在开始实现触摸屏功能之前,还需要解决一个问题,那就是触摸屏的校正。触摸屏和LCD是两种不同的物理器件。对于一个分辨率为320×240的LCD,它的宽度为320个像素,高度为240个像素。而触摸屏处理的数据是点的物理坐标,该坐标是通过触摸屏控制器采集得到的。要想实现触摸屏上的物理坐标与LCD上的像素点坐标一一对应上,两者之间就需要一定的转换,即校正。而且电阻式触摸屏由于自身的原因参数会发生变化,因此需要经常性的校正。比较常见的校正方法是三点校正法,它的原理是:
设LCD上每个点PD的坐标为[XD,YD],触摸屏上每个点PT的坐标为[XT,YT]。要实现触摸屏上的坐标转换为LCD上的坐标,需要下列公式进行转换:
XD=A×XT+B×YT+C
YD=D×XT+E×YT+F
因为其中一共有六个参数(A,B,C,D,E,F),因此只需要三个取样点就可以求得这六个参数。这六个参数一旦确定下来,只要给出任意触摸屏上的坐标点PT,代入这个公式,就可以得到它所对应的LCD上像素点的坐标PD。具体的求解过程就不细讲,只给出最终的结果。已知LCD上的三个取样点为:PD0,PD1,PD2,它们所对应的触摸屏上的三个点为:PT0,PT1,PT2。A,B,C,D,E,F这六个参数最终的结果都是一个分式,而且都有一个共同的分母,为:
K=(XT0-XT2)×(YT1-YT2)-(XT1-XT2)×(YT0-YT2)
那么这六个参数分别为:
A=[(XD0-XD2)×(YT1-YT2)-(XD1-XD2)×(YT0-YT2)] / K
B=[(XT0-XT2)×(XD1-XD2)-(XD0-XD2)×(XT1-XT2)] / K
C=[YT0×(XT2×XD1-XT1×XD2)+YT1×(XT0×XD2-XT2×XD0)+YT2×(XT1×XD0-XT0×XD1)] / K
D=[(YD0-YD2)×(YT1-YT2)-(YD1-YD2)×(YT0-YT2)] / K
E=[(XT0-XT2)×(YD1-YD2)-(YD0-YD2)×(XT1-XT2)] / K
F=[YT0×(XT2×YD1-XT1×YD2)+YT1×(XT0×YD2-XT2×YD0)+YT2×(XT1×YD0-XT0×YD1)] / K
下面的程序是实现触摸屏功能的简单实例——以触点为中心,绘制出一个红色的边长为10个像素的正方形。触点的坐标是用下面方法得到的:当触笔落下时,进入中断,然后读取触点处的坐标,直到触笔的抬起,才退出该次中断。由于触摸屏需要校正,因此在使用之前需要进行校正处理。但并不是每次使用都要校正,只要坐标没有发生漂移,就不需要再次校正。所以在进行一次校正后,只要把那几个参数保存起来,下次需要时直接使用上次保存下来的参数即可。在这里,我们利用EEPROM来保存这几个参数,即A,B,C,D,E,F,K分别保存在以0x20,0x30,0x40,0x50,0x60,0x70,0x80为首地址内存的连续4个字节空间内,另外内存地址0x1F保存一个标识信息,当为0x6A时,表示这几个参数已计算并保存好了,只需从上述内存地址中读取参数就行,而当为其他值时,就需要进行校正。校正时,需要三个取样点,在这里我们选取LCD上的(32,24),(160,216),(288,120)为这三个取样点,我们在这三个取样点上画一个十字(如下图所示),只需要依次点击这三个点,即可完成触摸屏的校正。
以上文字从网上摘录。觉得写得不错,当做笔记记下,我下面贴出的方法为裸奔三部曲中的方法,我验证了一下,不错,误差很小了,不到4个像素点。下面只贴出触摸屏初始化函数和中断函数的代码
- void Touch_Init(void)
- {
- rADCDLY = 50000; //正常转换模式下延时
- rADCCON = (1<<14)|(ADCPRS<<6); //使能AD转换预分频器
- rADCTSC = 0xd3; //等待中断模式,正常AD转换,XP上拉使能,XP,XM,YP输出禁止,YM输出使能
- if(rSRCPND &BIT_ADC) rSRCPND |= BIT_ADC;
- if(rINTPND & BIT_ADC) rINTPND |= BIT_ADC;
- if(rSUBSRCPND & BIT_SUB_TC) rSUBSRCPND|= BIT_SUB_TC;
- if(rSUBSRCPND & BIT_SUB_ADC)rSUBSRCPND |= BIT_SUB_ADC; //清除中断标志
- rINTMSK &=~BIT_ADC;
- rINTSUBMSK &=~(BIT_SUB_TC); //使能中断
- pISR_ADC =(unsigned)AdcTsAuto; //中断服务程序入口
- }
- void __irq AdcTsAuto(void)
- {
- unsigned int i;
- U32 PtX[6], PtY[6];
- short temp;
- if(rADCDAT0&0x8000)
- {
- rADCTSC&=0xff; // Set stylus down interrupt bit
- }
- rADCTSC =(1<<3)|(1<<2); //XP上拉禁止,自动顺序X,Y测量
- //rADCDLY = 50000;
- rADCCON |=0x1; //使能AD转换
- for(i=0;i<5;i++)
- {
- while(rADCCON & 0x1); //判断使能ADC转换后被清零
- while(!(rADCCON &0x8000)); //等待转换结束
- while(!(rSRCPND &(BIT_ADC))); //check if ADC is finished with interrupt bit
- PtX[i]=(rADCDAT0&0x3ff);
- PtY[i]=(rADCDAT1&0x3ff);
- }
- PtX[5]=(PtX[0]+PtX[1]+PtX[2]+PtX[3]+PtX[4])/5;
- PtY[5]=(PtY[0]+PtY[1]+PtY[2]+PtY[3]+PtY[4])/5;
- xdata=PtX[5];
- ydata=PtY[5];
- xdata*=0.272;
- ydata*=0.480;
- ydata=480-ydata;
- temp=ydata;
- ydata=xdata;
- xdata=temp;
- xdata=(xdata-20.0303)/0.8972;
- ydata=(ydata-37.86667)/0.7486; //将触摸屏的AD转换值转换为LCD像素点的值
- //check Stylus Up Interrupt.
- rSUBSRCPND|=BIT_SUB_TC;
- ClearPending(BIT_ADC);
- rINTSUBMSK=~(BIT_SUB_TC);
- rINTMSK=~(BIT_ADC); //清中断标志,再次使能中断
- rADCTSC =0xd3; //再次设置等待中断模式,这一次是判断触笔的抬起
- rADCTSC=rADCTSC|(1<<8); // 检测笔尖抬起中断信号
- while(1) //to check Pen-up state
- {
- if(rSUBSRCPND & (BIT_SUB_TC)) //check if ADC is finished with interrupt bit
- {
- break; //if Stylus is up(1) state
- }
- }
- Uart_Printf("count=%03d XP=%04d, YP=%04d\n", count++, xdata, ydata); //X-position Conversion data
- //rADCDLY = 50000;
- rADCTSC=rADCTSC&~(1<<8); // Detect stylus Down interrupt signal.
- rSUBSRCPND|=BIT_SUB_TC;
- rINTSUBMSK=~(BIT_SUB_TC); // Unmask sub interrupt (TC)
- ClearPending(BIT_ADC); //再次清A/D中断
- }
上一篇:S3C2440看门狗定时器
下一篇:S3C2440 LCD字符显示
推荐阅读最新更新时间:2024-03-16 14:50