新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > s3c2440的觸摸屏應(yīng)用與校正

s3c2440的觸摸屏應(yīng)用與校正

作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò) 收藏
觸摸屏是當(dāng)今最流行的一種人機(jī)交互接口,它被廣泛地應(yīng)用于手機(jī)等消費(fèi)類電子產(chǎn)品中,目前這種技術(shù)有向PC機(jī)方向發(fā)展的趨勢(shì)?;谠淼牟煌?,觸摸屏可以分為電阻式、電容式、表面聲波式等。電阻式是應(yīng)用較廣的一種觸摸屏,它的原理是通過(guò)測(cè)量橫向和縱向的電阻值來(lái)獲得觸點(diǎn)的坐標(biāo)。

s3c2440集成了4線制電阻式的觸摸屏接口,觸點(diǎn)坐標(biāo)的檢測(cè)是通過(guò)A/D轉(zhuǎn)換來(lái)實(shí)現(xiàn)的。s3c2440一共有4種觸摸屏接口模式,其中,自動(dòng)(連續(xù))XY坐標(biāo)轉(zhuǎn)換模式和等待中斷模式應(yīng)用地比較常見(jiàn)。等待中斷模式是在觸筆落下時(shí)產(chǎn)生一個(gè)中斷,在這種模式下,A/D觸摸屏控制寄存器ADCTSC的值應(yīng)為0xD3,在系統(tǒng)響應(yīng)中斷后,XY坐標(biāo)的測(cè)量模式必須為無(wú)操作模式,即寄存器ADCTSC的低兩位必須清零。自動(dòng)(連續(xù))XY坐標(biāo)轉(zhuǎn)換模式是系統(tǒng)依次轉(zhuǎn)換觸點(diǎn)的X軸坐標(biāo)和Y軸坐標(biāo),其中X軸坐標(biāo)值寫入寄存器ADCDAT0的低10位中,Y軸坐標(biāo)寫入寄存器ADCDAT1的低10位中,在這種模式下,系統(tǒng)同樣會(huì)產(chǎn)生中斷信號(hào)。在一般情況下,為實(shí)現(xiàn)觸摸屏功能,先是設(shè)置為等待中斷模式,在產(chǎn)生中斷后,再設(shè)置為自動(dòng)(連續(xù))XY坐標(biāo)轉(zhuǎn)換模式,依次讀取觸點(diǎn)的坐標(biāo)值。在實(shí)現(xiàn)觸摸屏功能的過(guò)程中,除了上面介紹的幾個(gè)寄存器外,還會(huì)用到以下寄存器。寄存器ADCTSC的第8位能夠?qū)崿F(xiàn)是觸筆落下中斷還是觸筆抬起中斷,如果寫過(guò)基于視窗應(yīng)用程序的人對(duì)這一點(diǎn)會(huì)很熟悉,它就好像單擊鼠標(biāo)操作一樣,一次單擊操作包括兩個(gè)動(dòng)作:按下和釋放,這兩個(gè)動(dòng)作可以完成不同的命令。寄存器ADCTSC的第3位可以選擇上拉電阻的使能,在等待中斷模式下,上拉電阻要有效,在觸發(fā)中斷后,上拉電阻要無(wú)效。寄存器ADCTSC的第2位用于選擇自動(dòng)(連續(xù))XY坐標(biāo)轉(zhuǎn)換模式。觸筆抬起/落下中斷狀態(tài)寄存器ADCUPDN的低2位能夠判斷觸筆在何種狀態(tài)下引起的中斷。A/D延時(shí)寄存器ADCDLY可以設(shè)置開(kāi)始中斷到真正開(kāi)始A/D轉(zhuǎn)換這段時(shí)間的延時(shí)長(zhǎng)度,它的時(shí)鐘源頻率為3.68MHz。

在開(kāi)始實(shí)現(xiàn)觸摸屏功能之前,還需要解決一個(gè)問(wèn)題,那就是觸摸屏的校正。觸摸屏和LCD是兩種不同的物理器件。對(duì)于一個(gè)分辨率為320×240的LCD,它的寬度為320個(gè)像素,高度為240個(gè)像素。而觸摸屏處理的數(shù)據(jù)是點(diǎn)的物理坐標(biāo),該坐標(biāo)是通過(guò)觸摸屏控制器采集得到的。要想實(shí)現(xiàn)觸摸屏上的物理坐標(biāo)與LCD上的像素點(diǎn)坐標(biāo)一一對(duì)應(yīng)上,兩者之間就需要一定的轉(zhuǎn)換,即校正。而且電阻式觸摸屏由于自身的原因參數(shù)會(huì)發(fā)生變化,因此需要經(jīng)常性的校正。比較常見(jiàn)的校正方法是三點(diǎn)校正法,它的原理是:

設(shè)LCD上每個(gè)點(diǎn)PD的坐標(biāo)為[XD,YD],觸摸屏上每個(gè)點(diǎn)PT的坐標(biāo)為[XT,YT]。要實(shí)現(xiàn)觸摸屏上的坐標(biāo)轉(zhuǎn)換為L(zhǎng)CD上的坐標(biāo),需要下列公式進(jìn)行轉(zhuǎn)換:
XD=A×XT+B×YT+C
YD=D×XT+E×YT+F
因?yàn)槠渲幸还灿辛鶄€(gè)參數(shù)(A,B,C,D,E,F),因此只需要三個(gè)取樣點(diǎn)就可以求得這六個(gè)參數(shù)。這六個(gè)參數(shù)一旦確定下來(lái),只要給出任意觸摸屏上的坐標(biāo)點(diǎn)PT,代入這個(gè)公式,就可以得到它所對(duì)應(yīng)的LCD上像素點(diǎn)的坐標(biāo)PD。具體的求解過(guò)程就不細(xì)講,只給出最終的結(jié)果。已知LCD上的三個(gè)取樣點(diǎn)為:PD0,PD1,PD2,它們所對(duì)應(yīng)的觸摸屏上的三個(gè)點(diǎn)為:PT0,PT1,PT2。A,B,C,D,E,F這六個(gè)參數(shù)最終的結(jié)果都是一個(gè)分式,而且都有一個(gè)共同的分母,為:
K=(XT0-XT2)×(YT1-YT2)-(XT1-XT2)×(YT0-YT2)
那么這六個(gè)參數(shù)分別為:
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

下面的程序是實(shí)現(xiàn)觸摸屏功能的簡(jiǎn)單實(shí)例——以觸點(diǎn)為中心,繪制出一個(gè)紅色的邊長(zhǎng)為10個(gè)像素的正方形。觸點(diǎn)的坐標(biāo)是用下面方法得到的:當(dāng)觸筆落下時(shí),進(jìn)入中斷,然后讀取觸點(diǎn)處的坐標(biāo),直到觸筆的抬起,才退出該次中斷。由于觸摸屏需要校正,因此在使用之前需要進(jìn)行校正處理。但并不是每次使用都要校正,只要坐標(biāo)沒(méi)有發(fā)生漂移,就不需要再次校正。所以在進(jìn)行一次校正后,只要把那幾個(gè)參數(shù)保存起來(lái),下次需要時(shí)直接使用上次保存下來(lái)的參數(shù)即可。在這里,我們利用EEPROM來(lái)保存這幾個(gè)參數(shù),即A,B,C,D,E,F,K分別保存在以0x20,0x30,0x40,0x50,0x60,0x70,0x80為首地址內(nèi)存的連續(xù)4個(gè)字節(jié)空間內(nèi),另外內(nèi)存地址0x1F保存一個(gè)標(biāo)識(shí)信息,當(dāng)為0x6A時(shí),表示這幾個(gè)參數(shù)已計(jì)算并保存好了,只需從上述內(nèi)存地址中讀取參數(shù)就行,而當(dāng)為其他值時(shí),就需要進(jìn)行校正。校正時(shí),需要三個(gè)取樣點(diǎn),在這里我們選取LCD上的(32,24),(160,216),(288,120)為這三個(gè)取樣點(diǎn),我們?cè)谶@三個(gè)取樣點(diǎn)上畫一個(gè)十字(如下圖所示),只需要依次點(diǎn)擊這三個(gè)點(diǎn),即可完成觸摸屏的校正。


…………
volatile U32 LCD_BUFFER[LCD_HEIGHT][LCD_WIDTH];
unsigned char iic_buffer[8];
unsigned char devAddr=0xa0;
int A,B,C,D,E,F,K;

volatile int xdata, ydata;

int flagIIC;//IIC標(biāo)志
int flagTS;//觸摸屏標(biāo)志
…………

//觸摸屏中斷
void __irq ADCTs(void)
{
rADCTSC = (1<<3)|(1<<2);//上拉電阻無(wú)效,自動(dòng)連續(xù)XY坐標(biāo)轉(zhuǎn)換模式開(kāi)啟
rADCDLY = 40000;//延時(shí)

rADCCON|=0x1;//開(kāi)始A/D轉(zhuǎn)換

while(rADCCON & 0x1)
;//檢查A/D轉(zhuǎn)換是否開(kāi)始
while(!(rADCCON & 0x8000))
;//等待A/D轉(zhuǎn)換的結(jié)束

while(!(rSRCPND & ((U32)0x1<<31)))
;//判斷A/D中斷的懸掛位

xdata=(rADCDAT0&0x3ff);//讀取X軸坐標(biāo)
ydata=(rADCDAT1&0x3ff);//讀取Y軸坐標(biāo)

flagTS = 1;//置標(biāo)志

rSUBSRCPND|=0x1<<9;
rSRCPND = 0x1<<31;
rINTPND = 0x1<<31;
rINTSUBMSK=~(0x1<<9);
rINTMSK=~(0x1<<31);//清A/D中斷,開(kāi)啟A/D中斷屏蔽

rADCTSC =0xd3;//再次設(shè)置等待中斷模式,這一次是判斷觸筆的抬起
rADCTSC=rADCTSC|(1<<8);//設(shè)置觸筆抬起中斷

while(1)//等待觸筆的抬起
{
if(rSUBSRCPND & (0x1<<9))//檢查A/D觸摸屏中斷懸掛
{
break;//如果觸筆抬起,則跳出該循環(huán)
}
}

rADCDLY=50000;
rSUBSRCPND|=0x1<<9;
rINTSUBMSK=~(0x1<<9);
rSRCPND = 0x1<<31;
rINTPND = 0x1<<31;//再次清A/D中斷,開(kāi)啟A/D中斷屏蔽
rADCTSC =0xd3;//設(shè)置等待中斷模式,為下一次觸筆的落下做準(zhǔn)備
}

//繪制“十”字型
void drawCross(U32 x,U32 y,U32 color)
{
int i;
for(i=x-10;iPutPixel(i,y, color);
for(i=y-10;iPutPixel(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);

//依次讀取三個(gè)采樣點(diǎn)的坐標(biāo)值
for(i=0;i<3;i++)
{
while(flagTS==0)
delay(500);
xt[i]=xdata;
yt[i]=ydata;
flagTS=0;
}

//計(jì)算參數(shù)
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);
}

//把一個(gè)32位整型轉(zhuǎn)換為4個(gè)8位字節(jié)型,并寫入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個(gè)8位字節(jié),并把它們組合成一個(gè)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;//設(shè)置延時(shí)
rADCCON=(1<<14)+(9<<6);//設(shè)置A/D預(yù)分頻

rADCTSC=0xd3;//設(shè)置觸摸屏為等待中斷模式。

pISR_ADC = (U32)ADCTs;

…………

flagTS = 0;
flagIIC = 1;

//讀取EEPROM中的標(biāo)志地址內(nèi)容,用于判斷觸摸屏校正的參數(shù)是否已計(jì)算并保存好
rd24c02a(0x1F,iic_buffer,1);

if(iic_buffer[0]!=0x6A)//如果觸摸屏的校正參數(shù)沒(méi)有計(jì)算并保存,重新校正
{
TSCal();
rINTMSK=~((0x1<<31)|(0x1<<27));//開(kāi)啟IIC中斷屏蔽
iic_buffer[0]=0x6A;
wr24c02a(0x1F,iic_buffer,1);//置“觸摸屏校正參數(shù)計(jì)算并保持好”的標(biāo)志信息
delay(3000);//等待一段時(shí)間,一定要有,否則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//如果觸摸屏校正參數(shù)已準(zhǔn)備好,則直接讀取
{
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;//計(jì)算X軸坐標(biāo)
yLcd = (D*xdata+E*ydata+F)/K;//計(jì)算Y軸坐標(biāo)
Brush_Background(xLcd-5,yLcd-5,xLcd+5,yLcd+5,0xFF0000);//繪制正方形
}
delay(1000000);
}
}


本文介紹的程序要略顯復(fù)雜一些,這里對(duì)觸摸屏校正和中斷再做一總結(jié):
1、一般地,在第一次使用觸摸屏?xí)r,需要校正一次,以后可以不再校正,除非發(fā)生了明顯的漂移。我們是把校正參數(shù)存儲(chǔ)在EEPROM中,下次再使用時(shí),只需讀取該組數(shù)據(jù)即可。EEPROM中的0x1F地址用于存儲(chǔ)校正參數(shù)標(biāo)識(shí)信息,在已經(jīng)校正過(guò)的情況下,該位內(nèi)容為0x6A,這樣在下次開(kāi)機(jī)使用觸摸屏?xí)r,只要讀取該位內(nèi)容,就可知道觸摸屏是否已校正,沒(méi)有校正則需要進(jìn)行校正,已經(jīng)校正過(guò)了則無(wú)需再重復(fù)校正了。
2、先設(shè)置等待中斷模式,以等待觸摸屏中斷的發(fā)生,當(dāng)中斷發(fā)生并進(jìn)入中斷以后,再轉(zhuǎn)換為自動(dòng)連續(xù)XY坐標(biāo)轉(zhuǎn)換模式,可正確讀取觸點(diǎn)的坐標(biāo)值。在中斷程序中,當(dāng)觸筆落下時(shí)進(jìn)入中斷,當(dāng)觸筆抬起時(shí)退出中斷,程序只記錄觸筆落下時(shí)觸點(diǎn)的坐標(biāo)值。

該段程序的演示圖如下:



關(guān)鍵詞: s3c2440觸摸屏校

評(píng)論


技術(shù)專區(qū)

關(guān)閉