void __irq AdcTsAuto(void)
{
//解摸屏按下,产生中断
U32 saveAdcdly;
if(rADCDAT0&0x8000)
rADCTSC&=0xff; // Set stylus down interrupt bit
//关闭XP上拉,启动自动顺序x/y转换
rADCTSC=(1<<3)|(1<<2); //Pull-up disable, Seq. X,Y postion measure.
//设置延时时间
saveAdcdly=rADCDLY;
rADCDLY=40000;
//开始AD转换
rADCCON|=0x1; //start ADC
//AD转换启动后开始位会被清0
while(rADCCON & 0x1); //check if Enable_start is low
//等待转换结束
while(!(rADCCON & 0x8000)); //check if EC(End of Conversion) flag is high, This line is necessary~!!
//查询INT_ADC中断,直到查到结束中断标志
while(!(rSRCPND & (BIT_ADC))); //check if ADC is finished with interrupt bit
//产生中断标志说明x,y已经转换结束,读取数据。
xdata=(rADCDAT0&0x3ff);
ydata=(rADCDAT1&0x3ff);
//按下标志
touchedflag=TRUE;
//check Stylus Up Interrupt.
//清中断,并且重开中断,再次设置等待中断,这一次设置等待弹起中断。
rSUBSRCPND|=BIT_SUB_TC;
ClearPending(BIT_ADC);
rINTSUBMSK=~(BIT_SUB_TC);
rINTMSK=~(BIT_ADC);
rADCTSC =0xd3; //Waiting for interrupt
rADCTSC=rADCTSC|(1<<8); // Detect stylus up interrupt signal.
//查询等待弹起中断标志,直到查到弹起。
while(1) //to check Pen-up state
{
if(rSUBSRCPND & (BIT_SUB_TC)) //check if ADC is finished with interrupt bit
{
//Uart_Printf("Stylus Up Interrupt~!\n");
break; //if Stylus is up(1) state
}
}
//此时,一个触摸屏动作检测已经完成,输出坐标信息。
Uart_Printf("count=%03d XP=%d, YP=%d\n", count++, xdata, ydata); //X-position Conversion data
//再次设置成按下中断,等待下一次动作
rADCDLY=saveAdcdly;
rADCTSC=rADCTSC&~(1<<8); // Detect stylus Down interrupt signal.
rSUBSRCPND|=BIT_SUB_TC;
rINTSUBMSK=~(BIT_SUB_TC); // Unmask sub interrupt (TC)
ClearPending(BIT_ADC);
}
2、触摸屏的校正
触摸屏校正的目的是为了把触摸屏上的坐标跟LCD上坐标一一对应起来。
如上图,假设LCD与触摸屏的点是一一对应的,LCD上四个角的点为人为设置的点(实际只需要上左上跟右下两个点就可以了,还有两个点是用来做平均的),触摸屏上四个角的点为LCD上四个点对应转换来的数值。(ax,ay)为正常工作时点击的点,(x,y)为(ax,ay)对应的坐标。
那么LCD与触摸屏的关系为:
x=x0+(x1-x0)*(ax-ax0)/(ax1-ax0)
y=y0+(y1-y0)*(ay-ay0)/(ay1-ay0)
具体步骤:
以320*240的屏举例:
(1)、设置四个LCD点(30,30)、(30,210)、(290,210)、(290,30)
(2)、在屏幕上依次画出这四个点(以四个点为中心点的十字形),并且依次点击这四个点,分别记下四个点转换出来的数值。(ax0,ay0),(ax0,ax1),(ax1,ay1),(ax1,ay0)
(3)、由x=x0+(x1-x0)*(ax-ax0)/(ax1-ax0),可以把(x1-x0)/(ax1-ax0)转换成常量系数Kx,那么
x=x0+(ax-ax0)*Kx,Kx=(x1-x0)/(ax1-ax0) ,这样只需记下x0,ax0,Kx三个值便可。
同样的:
y=y0+(y1-y0)*(ay-ay0)/(ay1-ay0), y=y0+(ay-ay0)*Ky, Ky=(y1-y0)/(ay1-ay0),只需记下y0,ay0,Ky便可.
(4)、校正完成,正常工作时当点击触摸屏时产生(ax,ay),则
x=x0+(ax-ax0)*Kx
y=y0+(ay-ay0)*Ky
便可以很容易求出实际坐标。
校正程序如下:
//触摸屏校正
//x=x0+(x1-x0)*(ax-ax0)/(ax1-ax0)
//x=x0+(ax-ax0)*Kx
//Kx=(x1-x0)/(ax1-ax0)
//x0,ax0,Kx
//同理
//y=y0+(y1-y0)*(ay-ay0)/(ay1-ay0)
//y=y0+(ay-ay0)*Ky
//Ky=(y1-y0)/(ay1-ay0)
//y0,ay0,Ky
volatile U32 touchedflag=FALSE;
//必要的参数
typedef struct cali
{
int x0;
int ax0;
float Kx;
int y0;
int ay0;
float Ky;
}TCpara;
typedef struct Point
{
int x;
int y;
}POINT;
//LCD四个校正点
POINT LCDPoint[4]=
{
30 ,30, //左上
30 ,210, //左下
290 ,210, //右下
290 ,30 //右上
};
TCpara TCcal;
void touchsrc_calibration()
{
U32 i;
//int x=30,y=30;
//int LCDx1=30,LCDy1=30,LCDx2=30,LCDy2=150,LCDx3=290,LCDy3=210;
//TCx3=0,TCy3=0,TCx4=0,TCy4=0;
//float A,B,C,D,E,F,K;
//float K
Lcd_ClearScr(0);
for(i=0;i<4;i++)
{
//分别画出四个点 Glib_Line(LCDPoint[i].x-10,LCDPoint[i].y,LCDPoint[i].x+10,LCDPoint[i].y,(U32)(255<<11));
Glib_Line(LCDPoint[i].x,LCDPoint[i].y-10,LCDPoint[i].x,LCDPoint[i].y+10,(U32)(255<<11));
//等待按下
while(!touchedflag);
touchedflag=FALSE;
//分别记下LCD四个点对应的触摸屏的值,因为TQ2440触摸屏的x,接到了控制器的y上,y接到了x上,所以这里反过来记。
switch(i)
{
case 0:
TCx0+=ydata;
TCy0+=xdata;
break;
case 1:
TCx0+=ydata;
TCy1+=xdata;
break;
case 2:
TCx1+=ydata;
TCy1+=xdata;
break;
case 3:
TCx1+=ydata;
TCy0+=xdata;
break;
default:
break;
}
Lcd_ClearScr(0);
}
//得出左上与右下两个点的AD值,注意,其余两个点是为左上与右下两个点服务的。
TCx0=TCx0>>1;
TCx1=TCx1>>1;
TCy0=TCy0>>1;
TCy1=TCy1>>1;
//记下LCD初始点
TCcal.x0 =LCDPoint[0].x;
TCcal.y0 =LCDPoint[0].y;
//记下触摸屏初始点
TCcal.ax0=TCx0;
TCcal.ay0=TCy0;
//算出Kx,Ky
TCcal.Kx =(float)(LCDPoint[2].x-LCDPoint[0].x)/(TCx1-TCx0);
TCcal.Ky =(float)((LCDPoint[2].y)-LCDPoint[0].y)/(TCy1-TCy0);//(TCy0-TCy1);
Uart_Printf("TCcal.x0=%d,TCcal.y0=%d\n",TCcal.x0,TCcal.y0);
Uart_Printf("TCcal.ax0=%d,TCcal.ay0=%d\n",TCcal.ax0,TCcal.ay0);
Uart_Printf("TCcal.Kx=%d,TCcal.Ky=%d\n",TCcal.Kx,TCcal.Ky);
}
//打印坐标
void PrintTouchSrcPoint()
{
int TCx,TCy,x,y;
//等待按下
while(!touchedflag);
touchedflag=FALSE;
TCx=ydata;
TCy=xdata;
//算出x,y坐标
x=TCcal.x0+(TCx-TCcal.ax0)*TCcal.Kx;
y=TCcal.y0+(TCy-TCcal.ay0)*TCcal.Ky;
if((x>=0 && x<320) && (y>=0 && y<240))
{
//y=239-y;
Glib_Rectangle(x-1,y-1,x+1,y+1,(U32)(255<<11));
Glib_FilledRectangle(x-1,y-1,x+1,y+1,(U32)(255<<11));
}
Uart_Printf("x=%d,y=%d\n",x,y);
}