触摸屏为什么点不准之触摸屏校准教程
嵌入式环境下,触摸屏是鼠标的替代也是升级输入设备,下面我们来研究一下触摸屏。
1.基础知识
触摸屏的原理这里不讲,只说下大体思路,触摸屏硬件能够接收到来自用于的触摸,通过若干方式,把数据转换成坐标,此时,坐标是物理坐标,即触摸屏的坐标,而不是显示设备的坐标,显示设备的坐标由软件来定义,而触摸屏的物理坐标是固定的。所以,当我们点击触摸屏,数据被送给驱动,驱动送给应用程序时,我们得到的数据还不是真正的显示设备数据哦,比如点击一点,硬件传来的是(189,
123),(我们约定x在前),这时如果我们说,屏幕上的(189,123)点有点击,这时不正确的,这个很容易明白的,物理的点只是采样到的点,并不是真正意义上的显示设备的坐标,毕竟显示坐标由我们来定。那么怎么办呢?~这时,需要校准触摸屏,所有的触摸屏使用前,必须要经过校准。
2.触摸屏校准原理
以上说了触摸屏需要校准的原因,问题出在,物理坐标和屏幕坐标并不匹配,不匹配有两个方面:
第一,物理坐标的1个单位和屏幕坐标的1个单位并不相等,我们知道屏幕坐标1个单位一般是一个像素,而物理坐标的1个单位并不是1个像素.
第二,假设我们把屏幕的左上角定义为(0,0),那么触摸屏的左上角的物理坐标并不是(0, 0)(我们点击之后的物理采样数据)。
综上,校准有两个方面:
第一,物理采样坐标与屏幕像素坐标的对应关系,也就是伸缩系数,即单位物理采样数据代表几个单位屏幕像素数据,x坐标和y坐标各有一个伸缩系数,分别记作:xScale和yScale。计算方法很简单,为了精确,可以采样屏幕上的四个点,让用户点击,比如(20,
20),(20,200),(300, 200),(300, 20),通过横着的线段除以物理采样的数据线段,得到了x的伸缩系数。同理可以得到y的伸缩系数。
第二,物理坐标的相对于屏幕像素坐标的偏移,假如我们不计算偏移,只计算伸缩系数的话,假设用户在屏幕点(20, 20)点击,我们经过转换物理采样数据,即乘上伸缩系数,发现,校准后的数据并不是(20,20)点,原因就是因为有偏移,原因是触摸屏的物理采样数据,在左上角并不是(0,0),而是某个正数对,采样到的数据不会是0的,这就是偏移产生的原因,所以,在计算过伸缩系数之后,比如点击屏幕(20,20),采样到的数据是(45,78),而第一步计算出的伸缩系数分别是0.78和0.67,那么物理坐标转换成屏幕坐标后是(45*0.78,
78*0.67),此时虽然我们得到了物理坐标对应的屏幕坐标,但是现在屏幕坐标和我们(20,20)所在的屏幕坐标并不在一个坐标系,即(0,0)点不同,所以我们要减去一个坐标系偏移,假设分别是xOffset和yOffset,那么两个坐标做差便得到了xOffset和yOffset。根据上面的四个参数,我们来举个例子,假如屏幕坐标左上角为(0,0),当我们点击屏幕,此时我们从驱动那里得到物理x和y数据,分别乘上xScale和yScale得到相对屏幕坐标,减去(平移)xOffset和yOffset,得到了当前的屏幕坐标。
3.示例代码:
typedef struct tagDATA
{
double xScale; //物理坐标x和lcd像素坐标x的比例关系,即每个物理坐标代表多少个像素坐标,真实的坐标x=测量出的物理坐标*xScale
double yScale; //同上
int xOffset; //x轴偏移,即物理坐标12,12如果是lcd左上角的点的物理采样数据,那么x偏移是12-0
int yOffset; //同上
int turn; //旋转角度,即把触摸屏的直线定义为0度,lcd上相同的一条直线相对于0度的偏移角度(暂时不使用)
}TSCALDATA;
intpointBas[5][2] =
{
0, 0,
20, 20,
20, 200,
300, 200,
300, 20,
};
//4个校准点,从物理采样得到
int pointGet[5][2];
double tmpBas =0.0;
double tmpGet = 0.0;
//xScale
tmpBas = (( (double)pointBas[4][0] -(double)pointBas[1][0] ) + ( (double)pointBas[3][0] -(double)pointBas[2][0]))/2.0;
tmpGet = (( (double)pointGet[4][0] -(double)pointGet[1][0] ) + ( (double)pointGet[3][0] -(double)pointGet[2][0]))/2.0;
tsCalData.xScale = tmpBas/tmpGet;
//yScale
tmpBas = (( (double)pointBas[2][1] -(double)pointBas[1][1] ) + ( (double)pointBas[3][1] -(double)pointBas[4][1]))/2.0;
tmpGet = (( (double)pointGet[2][1] -(double)pointGet[1][1] ) + ( (double)pointGet[3][1] -(double)pointGet[4][1]))/2.0;
tsCalData.yScale = tmpBas/tmpGet;
//xOffset
tmpBas = (((double)pointGet[4][0]*tsCalData.xScale - (double)pointBas[4][0] ) + ((double)pointGet[1][0]*tsCalData.xScale - (double)pointBas[1][0]))/2.0;
tsCalData.xOffset = (int)tmpBas;
//yOffset
tmpBas = (( (double)pointGet[4][1]*tsCalData.yScale- (double)pointBas[4][1] ) + ( (double)pointGet[1][1]*tsCalData.yScale -(double)pointBas[1][1]))/2.0;
tsCalData.yOffset = (int)tmpBas;
//write data tofile
datFd =fopen("../etc/tsCalDat", "wb+");
fwrite(&tsCalData, sizeof(TSCALDATA),1, datFd);
fclose(datFd);