关于这个ucos搞了一个月了,最近3周左右的时间都耗在这个触摸屏的效准上,真是郁闷死洒家了,小弟数学不是很好,今天突然想起了一个测试算法,于是拿来实验,效果不错,先分享一下。网上关于触摸屏的资料很多,其中巨大部分多是小屏的,其算法也多为2点,3点效验,我都测试过,误差较大。关于五点效验的算法很少,我朋友说,触摸屏效验就是个线性函数的问题,但是我参看资料搞了一周多也没弄明白,搁浅了几天,上周末突然到一份资料里面提到的k = y / x 来确定是五点钟的那个区域的意思。但是这篇文字提供的关于系数的计算公式有点错误,在另外一篇英文文档里面提供了,详细的效验算法的分析,提供了正确的公式,结合两篇文字,浑浑噩噩,郁闷好几天的我,总算是搞清楚了。现提供部分源码如下,各位多指点一下。
Touch目录下的 GUI_TOUCH_DriverAnalog.c文件,添加修改如下
void myAD2XY( int *adx , int *ady ){
f_dat = (float)(*ady - admy)/(float)(*adx - admx);
if(f_dat>0){
if( *adx>admx && admk[2] >=f_dat) dat1 = 1;
else if( *adx>admx && admk[2] < f_dat ) dat1 =2;//2
else if( *adx<admx && admk[0] >=f_dat ) dat1 =0;
else if( *adx<admx && admk[0] < f_dat ) dat1 =3;//0
else{ dat1 =0; }//*adx =0;*ady =0; }
}else{
if( *adx>admx && admk[1] >=f_dat) dat1 = 0;
else if( *adx>admx && admk[1] < f_dat ) dat1 =1;//1
else if( *adx<admx && admk[3] >=f_dat ) dat1 =3;
else if( *adx<admx && admk[3] < f_dat ) dat1 =2;//3
else{ dat1 =0; }//*adx =0;*ady =0; }
}
*adx = (int)(Factors[dat1][0].a*(*adx)+Factors[dat1][0].b*(*ady)+Factors[dat1][0].c);
*ady = (int)(Factors[dat1][1].a*(*adx)+Factors[dat1][1].b*(*ady)+Factors[dat1][1].c);
}
void GUI_TOUCH_Exec(void) {
#ifndef WIN32
static U32 i, saveAdcdly = 0;
U32 point_adcx=0 , point_adcy=0 ;
static int cs =0;
static int xPhys, yPhys ,x=0,y=0;
/* if (xyMinMax[GUI_COORD_X].Min < xyMinMax[GUI_COORD_X].Max) {
xMin = xyMinMax[GUI_COORD_X].Min;
xMax = xyMinMax[GUI_COORD_X].Max;
} else {
xMax = xyMinMax[GUI_COORD_X].Min;
xMin = xyMinMax[GUI_COORD_X].Max;
}
if (xyMinMax[GUI_COORD_Y].Min < xyMinMax[GUI_COORD_Y].Max) {
yMin = xyMinMax[GUI_COORD_Y].Min;
yMax = xyMinMax[GUI_COORD_Y].Max;
} else {
yMax = xyMinMax[GUI_COORD_Y].Min;
yMin = xyMinMax[GUI_COORD_Y].Max;
}
*/
rINTSUBMSK|=(BIT_SUB_ADC|BIT_SUB_TC); // Mask sub interrupt (ADC and TC)
if(rADCTSC&0x100)//rADCDAT0&0x8000)
{
rADCTSC&=0xff; // Set stylus down interrupt bit
GUI_TOUCH_StoreState(-1,-1);
}else{
rADCTSC = rADCTSC|(1<<3)|(1<<2); //Pull-up disable, Seq. X,Y postion measure.
saveAdcdly=rADCDLY;
rADCDLY=40000; //Normal conversion mode delay about (1/50M)*40000=0.8ms
for( i=0 ; i<8 ; i++){
rADCCON|=0x1; //start ADC
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~!!
while(!(rSRCPND & (BIT_ADC))); //check if ADC is finished with interrupt bit
point_adcx = point_adcx + (rADCDAT0&0x3ff);
point_adcy = point_adcy + (rADCDAT1&0x3ff);
}
xPhys = point_adcx>>3;
yPhys = point_adcy>>3;
#if !GUI_TOUCH_SWAP_XY //Is X/Y swapped ?
x = xPhys;
y = yPhys;
#else
x = yPhys;
y = xPhys;
#endif
for( i=0;i<50000;i++ );
if ((x <GUI_TOUCH_AD_LEFT) | (x>GUI_TOUCH_AD_RIGHT) | (y <GUI_TOUCH_AD_TOP) | (y>GUI_TOUCH_AD_BOTTOM)) {
// if ((x <xMin) | (x>xMax) | (y <yMin) | (y>yMax)) {
GUI_TOUCH_StoreState(-1,-1);
} else {
if( cs<5 ){
cs++;
}else{
// x = AD2X(x);
// y = AD2Y(y);
myAD2XY( &x ,&y );
}
GUI_TOUCH_StoreState(x,y);
}
rADCDLY=saveAdcdly;
rADCTSC=0xd3; //Wfait,XP_PU,XP_Dis,XM_Dis,YP_Dis,YM_En
}
rSUBSRCPND|=BIT_SUB_TC;
rINTSUBMSK=~(BIT_SUB_TC); // Unmask sub interrupt (TC)
ClearPending(BIT_ADC);
#endif // WIN32
}
void GUI_myTOUCH_Calibrate(int *Logx, int *Logy, int *xPhys, int *yPhys){
int move , mnext;
admx = xPhys[4];
admy = yPhys[4];
for( move =0 ; move<4; move++ ){
if( move == 3 ) mnext =0;
else mnext = move +1;
dat2 = yPhys[move] - yPhys[4];
dat1 = xPhys[move] - xPhys[4];
admk[move] = ((float)dat2/(float)dat1);
// mk = admk[move] = (yPhys[move] - yPhys[4])/(xPhys[move] - xPhys[4]);
/* dat = ((xPhys[move]-xPhys[4])*(yPhys[mnext]-yPhys[4]))-((xPhys[mnext]-xPhys[4])*(yPhys[move]-yPhys[4]));
*/
dat1 = xPhys[move]-xPhys[4];
dat2 = yPhys[mnext]-yPhys[4];
dat1 = dat1*dat2;
dat3 = xPhys[mnext]-xPhys[4];
dat2 = yPhys[move]-yPhys[4];
dat3 = dat3*dat2;
f_dat = (float)dat1-(float)dat3;
/* mk = Factors[move][0].a = /
(((Logx[move]-Logx[4])*(yPhys[mnext]-yPhys[4]))-((Logx[mnext]-Logx[4])*(yPhys[move]-yPhys[4])))/dat;
*/ dat1 = Logx[move]-Logx[4];
dat2 = yPhys[mnext]-yPhys[4];
dat1 = dat1*dat2;
dat3 = Logx[mnext]-Logx[4];
dat2 = yPhys[move]-yPhys[4];
dat3 = dat2*dat3;
dat1 = dat1-dat3;
Factors[move][0].a = (float)dat1/f_dat;
/* mk = Factors[move][0].b = /
((Logx[mnext]-Logx[4])*(xPhys[move]-xPhys[4])-(Logx[move]-Logx[4])*(xPhys[mnext]-xPhys[4]))/dat;
*/ dat1 = Logx[mnext]-Logx[4];
dat2 = xPhys[move]-xPhys[4];
dat1 = dat1*dat2;
dat3 = Logx[move]-Logx[4];
dat2 = xPhys[mnext]-xPhys[4];
dat3 = dat2*dat3;
dat1 = dat1-dat3;
Factors[move][0].b = (float)dat1/f_dat;
/* mk = Factors[move][0].c = (Logx[move]*(xPhys[mnext]*yPhys[4]-xPhys[4]*yPhys[mnext])/
+Logx[mnext]*(xPhys[move]*yPhys[4]-xPhys[4]*yPhys[move])/
+Logx[4]*(xPhys[move]*yPhys[mnext]-xPhys[mnext]*yPhys[move]))/dat;
*/ dat1 = xPhys[mnext]*yPhys[4]-xPhys[4]*yPhys[mnext];
dat1 = Logx[move]*dat1;
dat2 = xPhys[move]*yPhys[4]-xPhys[4]*yPhys[move];
dat2 = dat2*Logx[mnext];
dat3 = xPhys[move]*yPhys[mnext]-xPhys[mnext]*yPhys[move];
dat3 = dat3*Logx[4];
dat1 = dat1-dat2+dat3;
Factors[move][0].c = (float)dat1/f_dat;
/* mk = Factors[move][1].a = /
((Logy[move]-Logy[4])*(yPhys[mnext]-yPhys[4])-(Logy[mnext]-Logy[4])*(yPhys[move]-yPhys[4]))/dat;
*/ dat1 = Logy[move]-Logy[4];
dat2 = yPhys[mnext]-yPhys[4];
dat1 = dat1*dat2;
dat3 = Logy[mnext]-Logy[4];
dat2 = yPhys[move]-yPhys[4];
dat3 = dat2*dat3;
dat1 = dat1-dat3;
Factors[move][1].a = (float)dat1/f_dat;
/* mk = Factors[move][1].b = /
((xPhys[move]-xPhys[4])*(Logy[mnext]-Logy[4])-(xPhys[mnext]-xPhys[4])*(Logy[move]-Logy[4]))/dat;
*/ dat1 = xPhys[move]-xPhys[4];
dat2 = Logy[mnext]-Logy[4];
dat1 = dat1*dat2;
dat3 = xPhys[mnext]-xPhys[4];
dat2 = Logy[move]-Logy[4];
dat3 = dat3*dat2;
dat1 = dat1-dat3;
Factors[move][1].b = (float)dat1/f_dat;
/* mk = Factors[move][1].c = (Logy[move]*(xPhys[mnext]*yPhys[4]-xPhys[4]*yPhys[mnext])/
+Logy[mnext]*(xPhys[move]*yPhys[4]-xPhys[4]*yPhys[move])/
+Logy[4]*(xPhys[move]*yPhys[mnext]-xPhys[mnext]*yPhys[move]))/dat;
*/ dat1 = xPhys[mnext]*yPhys[4]-xPhys[4]*yPhys[mnext];
dat1 = Logy[move]*dat1;
dat2 = xPhys[move]*yPhys[4]-xPhys[4]*yPhys[move];
dat2 = Logy[mnext]*dat2;
dat3 = xPhys[move]*yPhys[mnext]-xPhys[mnext]*yPhys[move];
dat3 = Logy[4]*dat3;
dat1 = dat1-dat2+dat3;
Factors[move][1].c = (float)dat1/f_dat;
}
}
GUIDemo目录下GUIDEMO_Touch.c文件,修改如下:
extern void GUI_myTOUCH_Calibrate(int *Logx, int *Logy, int *xPhys, int *yPhys);
void _ExecCalibration(void) {
int ax_Phys[5],ay_Phys[5];
int move;
/* calculate log. Positions */
int ax[5] = { 50, LCD_XSIZE-50, LCD_XSIZE-50, 50, (LCD_XSIZE/2)-10};
int ay[5] = { 50, 50, LCD_YSIZE-50, LCD_YSIZE-50, (LCD_YSIZE/2)-10};
// int ax[5] = { 120, LCD_XSIZE-120, LCD_XSIZE-120, 120, 400};
// int ay[5] = { 20, 20, LCD_YSIZE-20, LCD_YSIZE-20, 300};
// GUI_TOUCH_SetDefaultCalibration();
/* _Calibrate upper left */
for( move =0 ; move<5; move++){
GUI_SetBkColor(GUI_RED);
GUI_Clear();
GUI_SetColor(GUI_WHITE); GUI_FillCircle(ax[move], ay[move], 10);
GUI_SetColor(GUI_RED); GUI_FillCircle(ax[move], ay[move], 5);
GUI_SetColor(GUI_WHITE);
do {
GUI_TOUCH_tState State;
GUI_TOUCH_GetState(&State);
if (State.Pressed) {
ax_Phys[move] = State.x;//GUI_TOUCH_GetxPhys();
ay_Phys[move] = State.y;//GUI_TOUCH_GetyPhys();
break;
}
GUI_Delay (100);
} while (1);
GUI_Delay (50);
/* release */
GUI_TOUCH_StoreState(-1,-1);
}
GUI_myTOUCH_Calibrate(ax,ay,ax_Phys,ay_Phys);
GUI_Delay(100);
GUI_DispStringAt ("Please touch display to continue...",50,20);
GUI_TOUCH_StoreState(-1,-1);
do {
GUI_TOUCH_tState State;
GUI_TOUCH_GetState(&State);
if (State.Pressed)
break;
GUI_Delay (10);
} while (1);
}
这样就ok了,