s3c2440的触摸屏应用与校正
时间:11-19
来源:互联网
点击:
iic_buffer[8];
unsigned char devAddr=0xa0;
int A,B,C,D,E,F,K;
volatile int xdata, ydata;
int flagIIC;//IIC标志
int flagTS;//触摸屏标志
…………
//触摸屏中断
void __irq ADCTs(void)
{
rADCTSC = (1<3)|(1<2);//上拉电阻无效,自动连续XY坐标转换模式开启
rADCDLY = 40000;//延时
rADCCON|=0x1;//开始A/D转换
while(rADCCON & 0x1)
;//检查A/D转换是否开始
while(!(rADCCON & 0x8000))
;//等待A/D转换的结束
while(!(rSRCPND & ((U32)0x1<31)))
;//判断A/D中断的悬挂位
xdata=(rADCDAT0&0x3ff);//读取X轴坐标
ydata=(rADCDAT1&0x3ff);//读取Y轴坐标
flagTS = 1;//置标志
rSUBSRCPND|=0x1<9;
rSRCPND = 0x1<31;
rINTPND = 0x1<31;
rINTSUBMSK=~(0x1<9);
rINTMSK=~(0x1<31);//清A/D中断,开启A/D中断屏蔽
rADCTSC =0xd3;//再次设置等待中断模式,这一次是判断触笔的抬起
rADCTSC=rADCTSC|(1<8);//设置触笔抬起中断
while(1)//等待触笔的抬起
{
if(rSUBSRCPND & (0x1<9))//检查A/D触摸屏中断悬挂
{
break;//如果触笔抬起,则跳出该循环
}
}
rADCDLY=50000;
rSUBSRCPND|=0x1<9;
rINTSUBMSK=~(0x1<9);
rSRCPND = 0x1<31;
rINTPND = 0x1<31;//再次清A/D中断,开启A/D中断屏蔽
rADCTSC =0xd3;//设置等待中断模式,为下一次触笔的落下做准备
}
//绘制“十”字型
void drawCross(U32 x,U32 y,U32 color)
{
int i;
for(i=x-10;i PutPixel(i,y, color);
for(i=y-10;i PutPixel(x,i, color);
}
//触摸屏校正
void TSCal(void)
{
int i=0;
int xt[3],yt[3];
Brush_Background(0,0,LCD_WIDTH,LCD_HEIGHT,0xFFFFFF);
drawCross(32,24,0xFF0000);
Draw_ASCII(36,28,0xFF0000,one);
drawCross(160,216,0xFF0000);
Draw_ASCII(164,220,0xFF0000,two);
drawCross(288,120,0xFF0000);
Draw_ASCII(292,124,0xFF0000,three);
//依次读取三个采样点的坐标值
for(i=0;i<3;i++)
{
while(flagTS==0)
delay(500);
xt[i]=xdata;
yt[i]=ydata;
flagTS=0;
}
//计算参数
K=(xt[0]-xt[2])*(yt[1]-yt[2])-(xt[1]-xt[2])*(yt[0]-yt[2]);
A=(32-288)*(yt[1]-yt[2])-(160-288)*(yt[0]-yt[2]);
B=(xt[0]-xt[2])*(160-288)-(32-288)*(xt[1]-xt[2]);
C=yt[0]*(xt[2]*160-xt[1]*288)+yt[1]*(xt[0]*288-xt[2]*32)+yt[2]*(xt[1]*32-xt[0]*160);
D=(24-120)*(yt[1]-yt[2])-(216-120)*(yt[0]-yt[2]);
E=(xt[0]-xt[2])*(216-120)-(24-120)*(xt[1]-xt[2]);
F=yt[0]*(xt[2]*216-xt[1]*120)+yt[1]*(xt[0]*120-xt[2]*24)+yt[2]*(xt[1]*24-xt[0]*216);
}
//把一个32位整型转换为4个8位字节型,并写入EEPROM中
void wrTStoIIC(int coef,unsigned char address)
{
iic_buffer[0]=(unsigned char)((coef&0xFF000000)>>24);
iic_buffer[1]=(unsigned char)((coef&0x00FF0000)>>16);
iic_buffer[2]=(unsigned char)((coef&0x0000FF00)>>8);
iic_buffer[3]=(unsigned char)(coef&0x000000FF);
wr24c02a(address,iic_buffer,4);
}
//读取EEPROM中的4个8位字节,并把它们组合成一个32位的整型。
int rdTStoIIC(unsigned char address)
{
int temp;
rd24c02a(address,iic_buffer,4);
temp=(iic_buffer[0]<24)|(iic_buffer[1]<16)|(iic_buffer[2]<8)|(iic_buffer[3]);
return temp;
}
void Main(void)
{
LCD_Init();
rLCDCON1|=1;
rADCDLY=50000;//设置延时
rADCCON=(1<14)+(9<6);//设置A/D预分频
rADCTSC=0xd3;//设置触摸屏为等待中断模式。
pISR_ADC = (U32)ADCTs;
…………
flagTS = 0;
flagIIC = 1;
//读取EEPROM中的标志地址内容,用于判断触摸屏校正的参数是否已计算并保存好
rd24c02a(0x1F,iic_buffer,1);
if(iic_buffer[0]!=0x6A)//如果触摸屏的校正参数没有计算并保存,重新校正
{
TSCal();
rINTMSK=~((0x1<31)|(0x1<27));//开启IIC中断屏蔽
iic_buffer[0]=0x6A;
wr24c02a(0x1F,iic_buffer,1);//置“触摸屏校正参数计算并保持好”的标志信息
delay(3000);//等待一段时间,一定要有,否则EEPROM不能正确读写
wrTStoIIC(A,0x20);
delay(3000);
wrTStoIIC(B,0x30);
delay(3000);
wrTStoIIC(C,0x40);
delay(3000);
wrTStoIIC(D,0x50);
delay(3000);
wrTStoIIC(E,0x60);
delay(3000);
wrTStoIIC(F,0x70);
delay(3000);
wrTStoIIC(K,0x80);
}
else//如果触摸屏校正参数已准备好,则直接读取
{
A=rdTStoIIC(0x20);
delay(3000);
B=rdTStoIIC(0x30);
delay(3000);
C=rdTStoIIC(0x40);
delay(3000);
D=rdTStoIIC(0x50);
delay(3000);
E=rdTStoIIC(0x60);
delay(3000);
F=rdTStoIIC(0x70);
delay(3000);
K=rdTStoIIC(0x80);
}
Brush_Background(0,0,LCD_WIDTH,LCD_HEIGHT,0xFFFFFF);
while(1)
{
if(flagTS)
{
flagTS=0;
xLcd = (A*xdata+B*ydata+C)/K;//计算X轴坐标
yLcd = (D*xdata+E*ydata+F)/K;//计算Y轴坐标
Brush_Background(xLcd-5,yLcd-5,xLcd+5,yLcd+5,0xFF0000);//绘制正方形
}
delay(1000000);
}
}
本文介绍的程序要略显复杂一些,这里对触摸屏校正和中断再做一总结:
1、一般地,在第一次使用触摸屏时,需要校正一次,以后可以不再校正,除非发生了明显的漂移。我们是把校正参数存储在EEPROM中,下次再使用时,只需读取该组数据即可。EEPROM中的0x1F地址用于存储校正参数标识信息,在已经校正过的情况下,该位内容为0x6A,这样在下次开机使用触摸屏时,只要读取该位内容,就可知道触摸屏是否已校正,没有校正则需要进行校正,已经校正过了则无需再重复校正了。
2、先设置等待中断模式,以等待触摸屏中断的发生,当中断发生并进入中断以后,再转换为自动连续XY坐标转换模式,可正确读取触点的坐标值。在中断程序中,当触笔落下时进入中断,当触笔抬起时退出中断,程序只记录触笔落下时触点的坐标值。
该段程序的演示图如下:
unsigned char devAddr=0xa0;
int A,B,C,D,E,F,K;
volatile int xdata, ydata;
int flagIIC;//IIC标志
int flagTS;//触摸屏标志
…………
//触摸屏中断
void __irq ADCTs(void)
{
rADCTSC = (1<3)|(1<2);//上拉电阻无效,自动连续XY坐标转换模式开启
rADCDLY = 40000;//延时
rADCCON|=0x1;//开始A/D转换
while(rADCCON & 0x1)
;//检查A/D转换是否开始
while(!(rADCCON & 0x8000))
;//等待A/D转换的结束
while(!(rSRCPND & ((U32)0x1<31)))
;//判断A/D中断的悬挂位
xdata=(rADCDAT0&0x3ff);//读取X轴坐标
ydata=(rADCDAT1&0x3ff);//读取Y轴坐标
flagTS = 1;//置标志
rSUBSRCPND|=0x1<9;
rSRCPND = 0x1<31;
rINTPND = 0x1<31;
rINTSUBMSK=~(0x1<9);
rINTMSK=~(0x1<31);//清A/D中断,开启A/D中断屏蔽
rADCTSC =0xd3;//再次设置等待中断模式,这一次是判断触笔的抬起
rADCTSC=rADCTSC|(1<8);//设置触笔抬起中断
while(1)//等待触笔的抬起
{
if(rSUBSRCPND & (0x1<9))//检查A/D触摸屏中断悬挂
{
break;//如果触笔抬起,则跳出该循环
}
}
rADCDLY=50000;
rSUBSRCPND|=0x1<9;
rINTSUBMSK=~(0x1<9);
rSRCPND = 0x1<31;
rINTPND = 0x1<31;//再次清A/D中断,开启A/D中断屏蔽
rADCTSC =0xd3;//设置等待中断模式,为下一次触笔的落下做准备
}
//绘制“十”字型
void drawCross(U32 x,U32 y,U32 color)
{
int i;
for(i=x-10;i
for(i=y-10;i
}
//触摸屏校正
void TSCal(void)
{
int i=0;
int xt[3],yt[3];
Brush_Background(0,0,LCD_WIDTH,LCD_HEIGHT,0xFFFFFF);
drawCross(32,24,0xFF0000);
Draw_ASCII(36,28,0xFF0000,one);
drawCross(160,216,0xFF0000);
Draw_ASCII(164,220,0xFF0000,two);
drawCross(288,120,0xFF0000);
Draw_ASCII(292,124,0xFF0000,three);
//依次读取三个采样点的坐标值
for(i=0;i<3;i++)
{
while(flagTS==0)
delay(500);
xt[i]=xdata;
yt[i]=ydata;
flagTS=0;
}
//计算参数
K=(xt[0]-xt[2])*(yt[1]-yt[2])-(xt[1]-xt[2])*(yt[0]-yt[2]);
A=(32-288)*(yt[1]-yt[2])-(160-288)*(yt[0]-yt[2]);
B=(xt[0]-xt[2])*(160-288)-(32-288)*(xt[1]-xt[2]);
C=yt[0]*(xt[2]*160-xt[1]*288)+yt[1]*(xt[0]*288-xt[2]*32)+yt[2]*(xt[1]*32-xt[0]*160);
D=(24-120)*(yt[1]-yt[2])-(216-120)*(yt[0]-yt[2]);
E=(xt[0]-xt[2])*(216-120)-(24-120)*(xt[1]-xt[2]);
F=yt[0]*(xt[2]*216-xt[1]*120)+yt[1]*(xt[0]*120-xt[2]*24)+yt[2]*(xt[1]*24-xt[0]*216);
}
//把一个32位整型转换为4个8位字节型,并写入EEPROM中
void wrTStoIIC(int coef,unsigned char address)
{
iic_buffer[0]=(unsigned char)((coef&0xFF000000)>>24);
iic_buffer[1]=(unsigned char)((coef&0x00FF0000)>>16);
iic_buffer[2]=(unsigned char)((coef&0x0000FF00)>>8);
iic_buffer[3]=(unsigned char)(coef&0x000000FF);
wr24c02a(address,iic_buffer,4);
}
//读取EEPROM中的4个8位字节,并把它们组合成一个32位的整型。
int rdTStoIIC(unsigned char address)
{
int temp;
rd24c02a(address,iic_buffer,4);
temp=(iic_buffer[0]<24)|(iic_buffer[1]<16)|(iic_buffer[2]<8)|(iic_buffer[3]);
return temp;
}
void Main(void)
{
LCD_Init();
rLCDCON1|=1;
rADCDLY=50000;//设置延时
rADCCON=(1<14)+(9<6);//设置A/D预分频
rADCTSC=0xd3;//设置触摸屏为等待中断模式。
pISR_ADC = (U32)ADCTs;
…………
flagTS = 0;
flagIIC = 1;
//读取EEPROM中的标志地址内容,用于判断触摸屏校正的参数是否已计算并保存好
rd24c02a(0x1F,iic_buffer,1);
if(iic_buffer[0]!=0x6A)//如果触摸屏的校正参数没有计算并保存,重新校正
{
TSCal();
rINTMSK=~((0x1<31)|(0x1<27));//开启IIC中断屏蔽
iic_buffer[0]=0x6A;
wr24c02a(0x1F,iic_buffer,1);//置“触摸屏校正参数计算并保持好”的标志信息
delay(3000);//等待一段时间,一定要有,否则EEPROM不能正确读写
wrTStoIIC(A,0x20);
delay(3000);
wrTStoIIC(B,0x30);
delay(3000);
wrTStoIIC(C,0x40);
delay(3000);
wrTStoIIC(D,0x50);
delay(3000);
wrTStoIIC(E,0x60);
delay(3000);
wrTStoIIC(F,0x70);
delay(3000);
wrTStoIIC(K,0x80);
}
else//如果触摸屏校正参数已准备好,则直接读取
{
A=rdTStoIIC(0x20);
delay(3000);
B=rdTStoIIC(0x30);
delay(3000);
C=rdTStoIIC(0x40);
delay(3000);
D=rdTStoIIC(0x50);
delay(3000);
E=rdTStoIIC(0x60);
delay(3000);
F=rdTStoIIC(0x70);
delay(3000);
K=rdTStoIIC(0x80);
}
Brush_Background(0,0,LCD_WIDTH,LCD_HEIGHT,0xFFFFFF);
while(1)
{
if(flagTS)
{
flagTS=0;
xLcd = (A*xdata+B*ydata+C)/K;//计算X轴坐标
yLcd = (D*xdata+E*ydata+F)/K;//计算Y轴坐标
Brush_Background(xLcd-5,yLcd-5,xLcd+5,yLcd+5,0xFF0000);//绘制正方形
}
delay(1000000);
}
}
本文介绍的程序要略显复杂一些,这里对触摸屏校正和中断再做一总结:
1、一般地,在第一次使用触摸屏时,需要校正一次,以后可以不再校正,除非发生了明显的漂移。我们是把校正参数存储在EEPROM中,下次再使用时,只需读取该组数据即可。EEPROM中的0x1F地址用于存储校正参数标识信息,在已经校正过的情况下,该位内容为0x6A,这样在下次开机使用触摸屏时,只要读取该位内容,就可知道触摸屏是否已校正,没有校正则需要进行校正,已经校正过了则无需再重复校正了。
2、先设置等待中断模式,以等待触摸屏中断的发生,当中断发生并进入中断以后,再转换为自动连续XY坐标转换模式,可正确读取触点的坐标值。在中断程序中,当触笔落下时进入中断,当触笔抬起时退出中断,程序只记录触笔落下时触点的坐标值。
该段程序的演示图如下:
s3c2440触摸屏校 相关文章:
- s3c2440的触摸屏校正与测试(11-20)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)