mini2440上連接配接的是一個電阻式觸摸屏,電阻式觸摸屏是基于AD轉換實作的,即某個位置按下之後,這點的電壓會發生改變,通過電壓就可以判斷出是哪一個點被按下了,arm可以得到這個點的坐标。因為觸摸屏和lcd是兩個裝置,是以,觸摸屏得到的坐标一般不能夠與lcd上的坐标對應起來,是以需要我們在程式中手動的進行校正(雖然不對應,但是他們之間的關系式線性的,是以通過三個點的采樣,就可以把系數确定下來。)
s3c2440是不支援中斷嵌套的。
arm與觸摸屏通過tsxp\tsxm tsyp\tsym 四根線相連接配接,資料手冊中有一句話:When Touch Screen device is used; XM or PM is only connected ground for Touch Screen I/F.s3c2440一共有4種觸摸屏接口模式,其中,自動(連續)XY坐标轉換模式和等待中斷模式是我們用到的。
(1)等待中斷模式是在觸筆落下時産生一個中斷,在這種模式下,A/D觸摸屏控制寄存器ADCTSC的值應為0xD3,在系統響應中斷後,XY坐标的測量模式必須為無操作模式,即寄存器ADCTSC的低兩位必須清零。
(2)自動(連續)XY坐标轉換模式是系統依次轉換觸點的X軸坐标和Y軸坐标,其中X軸坐标值寫入寄存器ADCDAT0的低10位中,Y軸坐标寫入寄存器ADCDAT1的低10位中,在這種模式下,系統同樣會産生中斷信号。
在一般情況下,為實作觸摸屏功能,先是設定為等待中斷模式,在産生int_tc中斷後,在中斷函數中再設定為自動(連續)XY坐标轉換模式,依次讀取觸點的坐标值。
與觸摸屏的功能實作相關的有兩個中斷:int_adc和int_tc,這兩個中斷源屬于subinterrupt source,都屬于int_adc,是以在配置中斷的時候就需要按照sub中斷源的配置方法進行配置。其中,int_tc是在觸摸屏被按下或被釋放時産生,一個時刻隻能檢測其中一種事件,具體是檢測觸摸屏按下還是釋放,需要我們在寄存器ADCTSC的第8位能夠設定。int_adc是在ad轉換完成之後産生的。
寄存器ADCTSC的第3位可以選擇上拉電阻的使能,在等待中斷模式下,上拉電阻要有效,在觸發中斷後,上拉電阻要無效。寄存器ADCTSC的第2位用于選擇自動(連續)XY坐标轉換模式。觸筆擡起/落下中斷狀态寄存器ADCUPDN的低2位能夠判斷觸筆在何種狀态下引起的中斷。A/D延時寄存器ADCDLY可以設定開始中斷到真正開始A/D轉換這段時間的延時長度,它的時鐘源頻率為3.68MHz。
實作觸摸屏功能的流程是這樣的:
1. 設定觸摸屏為等待中斷模式,配置ADCTSC為檢測觸摸屏被按下 産生中斷。
2. 産生中斷後,證明觸摸屏被按下。在中斷函數中修改ADCTSC和ADCCON,配置觸摸屏為連續轉換功能。同時要屏蔽int_adc中斷。因為我們是在中斷函數中,是以,通過while循環檢測srcpnd 和 subsrcpnd寄存器來檢測是否産生了adc轉換完成的中斷。也就是屏蔽中斷,但是通過檢測是否産生中斷,來判斷adc轉換是否完成。
3. adc轉換結束後,提取想要的資料。然後配置ADCSTC為檢測觸摸屏被釋放産生中斷,同時也要繼續屏蔽中斷。通過檢測srcpnd和subsrcpnd來判斷是否産生了觸摸屏被釋放的中斷。當檢測到觸摸屏被釋放後,結束中斷函數。
當然,采用其他方法來實作我覺也是可以的,比如說檢測到觸摸屏被按下後,就結束中斷函數。也就是把上面的三個步驟,分别在三個中斷函數中實作,也是可行的。
此外,涉及到觸摸屏的校正,轉載趙老師的方法如下:
比較常見的校正方法是三點校正法,它的原理是:
設LCD上每個點PD的坐标為[XD,YD],觸摸屏上每個點PT的坐标為[XT,YT]。要實作觸摸屏上的坐标轉換為LCD上的坐标,需要下列公式進行轉換:
XD=A×XT+B×YT+C
YD=D×XT+E×YT+F
因為其中一共有六個參數(A,B,C,D,E,F),是以隻需要三個取樣點就可以求得這六個參數。這六個參數一旦确定下來,隻要給出任意觸摸屏上的坐标點PT,代入這個公式,就可以得到它所對應的LCD上像素點的坐标PD。具體的求解過程就不細講,隻給出最終的結果。已知LCD上的三個取樣點為:PD0,PD1,PD2,它們所對應的觸摸屏上的三個點為:PT0,PT1,PT2。A,B,C,D,E,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
具體操作,就是先在lcd上顯示三個點,然後等用于點選這三個點之後,采集這三個點的實際坐标和理論坐标,這樣就可以計算得到上面的參數。
下面附上我的代碼。
static void __irq touchscreen_irq(void)
{
int xdata, ydata;
rADCTSC = (1<<3)|(1<<2); //上拉電阻無效,自動連續XY坐标轉換模式開啟
rADCDLY = 40000; //延時
rADCCON|=0x1; //開始A/D轉換
while(rADCCON & 0x1); //檢查A/D轉換是否開始
while(!(rADCCON & 0x8000)); //等待A/D轉換的結束
while(!(rSRCPND & (BIT_ADC))) ; //判斷A/D中斷的懸挂位
xdata=(rADCDAT0&0x3ff); //讀取X軸坐标
ydata=(rADCDAT1&0x3ff); //讀取Y軸坐标
uart_printf("xdata = %x, ydata = %x adcdata0 = %x ", xdata, ydata, rADCDAT0);
rSUBSRCPND|=BIT_SUB_TC;
ClearPending(BIT_ADC);
rADCTSC =0xd3; //再次設定等待中斷模式,這一次是判斷觸筆的擡起
rADCTSC = rADCTSC|(1<<8); //設定觸筆擡起中斷
while(1) //等待觸筆的擡起
{
if(rSUBSRCPND & (0x1<<9)) //檢查A/D觸摸屏中斷懸挂
{
break; //如果觸筆擡起,則跳出該循環
}
}
uart_printf("adcdata0 = %x ", rADCDAT0);
rSUBSRCPND = 1<<9;
ClearPending(BIT_ADC);
uart_printf("irq finish\r\n");
rADCTSC=0xd3; // important here
}
void touchscreen_init(void)
{
rADCDLY=50000; //設定延時
rADCCON=(1<<14)+(9<<6); //設定A/D預分頻
rADCTSC=0xd3; //設定觸摸屏為等待中斷模式。
pISR_ADC = (U32)touchscreen_irq;
rINTSUBMSK &= ~(BIT_SUB_TC);
rSUBSRCPND = 1<<9;
ClearPending(BIT_ADC);
EnableIrq(BIT_ADC);
}
void touchscreen_test(void)
{
touchscreen_init();
}