触摸屏校正的方法这里使用的是三点校正。
设LCD屏上的点为[Xd,Yd],触摸屏上的点为[X,Y]
校正的公式:
Xd = A*X + B*Y + C;
Yd = D*X + E*Y + F;
这里有六个参数,所以需要三个点。最后计算公式:
K=(XT0-XT2)×(YT1-YT2)-(XT1-XT2)×(YT0-YT2)
A=[(XD0-XD2)×(YT1-YT2)-(XD1-XD2)×(YT0-YT2)] / K
B=[(XT0-XT2)×(XD1-XD2)-(XD0-XD2)×(XT1-XT2)] / K
C=[YT0×(XT2×XD1-XT1×XD2)+YT1×(XT0×XD2-XT2×XD0)+YT2×(XT1×XD0-XT0×XD1)] / K
D=[(YD0-YD2)×(YT1-YT2)-(YD1-YD2)×(YT0-YT2)] / K
E=[(XT0-XT2)×(YD1-YD2)-(YD0-YD2)×(XT1-XT2)] / K
F=[YT0×(XT2×YD1-XT1×YD2)+YT1×(XT0×YD2-XT2×YD0)+YT2×(XT1×YD0-XT0×YD1)] / K
#ifndef TOUCH_H
#define TOUCH_H
#include "2440addr.h"
#include "config.h"
#define PRSCEN 1 //使能分频
#define PRSCVL 49 //分频系数
/* 设置为等待中断 */
#define waitDownInit() do{ \
rADCTSC = 0xd3;\
}while(0)
__irq void touchISR();
void touchInit(void);
static void delay(int time);
#endif
#include "TOUCH.h"
#include "uart.h"
#include "2440addr.h"
#include "IIC.h"
volatile int x,y;
static volatile int flag;
volatile int flagTS;
__irq void touchISR()
{
/* 松开产生的中断 */
if (rADCTSC & (0x100))
{
rADCTSC &= 0xff;
}
else /* 按下产生的中断 */
{
/* 在检测XY坐标时要禁止上拉,这里设置为自动转换 */
rADCTSC = (1<<3) | (1<<2);
/* 开启AD转换 */
rADCCON |= 1;
/* 等待AD转换开启 */
while(rADCCON & 1)
;
/* 等待AD转换结束 */
while(!(rADCCON & (1<<15)))
;
/* 设置为检测松开中断 */
rADCTSC = (1<<8) | 0xd3;
/* 读取XY坐标值 */
x = rADCDAT0 & 0x3ff;
y = rADCDAT1 & 0x3ff;
flag = 0; /* 用于校正参数函数的轮询(等待三个触摸点被按下) */
flagTS = 1; /* 用于主函数轮询触摸点是否更新,即是否按下触摸屏 */
}
rSUBSRCPND = (1<<9);
rSRCPND = 1<<31;
rINTPND = 1<<31;
}
void touchInit(void)
{
pISR_ADC = (unsigned int)touchISR;
/* 设置延时,之前没加的时候一按下就出了好多个数据,转换太快了 */
rADCDLY = 50000;
rADCCON = (PRSCEN<<14) | (PRSCVL<<6);
/* 刚开始的时候设置为等待中断 */
waitDownInit();
rINTMSK &= ~(1<<31);
rINTSUBMSK &= ~(1<<9);
}
int A,B,C,D,E,F,K;
static int Xt[3];
static int Yt[3];
/* 三个LCD点 */
static int Xd[3] = {32,160,288};
static int Yd[3] = {24,216,120};
/* 使用三点校正算法 */
void correctTouch(void)
{
int i;
/* 依次获取三个触摸屏点 */
for(i=0; i<3; i++)
{
flag = 1;
while(flag==1)
delay(100);
Xt[i] = x;
Yt[i] = y;
}
/* 计算校正参数 */
K = (Xt[0] - Xt[2])*(Yt[1]-Yt[2]) - (Xt[1] - Xt[2])*(Yt[0]-Yt[2]);
A = ((Xd[0] - Xd[2])*(Yt[1]-Yt[2]) - (Xd[1]-Xd[2])*(Yt[0]-Yt[2]));
B = ((Xt[0]-Xt[2])*(Xd[1]-Xd[2]) - (Xd[0] - Xd[2])*(Xt[1]-Xt[2]));
C = Yt[0]*(Xt[2]*Xd[1]-Xt[1]*Xd[2])+Yt[1]*(Xt[0]*Xd[2]-Xt[2]*Xd[0])+Yt[2]*(Xt[1]*Xd[0]-Xt[0]*Xd[1]);
D = (Yd[0]-Yd[2])*(Yt[1]-Yt[2])-(Yd[1]-Yd[2])*(Yt[0]-Yt[2]);
E = (Xt[0]-Xt[2])*(Yd[1]-Yd[2])-(Yd[0]-Yd[2])*(Xt[1]-Xt[2]);
F = Yt[0]*(Xt[2]*Yd[1]-Xt[1]*Yd[2])+Yt[1]*(Xt[0]*Yd[2]-Xt[2]*Yd[0])+Yt[2]*(Xt[1]*Yd[0]-Xt[0]*Yd[1]);
}
static void delay(int time)
{
int i,j;
for(i=0; i<time;i++)
for(j=0;j<1000;j++)
;
}
#include "2440addr.h"
#include "config.h"
#include "TouchScreen.h"
#include "TOUCH.h"
#include "IIC.h"
extern int flagTS;
extern int x,y;
extern int A,B,C,D,E,F,K;
static void delay(int time);
volatile unsigned char c;
void Main()
{
unsigned int xLCD,yLCD;
LCD_Init();
uartInit(115200);
touchInit();
/* 触摸屏校正 */
correctTouch();
LCD_CLSR(0xffffff);
while(1)
{
if (flagTS)
{
flagTS = 0;
/* 将触摸屏上的点转换为LCD屏上的点 */
xLCD = (A*x + B*y + C)/K;
yLCD = (D*x + E*y + F)/K;
LCD_PaintCross(xLCD,yLCD,0xFF0000);
}
delay(1000);
}
}
static void delay(int time)
{
int i,j;
for(i=0; i<time;i++)
for(j=0;j<1000;j++)
;
}