触摸屏校准代码解析:实现原理与代码详解
该代码为触摸屏校准代码,主要功能是通过四个校准点的坐标以及三组校准点的距离,计算出触摸屏在屏幕上的实际位置与物理位置之间的关系(即校准参数),并将其存储下来。具体实现过程如下:
-
显示提示信息,要求用户按下四个校准点,并在连续10秒钟内完成校准,否则自动退出。
-
扫描物理坐标,如果检测到按键按下,则将坐标值存储到缓存数组中,并根据不同的点数,分别画出不同的校准点。
-
当四个校准点坐标值都被存储下来后,遍历三组校准点的距离是否在允许范围内。如果不合格,则清空之前的校准点,重新开始校准。如果合格,则进入下一步。
-
根据四个校准点的坐标值,计算出触摸屏在屏幕上的实际位置与物理位置之间的关系(即校准参数),并将其存储下来。如果触摸屏和预设的相反了,则修改触摸屏类型,并重新开始校准。
-
显示校正完成信息,并将校准参数存储到Flash中,以便下次使用时调用。
// 校准点参数:(0,1)与(2,3),(0,2)与(1,3),(1,2)与(0,3),这三组点的距离 const u8 TP_ADJDIS_TBL[3][4]={{0,1,2,3},{0,2,1,3},{1,2,0,3}};// 校准距离计算表
// 触摸屏校准代码 // 得到四个校准参数 void TP_Adjust(void) { u16 pos_temp[4][2];// 坐标缓存值 u8 cnt=0; u16 d1,d2; float fac; u16 outtime=0; u32 tem1,tem2; LCD_Clear(WHITE); // 清屏 POINT_COLOR=BLUE; // 蓝色 LCD_ShowString(40,40,160,100,16,(u8*)TP_REMIND_MSG_TBL);// 显示提示信息 TP_Drow_Touch_Point(20,20,RED);// 画点 1 tp_dev.sta=0;// 消除触发信号 tp_dev.xfac=0;// xfac 用来标记是否校准过,所以校准之前必须清掉!以免错误 while(1)// 如果连续 10 秒钟没有按下,则自动退出 { READJ: tp_dev.scan(1);// 扫描物理坐标 if((tp_dev.sta&0xc0)==TP_CATH_PRES)// 按键按下了一次(此时按键松开了.) { outtime=0; tp_dev.sta&=~(1<<6); // 标记按键已经被处理过了. pos_temp[cnt][0]=tp_dev.x[0]; pos_temp[cnt][1]=tp_dev.y[0]; cnt++; switch(cnt) { case 1: TP_Drow_Touch_Point(20,20,WHITE); // 清除点 1 TP_Drow_Touch_Point(lcddev.width-20,20,RED); // 画点 2 break; case 2: TP_Drow_Touch_Point(lcddev.width-20,20,WHITE); // 清除点 2 TP_Drow_Touch_Point(20,lcddev.height-20,RED); // 画点 3 break; case 3: TP_Drow_Touch_Point(20,lcddev.height-20,WHITE); // 清除点 3 TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,RED);// 点 4 break; case 4: // 全部四个点已经得到 for(cnt=0;cnt<3;cnt++)// 计算三组点的距离是否在允许范围内? { tem1=abs(pos_temp[TP_ADJDIS_TBL[cnt][0]][0]-pos_temp [TP_ADJDIS_TBL[cnt][1]][0]);// x1-x2/x1-x3/x2-x3 tem2=abs(pos_temp[TP_ADJDIS_TBL[cnt][0]][1]-pos_temp [TP_ADJDIS_TBL[cnt][1]][1]);// y1-y2/y1-y3/y2-y3 tem1*=tem1; tem2*=tem2; d1=sqrt(tem1+tem2);// 得到两点之间的距离 tem1=abs(pos_temp[TP_ADJDIS_TBL[cnt][2]][0]-pos_temp [TP_ADJDIS_TBL[cnt][3]][0]);// x3-x4/x2-x4/x1-x4 tem2=abs(pos_temp[TP_ADJDIS_TBL[cnt][2]][1]-pos_temp [TP_ADJDIS_TBL[cnt][3]][1]);// y3-y4/y2-y4/y1-y4 tem1*=tem1; tem2*=tem2; d2=sqrt(tem1+tem2);// 得到两点之间的距离 fac=(float)d1/d2; if(fac<0.95||fac>1.05||d1==0||d2==0)// 不合格 { cnt=0; TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,WHITE); // 清除点 4 TP_Drow_Touch_Point(20,20,RED); // 画点 1 TP_Adj_Info_Show(pos_temp[0][0],pos_temp[0][1], pos_temp[1][0],pos_temp[1][1],pos_temp[2][0], pos_temp[2][1],pos_temp[3][0],pos_temp[3][1],fac100); goto READJ; // 不合格,重新校准 } } // 正确了 tp_dev.xfac=(float)(lcddev.width-40)/(pos_temp[1][0]- pos_temp[0][0]);// 得到 xfac tp_dev.xoff=(lcddev.width-tp_dev.xfac(pos_temp[1][0]+ pos_temp[0][0]))/2;// 得到 xoff tp_dev.yfac=(float)(lcddev.height-40)/(pos_temp[2][1]- pos_temp[0][1]);// 得到 yfac tp_dev.yoff=(lcddev.height-tp_dev.yfac*(pos_temp[2][1]+ pos_temp[0][1]))/2;// 得到 yoff if(abs(tp_dev.xfac)>2||abs(tp_dev.yfac)>2)// 触屏和预设的相反了. { cnt=0; TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,WHITE); // 清除点 4 TP_Drow_Touch_Point(20,20,RED); // 画点 1 LCD_ShowString(40,26,lcddev.width,lcddev.height,16,'TP Need readjust!'); tp_dev.touchtype=!tp_dev.touchtype;// 修改触屏类型. if(tp_dev.touchtype)// X,Y 方向与屏幕相反 { CMD_RDX=0X90; CMD_RDY=0XD0; }else { CMD_RDX=0XD0; CMD_RDY=0X90; }// 与屏相同 continue; } POINT_COLOR=BLUE; LCD_Clear(WHITE);// 清屏 LCD_ShowString(35,110,lcddev.width,lcddev.height,16,'Touch Screen Adjust OK!');// 校正完成 delay_ms(1000); TP_Save_Adjdata(); LCD_Clear(WHITE);// 清屏 return;// 校正完成 } } delay_ms(10); outtime++; if(outtime>1000) { TP_Get_Adjdata();break; } } }
原文地址: https://www.cveoy.top/t/topic/neOl 著作权归作者所有。请勿转载和采集!