天天看點

mini2440裸機程式設計--------觸摸屏驅動

       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();
}
           

繼續閱讀