裸機系列——s3c2440之觸摸屏

平臺         mini2440

觸摸屏     索尼x-35 3.5寸觸摸屏

1.0、觸摸屏與lcd

觸摸屏與lcd是倆個獨立的屏在lcd中已經講過了,但是這裏在提一下,主要是涉及到一個觸摸屏校正的問題,我以前一直很是不解我手指點的什麼東西電腦是怎麼知道的,直到我弄觸摸屏的時候在明白,原來是因爲lcd與觸摸屏分開但是他們之間有對應關係,簡單的說就是一個觸摸屏的座標點對應lcd的一個像素點,這樣當我們按下觸摸屏後,系統通過計算得到該地方的座標,然後通過對應關係找到相應位置的lcd顯示的內容。因爲觸摸屏和lcd是獨立的,總是因爲一些物理的原因會有一些位置上的改變,所以這種對應關係不是不變的,我們可以通過開機的時候的校驗來確定這種關係,比如(下面是引用趙老師的)

LCD上每個點PD的座標爲[XD,YD],觸摸屏上每個點PT的座標爲[XT,YT]。要實現觸摸屏上的座標轉換爲LCD上的座標,需要下列公式進行轉換:

XD=A×XT+B×YT+C

YD=D×XT+E×YT+F

這樣我們只有確定了ABCDEF六個參數我們就可以確定這種對應關係了,其他的點就都可以對應了。這就是觸摸屏校驗的原理,因爲我沒有去弄,所以就不多說了。

2.0、電阻觸摸屏的原理

這個的話說簡單就簡單說複雜就複雜,簡單的說的話通過X方向和Y方向的分開的電阻線,當你按下觸摸屏的時候XY就有一個觸點,然後通過計算在XY方向的分壓值,在把電壓值經過AD轉換後即可得到xy的座標。複雜的話這個就說不清啦,就我知道的這點東西,呵呵,不過很多東西都不需要我們自己去算了,2440觸摸屏有這些功能了只有我們去設置寄存器就可以了,像設置思想哦那個x/y座標轉換模式後,系統就自動轉換出觸點的xy座標值了。

3.0、觸摸屏的流程

觸摸屏的流程我覺得是整個觸摸屏比較重要的地方,其他的設置好寄存器之後讀數據就可以了。流程中比較重要的是倆箇中斷,觸摸屏中斷和ADC中斷,其中觸摸屏中斷包括觸摸屏按下中斷和觸摸屏鬆開中斷。

初始化中斷和寄存器——>等待觸摸屏中斷模式——>TC 中斷(觸摸屏按下中斷)——>(進入xy自動轉換模式)——>(ADC轉換完成後)ADC中斷——>(鬆開觸摸屏)——>TC中斷(鬆開觸摸屏)——>等待觸摸屏中斷模式(循環)

代碼比較簡單,不過前面加入了串口的程序用於調試和輸出信息

/*************************************************
file name 	Touchp
function	Touch Screen test 
硬件平臺	mini2440開發板
		索尼X-35觸摸屏 3.5寸 240 * 320
problem		串口顯示用自己的程序第一個字符有問題,有時不能顯示,用參考的
			Uart_Send_String也不行,用可變參數的Uart_printf顯示沒問題
finishtime	2011-08-11 19:38
作者		周茂夫
修改記錄	暫無
*************************************************/
#define	GLOBAL_CLK		1

#include <stdlib.h>
#include <string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "mmu.h"

#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

#define baudrate 115200 

#define wait_down_int()	(rADCTSC = 0xd3)
#define wait_up_int()	(rADCTSC = 0x1d3)
#define mode_auto_xy()	(rADCTSC = 0x0c)
#define Read_Adcdata0()	(int)(rADCDAT0 & 0x3ff)
#define Read_Adcdata1()	(int)(rADCDAT1 & 0x3ff)
#define PRSCVL(n)		((n)<<6)

static void delay(int times)
{
	int i = 1000 ;
	while(times--)
	{
		for(; i>0; --i)
			;
	}
}

/***********************************
UART_int初始化led IO端口GPBCON5-8
初始化GPBHCON爲串口通信
配置串口通信寄存器
配置中斷寄存器
************************************/
void UART_int_init(void)
{
	/********configuration LED IO port**********/
	rGPBCON &= ~(0xff<<10) ;
	rGPBCON |= 0x55<<10 ;
	
	/*******configuration GPHCON to UART*******/
	rGPHCON &= ~(0xf<<4) ;
	rGPHCON |=  0xa<<4 ;
	
	/****configuration UART0 communication register******/
	rULCON0 = 0x03 ;						//8-bits,1 stop bit, no parity
	rUCON0  = 0x05 ;
	rUBRDIV0= (int)(PCLK/baudrate/16) -1 ;	//configuration UART baudrate
	
	/*****clean interrupt bit clea RX_INT******/
	rSUBSRCPND |= 0x1 ;
	rSRCPND |= 1<<28 ;
	rINTPND |= 1<<28 ;

	/******open UART interrupt*********/
	rINTSUBMSK &= ~(0x1) ;
	rINTMSK &= ~(0x1<<28) ;	
}

//UART send byte
void UART_send_byte(char Tx_data)
{
	while(!(rUTRSTAT0&0x2)) ;//wait Tx empty
	if(Tx_data == '\n')		//Tx '\n'
	{
		rUTXH0 = 0x0d ;
		while(!(rUTRSTAT0&0x2)) ;
		rUTXH0 = 0x0a ;
	}
	else
	{
		rUTXH0 = Tx_data ;
	}
}
//UART send string
void UART_send_string(const char *str) 
{
	while(*str)
	{
		UART_send_byte(*str) ;
		str++ ;
	}
}
//UART receive byte
void UART_receive_byte(void) 
{
	char temp ;
	
	while(!(rUTRSTAT0&0x1)) ;	//wait RX ready
	
	temp = rURXH0 ;
	UART_send_byte(temp) ;
	
}

/*******************************************
中斷處理函數
置1清除中斷,注意順序,先子中斷後父中斷
點亮led燈
********************************************/
void __irq UART0_interrupt(void)
{
	/******clean interrupt bit*************/
	rSUBSRCPND |= 0x1 ;
	rSRCPND |= 1<<28 ;
	rINTPND |= 1<<28 ;
	
	//rGPBDAT &= ~(0xf<<5) ;	//lighten led
	UART_receive_byte(); 
	/*
	if(temp=='s'||temp=='S')
	{
		***********Close interrupt*************
		rINTSUBMSK 	|= (BIT_SUB_TC) ;
		rINTSUBMSK 	|= (BIT_SUB_ADC) ;
		rINTMSK 	|= (BIT_ADC) ;
		Uart_Printf("Touch Screen Test is Finished!!!\n") ;
	}	
	*/
}

/**************【Touch Screen】****************/
static void Ts_Init(void)
{
	//使能預分頻功能 設置A/D時鐘 = PCLK/(49+1)
	rADCCON		= (1<<14)|PRSCVL(49);
	rADCDLY		= 50000 ;
	rADCUPDN	= 0x3 ;	//按下 鬆開 都產生TC中斷
		
	/******clean interrupt bit*******/ 
 	rSUBSRCPND	|= BIT_SUB_ADC ; 
 	rSUBSRCPND	|= BIT_SUB_TC ; 
 	rSRCPND 	|= BIT_ADC ;
	rINTPND 	|= BIT_ADC ;

	/***********Open ADC TC interrupt*********/
	rINTSUBMSK 	&= ~(BIT_SUB_TC) ;
	rINTSUBMSK 	&= ~(BIT_SUB_ADC) ;
	rINTMSK 	&= ~(BIT_ADC) ;

}

static void interrupt_Tc(void)
{
	if(rADCDAT0 & 0x8000)
	{
		Uart_Printf("Stylus Up \n\r") ;
		wait_down_int() ;	//wait interrupt mode
	}
	else
	{
		Uart_Printf("Stylus Down: ") ;
		mode_auto_xy() ; 	//進入自動轉換xy模式
 		
 		rADCCON |= 1 ;	//start ADC 
 	}
 	/******clean interrupt bit*************/ 
 	rSUBSRCPND	|= BIT_SUB_TC ; 
 	rSRCPND 	|= BIT_ADC ;
	rINTPND 	|= BIT_ADC ;
}

static void interrupt_Adc(void)
{
	Uart_Printf("xdata = %4d,  ydata = %4d\r\n", Read_Adcdata0(), Read_Adcdata1()) ;	
	
	wait_up_int() ;	//wait 鬆開觸摸屏 中斷模式
 	
 	/******clean interrupt bit*************/ 
 	rSUBSRCPND	|= BIT_SUB_ADC ; 
 	rSRCPND 	|= BIT_ADC ;
	rINTPND 	|= BIT_ADC ;	
}

void __irq AdcTsinttrupt(void)
{
	rGPBDAT &= ~(0xf<<5) ;	//lighten led
	
	if(rSUBSRCPND & BIT_SUB_TC)
	{	
		UART_send_string("Tc interrupt\n") ;
		interrupt_Tc() ;	
	}

	if(rSUBSRCPND & BIT_SUB_ADC)
	{		
		UART_send_string("Adc interrupt\n") ;
		interrupt_Adc() ;
	}	
}

static void Ts_test(void)
{
	Ts_Init() ;
	pISR_ADC	= (U32)AdcTsinttrupt ;
	wait_down_int() ;	//wait interrupt mode
	Uart_Printf("Touch Screen test,Please send 's'/'S' stop test\n") ;	
}
/*******************************************************************
串口UART是掛在PCLK總線上的,需要設置PCLK時鐘,即需要設置2440時鐘。
首先需要設置PLLCON寄存器設置CPU時鐘(FCLK),然後設置FCLK HCLK PCLK的
分頻比,確定好PCLK時鐘。
********************************************************************/
int Main(void)
{
	MMU_Init();
	ChangeMPllValue(127,2,1);		//405MHZ
	ChangeClockDivider(13,12);        //1:3:6	
	
	UART_int_init() ;
	pISR_UART0 = (U32)UART0_interrupt ;
	//delay(5000) ;
	Uart_SendString("\nUart initial finish!!\n") ;
	Ts_test(); 
	Uart_Printf("Touch Screen initial finish\n") ;
	while(1) 
	{
		
	}
	return 0 ;
}

2011--09--04 11:46


發佈了53 篇原創文章 · 獲贊 21 · 訪問量 37萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章