裸机系列——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


你可能感兴趣的:(c,String,UP,byte,平台,delay)