平臺 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