首先移植的是liujun6037的代码,他的代码思路为:对X、Y的坐标连续采样十次;不足十次则认为数据无效,不做任何操作;然后对十次数据进行排序;最后取中间三次的数据进行平均,得到最终的X、Y坐标。不同的是,我把冒泡排序换成我常用的选择排序,其实还是O(n^2)。其效果如图1所示。可以清楚地看到,本次尝试很失败,有很多莫名其妙的散点。
代码1 第一种尝试
view source print ? 01void ads_GetXY(void) 02{ 03 u8 cnt=0; 04 u8 i, j, k, min; 05 u16 temp; 06 u16 tempXY[2][9], XY[2]; 07 do 08 { 09 if(ads_ReadXY()) 10 { 11 tempXY[0][cnt] = X; 12 tempXY[1][cnt] = Y; 13 cnt++; 14 } 15 }while(cnt<9); 16 if(cnt==9) 17 { 18 for(k=0; k<2; k++) 19 { // 降序排列 20 for(i=0; i<cnt-1; i++) 21 { 22 min=i; 23 for (j=i+1; j<cnt; j++) 24 { 25 if (tempXY[k][min] > tempXY[k][j]) min=j; 26 } 27 temp = tempXY[k][i]; 28 tempXY[k][i] = tempXY[k][min]; 29 tempXY[k][min] = temp; 30 } 31 // 求中间值的均值 32 XY[k] = (tempXY[k][3]+tempXY[k][4]+tempXY[k][5]+tempXY[k][6]) / 4; 33 } 34 } 35 // 矫正坐标 36 X = ((XY[0]-350)/11); 37 Y = ((XY[1]-400)/14); 38}图1 第一种尝试
由于第一种尝试比较失败,我就在网上搜到了参考2的算法。尝试了一下,效果极差,线条极其发散,图片就不贴了。代码贴到这里作为反面例程。
代码2 第二种尝试
view source print ? 01void ads_GetXY(void) 02{ 03 u8 cnt=0; 04 u8 i, j, k, min; 05 u16 temp; 06 u16 tempXY[2][9], avgXY[2][3], XY[2]; 07 s16 diffXY[2][3]; 08 do 09 { 10 if(ads_ReadXY()) 11 { 12 tempXY[0][cnt] = X; 13 tempXY[1][cnt] = Y; 14 cnt++; 15 } 16 }while(cnt<9); 17 if(cnt==9) 18 { 19 for(k=0; k<2; k++) 20 { // 取平均值 21 avgXY[k][0] = (tempXY[k][0]+tempXY[k][1]+tempXY[k][2])/3; 22 avgXY[k][1] = (tempXY[k][3]+tempXY[k][4]+tempXY[k][5])/3; 23 avgXY[k][2] = (tempXY[k][6]+tempXY[k][7]+tempXY[k][8])/3; 24 // 取差值 25 diffXY[k][0] = avgXY[k][0] - avgXY[k][1]; 26 diffXY[k][1] = avgXY[k][1] - avgXY[k][2]; 27 diffXY[k][2] = avgXY[k][2] - avgXY[k][0]; 28 // 取差值的绝对值 29 diffXY[k][0] = (diffXY[k][0] > 0) ? diffXY[k][0] : -diffXY[k][0]; 30 diffXY[k][1] = (diffXY[k][1] > 0) ? diffXY[k][1] : -diffXY[k][1]; 31 diffXY[k][2] = (diffXY[k][2] > 0) ? diffXY[k][2] : -diffXY[k][2]; 32 // 取最小的数得平均值 33 if(diffXY[k][0] < diffXY[k][1]) 34 { 35 if(diffXY[k][2] < diffXY[k][1]) 36 XY[k] = (avgXY[k][0]+avgXY[k][2])>>1; 37 else 38 XY[k] = (avgXY[k][0]+avgXY[k][1])>>1; 39 } 40 else if(diffXY[k][2] < diffXY[k][1]) 41 XY[k] = (avgXY[k][0]+avgXY[k][2])>>1; 42 else 43 XY[k] = (avgXY[k][1]+avgXY[k][2])>>1; 44 } 45 } 46 // 矫正坐标 47 X = ((XY[0]-350)/11); 48 Y = ((XY[1]-400)/14); 49}
既然第一种尝试的线条已经比较收敛,那么散点是怎么出来的呢?经过达克斯特兄的一点指导和我的多次实验,终于干掉了这个头疼的散点。原来虽然使用中位值平均滤波法可以稳定获取符合触摸屏范围的数据,但是却无法滤除跳变的散点。对于跳变的散点必须通过加阈值才能消除。下面贴出我的代码。代码思路:采样符合触摸屏范围的数据若干次,将其排序,取中间两位的差值;若差值大于阈值,则丢弃。因为数据已经排序,因此差值肯定是正值或零值,即无需申明为有符号数。同时由于阈值判断的加入,我们可以将数据的采样次数适当调整,此处仅为4次,所得效果已经非常令人满意。需要注意的是采样数据不宜过多,否则连续的线会变成离散的点。
代码3 第3种尝试
view source print ? 01#define SAMP_CNT 4 02#define SAMP_CNT_DIV2 2 03u8 ads_GetXY(void) 04{ 05 u8 i, j, k, min; 06 u16 temp; 07 u16 tempXY[2][SAMP_CNT], XY[2]; 08 // 采样 09 for(i=0; i<SAMP_CNT; i++) 10 { 11 if(ads_ReadXY()) 12 { 13 tempXY[0][i] = X; 14 tempXY[1][i] = Y; 15 } 16 } 17 // 滤波 18 for(k=0; k<2; k++) 19 { // 降序排列 20 for(i=0; i<SAMP_CNT-1; i++) 21 { 22 min=i; 23 for (j=i+1; j<SAMP_CNT; j++) 24 { 25 if (tempXY[k][min] > tempXY[k][j]) min=j; 26 } 27 temp = tempXY[k][i]; 28 tempXY[k][i] = tempXY[k][min]; 29 tempXY[k][min] = temp; 30 } 31 // 设定阈值 32 if((tempXY[k][SAMP_CNT_DIV2]-tempXY[k][SAMP_CNT_DIV2-1]) > 5) 33 return 0; 34 // 求中间值的均值 35 XY[k] = (tempXY[k][SAMP_CNT_DIV2]+tempXY[k][SAMP_CNT_DIV2-1]) / 2; 36 } 37 // 矫正坐标 38 X = ((XY[0]-350)/11); 39 Y = ((XY[1]-400)/14); 40 return 1; 41}