觸摸屏由于其體積小、輕便和接口簡單的特點,成為一種在嵌入式系統中應用廣泛的輸
入設備。本實例首先介紹四線電阻式觸摸屏的結構和工作原理,然后介紹S3C2440A 通過內
部集成的觸摸屏控制寄存器的設置,來完成對觸摸屏觸摸位置坐標的讀取。

典型觸摸屏的工作組件一般由3 部分組成。兩層透明的阻性導體層、兩層
導體之間的隔離層和電極。阻性導體層選用阻性材料,如將銦錫氧化物(1TO)涂在襯底上構
成,或者上層襯底用塑料,下層襯底用玻璃。隔離層為粘性絕緣液體材料,如聚脂薄膜。電
極選用導電性能極好的材料(如銀粉墨)構成,其導電性能大約為ITO 的1 000 倍。
工作原理:見下圖
1.獲取X坐標:X+和X-加上正負電壓,X方向就會形成電勢梯度網絡;Y-接高阻,Y+接輸入,一旦屏幕上某點被按下,絕緣液體被排開,上下兩個導體層在此點導通,Y+獲取此點在X方向上的電勢,即此點的X坐標,通過ADC轉換成數字量輸入給系統。
同理
1.獲取Y坐標:Y+和Y-加上正負電壓,Y方向就會形成電勢梯度網絡;X-接高阻,X+接輸入,一旦屏幕上某點被按下,絕緣液體被排開,上下兩個導體層在此點導通,X+獲取此點在Y方向上的電勢,即此點的Y坐標,通過ADC轉換成數字量輸入給系統。
這樣,通過ADC轉換成數字量輸入給系統。
這里做個試驗,筆尖接觸 觸摸屏,然后串口打印坐標值。
注意X測量時,依據上述原理,XP接參考電平,XM接地,YP接ADC通道5,YM接高阻,上拉功能取消,這些都在寄存器中設置ADCTSC。
同理,Y測量時,YP接參考電平,YM接地,XP接ADC通道7,XM接高阻,上拉功能取消.
其他用到的是ADC相關的寄存器。
//******************************************************************** #define adc_frequency 2000000 U16 x_tsc,y_tsc; void Main(void)
{
int i;
……硬件初始化……
Uart_Printf("\n觸摸屏中斷+坐標提取實驗\n"); tsc_int_init(); //觸摸屏中斷初始化
tsc_init(); //觸摸屏初始化
while(1);
} void tsc_int_init(void) //觸摸屏中斷初始化
{
rSUBSRCPND |= 1<<9; //INT_TC清0 rSRCPND |= 1<<31; //INT_ADC清0
rINTPND |= 1<<31; //INT_ADC清0
pISR_ADC = (U32)TSC_ISR; //申請中斷向量
rINTMSK = rINTMSK & ~(1<<31); //禁止ADC的屏蔽
rINTSUBMSK = rINTSUBMSK & ~(1<<9); //禁止TSC的屏蔽
rADCTSC = 0x0d3 ; //等待中斷模式的特定設置
}
void TSC_ISR(void) __irq //觸摸屏中斷例程
{
rINTMSK |= 1<<31; //ADC中斷的屏蔽
rINTSUBMSK |= 1<<9 | 1<<10; //TSC和ADC_S中斷屏蔽
tsc_get(); //得到觸點坐標
Uart_Printf("x=%d,y=%d\n",x_tsc,y_tsc);
rSUBSRCPND |= 1<<9; //INT_TC清0
rSRCPND |= 1<<31; //INT_ADC清0
rINTPND |= 1<<31; //INT_ADC清0
rINTMSK = rINTMSK & ~(1<<31); //禁止ADC的屏蔽
rINTSUBMSK = rINTSUBMSK & ~(1<<9); //禁止TSC的屏蔽
rINTSUBMSK = rINTSUBMSK & ~(1<<10); //禁止ADC_S的屏蔽 }
void tsc_init(void) //觸摸屏初始化
{
rADCDLY= 0x5000;//必須要延時
rADCCON = (PCLK/adc_frequency - 1)<<6 | 1<<14 ; //設置ADC頻率,預分頻有效
}
void tsc_get(void)
{
rADCCON = rADCCON & ~(7<<3) | 7<<3 ; //選擇XP通道
rADCTSC = (0<<7)|(1<<6)|(1<<5)|(0<<4)|(1<<3)|(0<<2)|1 ; //X測量模式:YM=Z, YP=AIN[5] ,XM=GND, XP=V, PULL_UP=DISABLE, NORMAL, X-position (ENABLE=GND/V)
rADCCON|=0x1; //啟動ADC
while(rADCCON & 0x1); //等待啟動
while(!(rADCCON & 0x8000)); //等待是否轉換完畢
x_tsc = rADCDAT0&0x3FF; //得到轉換結果
rADCCON = rADCCON & ~(7<<3) | 5<<3 ; //選擇YP通道
rADCTSC = (1<<7)|(0<<6)|(0<<5)|(1<<4)|(1<<3)|(0<<2)|2 ; //Y測量模式:YM=GND, YP=V ,XM=Z, XP=AIN[7], PULL_UP=DISENBLE, NORMAL, Y-position (DISABLE=AIN/Z)
rADCCON|=0x1; //啟動ADC
while(rADCCON & 0x1); //等待啟動
while(!(rADCCON & 0x8000)); //等待是否轉換完畢
y_tsc = rADCDAT1&0x3FF; //得到轉換結果
tsc_int_init(); //觸摸屏中斷初始化
Delay(10);
while(!((rADCDAT0 & 0X8000) & (rADCDAT1 & 0X8000) ));//等待筆尖抬起
}
//*******************************************************************
結果如圖:
下面做個LCD和觸摸屏TSC結合的實驗,每當觸摸屏某點被按下,在LCD的此點顯示一個小正方形。
注意LCD的XY坐標與TSC的XY坐標不一樣,需要轉化,我研究了一下之間的關系,不是太精準,僅供參考:(x_lcd, y_lcd) = ( 1.0084*y_tsc - 150,-0.82*x_tsc +600,12345)。
//******************************************************************** #define adc_frequency 2000000
#define CLKVAL (6) //VCLK=HCLK÷[(CLKVAL+1)×2]
#define PNRMODE (3) //TFT LCD panel
#define BPPMODE (12) //16 bpp for TFT
#define ENVID (1) //輸出和控制 有效 #define VBPD (29) //垂直同步信號后肩
#define LINEVAL (480) //垂直尺寸
#define VFPD (13) //垂直同步信號前肩
#define VSPW (3) //垂直同步信號脈寬 #define HBPD (40) //水平同步信號后肩
#define HOZVAL (800) //水平尺寸
#define HFPD (40) //水平同步信號前肩 #define HSPW (48) //水平同步信號脈寬 #define FRM565 (1) //565格式
#define PWREN (1) //GPG供電使能(用于掉電模式)
#define BSWP (0) //字節不交換:
//#define HWSWP (1) //半字交換 16位用不到
#define OFFSIZE (0) //若不用虛擬屏幕,則為0
#define PAGEWIDTH (HOZVAL)//虛擬屏幕的寬 單位半字 若不用虛擬屏幕,則和實際一致
U16 x_tsc,y_tsc;
void Main(void)
{
int i;
……硬件初始化……
Uart_Printf("\n觸摸屏和LCD綜合實驗\n\n");
Uart_Printf(" 觸摸處將顯一個方塊\n\n");
tsc_int_init(); //觸摸屏中斷初始化
tsc_init(); //觸摸屏初始化
lcd_init(); //LCD初始化
//test(); while(1);
} void test(void)
{
int i;
for(i=50;i<480;i+=50)
zhengfangxing(400,i,3000);
}
void tsc_int_init(void) //觸摸屏中斷初始化
{
rSUBSRCPND |= 1<<9; //INT_TC清0 rSRCPND |= 1<<31; //INT_ADC清0
rINTPND |= 1<<31; //INT_ADC清0
pISR_ADC = (U32)TSC_ISR; //申請中斷向量
rINTMSK = rINTMSK & ~(1<<31); //禁止ADC的屏蔽
rINTSUBMSK = rINTSUBMSK & ~(1<<9); //禁止TSC的屏蔽
rADCTSC = 0x0d3 ; //等待中斷模式的特定設置
}
void TSC_ISR(void) __irq //觸摸屏中斷例程
{
rINTMSK |= 1<<31; //ADC中斷的屏蔽
rINTSUBMSK |= 1<<9 | 1<<10; //TSC和ADC_S中斷屏蔽
tsc_get(); //得到觸點坐標
Uart_Printf("x=%d,y=%d\n",x_tsc,y_tsc);
zhengfangxing( 1.0084*y_tsc - 150,-0.82*x_tsc +600,12345);//實驗獲得轉換關系,精度有待提高 rSUBSRCPND |= 1<<9; //INT_TC清0
rSRCPND |= 1<<31; //INT_ADC清0
rINTPND |= 1<<31; //INT_ADC清0
rINTMSK = rINTMSK & ~(1<<31); //禁止ADC的屏蔽
rINTSUBMSK = rINTSUBMSK & ~(1<<9); //禁止TSC的屏蔽
rINTSUBMSK = rINTSUBMSK & ~(1<<10); //禁止ADC_S的屏蔽 }
void tsc_init(void) //觸摸屏初始化
{
rADCDLY= 0x5000;//必須要延時
rADCCON = (PCLK/adc_frequency - 1)<<6 | 1<<14 ; //設置ADC頻率,預分頻有效
}
void tsc_get(void)
{
rADCCON = rADCCON & ~(7<<3) | 7<<3 ; //選擇XP通道
rADCTSC = (0<<7)|(1<<6)|(1<<5)|(0<<4)|(1<<3)|(0<<2)|1 ; //X測量模式:YM=Z, YP=AIN[5] ,XM=GND, XP=V, PULL_UP=DISABLE, NORMAL, X-position (ENABLE=GND/V)
rADCCON|=0x1; //啟動ADC
while(rADCCON & 0x1); //等待啟動
while(!(rADCCON & 0x8000)); //等待是否轉換完畢
x_tsc = rADCDAT0&0x3FF; //得到轉換結果
rADCCON = rADCCON & ~(7<<3) | 5<<3 ; //選擇YP通道
rADCTSC = (1<<7)|(0<<6)|(0<<5)|(1<<4)|(1<<3)|(0<<2)|2 ; //Y測量模式:YM=GND, YP=V ,XM=Z, XP=AIN[7], PULL_UP=DISENBLE, NORMAL, Y-position (DISABLE=AIN/Z)
rADCCON|=0x1; //啟動ADC
while(rADCCON & 0x1); //等待啟動
while(!(rADCCON & 0x8000)); //等待是否轉換完畢
y_tsc = rADCDAT1&0x3FF; //得到轉換結果
tsc_int_init(); //觸摸屏中斷初始化
Delay(10);
while(!((rADCDAT0 & 0X8000) & (rADCDAT1 & 0X8000) ));//等待筆尖抬起
}
void lcd_init(void)
{
rGPCCON = 0xAAAAAAAA; //LCD功能
rGPDCON = 0xAAAAAAAA; //LCD功能
rGPGCON = rGPGCON & ~(3<<8) | 3<<8 ; //LCD電源功能
rLCDCON1 = rLCDCON1 & ~(0x3ff<<8) | CLKVAL<<8 ; //LCD頻率
rLCDCON1 = rLCDCON1 & ~(0x3<<5) | PNRMODE<<5 ; //顯示模式
rLCDCON1 = rLCDCON1 & ~(0xf<<1) | BPPMODE<<1 ; //BPP模式(每個像素用幾位表示)
rLCDCON1 = rLCDCON1 & ~(1) | 0 ; //關閉輸出
rLCDCON2 = rLCDCON2 & ~(0xff<<24) | VBPD<<24 ; //與LCD屬性一致
rLCDCON2 = rLCDCON2 & ~(0x3ff<<14) | (LINEVAL-1)<<14 ; //垂直尺寸
rLCDCON2 = rLCDCON2 & ~(0xff<<6) | VFPD<<6 ; //與LCD屬性一致
rLCDCON2 = rLCDCON2 & ~(0x3f) | VSPW ; //與LCD屬性一致
rLCDCON3 = rLCDCON3 & ~(0x7f<<19) | HBPD<<19 ; //與LCD屬性一致
rLCDCON3 = rLCDCON3 & ~(0x7ff<<8) | (HOZVAL-1)<<8 ; //水平尺寸
rLCDCON3 = rLCDCON3 & ~(0xff) | HFPD ; //與LCD屬性一致
rLCDCON4 = rLCDCON4 & ~(0xff) | HSPW ; //與LCD屬性一致
rLCDCON5 = rLCDCON5 & ~(1<<11) | FRM565<<11 ; //模式:565或5551
rLCDCON5 = rLCDCON5 & ~(1<<3) | PWREN<<3 ; //供電引腳使能 ( GPG4 )
rLCDCON5 = rLCDCON5 & ~(1<<1) | BSWP ; //字節是否交換
rLCDSADDR1 = rLCDSADDR1 & ~(0x1ff<<21) | ( ( (U32)pixel>>22 )&0x1ff )<<21 ; //緩存區首地址高位[30:22]->rLCDSADDR1[29:21]
rLCDSADDR1 = rLCDSADDR1 & ~(0x1fffff) | ( (U32)pixel>>1 )&0x1fffff ; //緩存區首地址低位[21:1]->rLCDSADDR1[20:0]
rLCDSADDR2 = rLCDSADDR2 & ~(0x1fffff) | ( ((U32)pixel+LINEVAL*HOZVAL*2)>>1 )&0x1fffff ; //緩存區(尾地址+1)低位[21:1]->rLCDSADDR2[20:0]
rLCDSADDR3 = rLCDSADDR3 & ~(0x7ff<<11) | OFFSIZE<<11 ; //虛擬屏幕偏移長度
rLCDSADDR3 = rLCDSADDR3 & ~(0x7ff) | PAGEWIDTH ; //虛擬屏幕寬度
rLCDCON1 = rLCDCON1 & ~(1) | ENVID ; //開啟輸出,這個要最后做,不然有問題
} U8 make_pixel(U16 x,U16 y,U32 color)
{
if(x<HOZVAL && y<LINEVAL)
{
pixel[y][x] = color;
return 1;
}
else return 0;
}
void rectangle(U16 x1,U16 x2,U16 y1,U16 y2,U32 color)
{
U16 x;
for(;y1<=y2;y1++)
for(x=x1;x<=x2;x++)
make_pixel(x,y1,color);
}
void zhengfangxing(U16 x, U16 y,U32 color)
{
rectangle(x-10,x+10,y-10,y+10,color);
} //******************************************************************* 實驗運行基本正常:

|