ADC触摸屏转换---那些年我们一起玩mini2440(arm9)裸机

触摸屏驱动程序设计

触摸屏工作原理:

四线电阻屏结构上如图,是在玻璃或丙稀酸基板上覆盖两层均匀导电的ITO层,分别作为x电极和y电极,他们之间由均匀排列的透明格点分来绝缘。X电极和y电极的正负端由导电线(黑色粗体线)从两端引出,引出x-,x+,y-,y+.

当接触触摸屏表面并施加压力时,上层的ITO导电层和下层的ITO导电层发生接触,形成上面右图的等效电路。

1.y坐标计算:

y+加驱动电压V-drivey-接地。X+作为引出端测量接触点的电压,由于ITO层均匀导电,触电电压与V-drive电压之比等于Y坐标与屏高度之比。

2.x坐标计算:

x+加驱动电压V-drive电压,x-接地。Y+作为引出端测量接触点的电压,由于ITO层均匀导电,触点电压与V-drive电压比等于x坐标与屏宽度之比。

y=Vx/V-driv *heightx=Vy/ V-driv * width

触摸屏工作流程(理解好这几步流程,代码至少能看懂30%

1.设置触摸屏接口为等待中断模式,等待触摸屏被按下。

2.如果中断INT_TC发生,选择X,Y坐标转换模式(x/y坐标分别转换模式,x/y坐标自动转换),启动AD转换。

3.AD转换完后,通过中断(INT_ADC,获取x/y坐标,

ADCDAT0 bit[9:0]-x坐标;

ADCDAT1 bit[9:0]-y坐标;

4.设置触摸屏接口为等待中断模式,等待触摸笔离开触摸屏。

5.返回步骤1,等待下次触摸笔被按下。

#define    GLOBAL_CLK             1

#include <stdlib.h>

#include <string.h>

#include "def.h"

#include "option.h"

#include "2440addr.h"

#include "2440lib.h"

#include "2440slib.h"

#include "mmu.h"

#include "profile.h"

#include "memtest.h"

 

 

#define ADC_FREQ 2500000

//#define ADC_FREQ   1250000

 

int count = 0;

volatile U32 preScaler;

 

int xdata,ydata;

void Test_Touchpanel(void);

 

 

static void __irq AdcTsAuto(void);

 

 

static void cal_cpu_bus_clk(void);

void Set_Clk(void);

 

/*************************************************

Function name: delay

Parameter    : times

Description     : 延时函数

Return            : void

Argument     : void

Autor & date : Daniel

**************************************************/

void delay(int times)

{

    int i,j;

    for(i=0;i<times;i++)

       for(j=0;j<400;j++);

}

/*************************************************

Function name: Main

Parameter    : void

Description     : 主功能函数

Return            : void

Argument     : void

Autor & date : Daniel

**************************************************/

int Main(void)

{     

   

    int Scom=0;

    MMU_Init();

    Set_Clk();

    Uart_Init(0,115200);

    Uart_Select(Scom);

   // Uart_Printf("\nHello World!\n");

    

    Test_Touchpanel();

    

    while(1);

       return 0;

 

}     

 

/*************************************************

Function name: Test_Touchpanel

Parameter    : void

Description     : 触摸屏初始化

Return            : void

Argument     : void

Autor & date : Daniel

**************************************************/

void Test_Touchpanel(void)

{

   

    rADCDLY=50000;                  //Normal conversion mode delay about (1/3.6864M)*50000=13.56ms

    

    /*设置AD转频率*/

    preScaler = ADC_FREQ;

       Uart_Printf("ADC conv,freq. = %dHz\n",preScaler);

       preScaler = 50000000/ADC_FREQ - 1; //PCLK=50M

       rADCCON = (1<<14)|(preScaler<<6); //ADCPRS En,PRSCVL

   // rADCCON=(1<<14)+(preScaler<<6);   //ADCPRS En, ADCPRS Value

 

    Uart_Printf("ADC touch screen test\n");

 

       /*设置触摸屏为等待中断模式,等待触摸笔被按下*/

    rADCTSC=0xd3;  //Wfait,XP_PU,XP_Dis,XM_Dis,YP_Dis,YM_En

    

    /*clear irq*/

    //ClearPending(BIT_ADC);

    rSRCPND = 0x80000000;

       rINTPND = 0x80000000;

    ClearSubPending(BIT_SUB_TC);  

       

       

 

    pISR_ADC = (U32)AdcTsAuto;

 

 

       /*enable INT_TC irq*/

       //EnableIrq(BIT_ADC);

    rINTMSK = 0x7fffffff;//允许中断           

    EnableSubIrq(BIT_SUB_TC);

    

}

 

/*************************************************

Function name: AdcTsAuto

Parameter    : void

Description     : 中断服务程序

Return            : void

Argument     : void

Autor & date : Daniel

**************************************************/

static void __irq AdcTsAuto(void)

{

 

       U32 saveAdcdly;

       

       /****************stylus down************************/

       /*检测子中断源,判断是否是INT_TC中断,且触摸笔按下*/

       if(rSUBSRCPND & (BIT_SUB_TC))//产生中断

       {

              if( !(rADCDAT0&0x8000))//按下产生的中断

                     Uart_Printf("\nStylus down\n");

              else                   //抬起产生的中断   

                  Uart_Printf("\nStylus up\n"); 

       }

       

       /*pull-up disable,自动连续X,Y坐标转换*/

       rADCTSC = (1<<3)|(1<<2);

       saveAdcdly=rADCDLY;

       rADCDLY=40000;    //延时             //Normal conversion mode delay about (1/50M)*40000=0.8ms

       

       /*开始AD转换*/

       rADCCON|=0x1;                   //start ADC

    while(rADCCON & 0x1);            //check if Enable_start is low

    

       while(!(rADCCON & 0x8000));//转换是否结束  //check if EC(End of Conversion) flag is high, This line is necessary~!!

       

       while(!(rSRCPND & 0x80000000));  //check if ADC is finished with interrupt bit

 

       /*获取X,Y坐标*/

       xdata=(rADCDAT0&0x3ff);

    ydata=(rADCDAT1&0x3ff);

    

    ClearSubPending(BIT_SUB_TC);

    //ClearPending(BIT_ADC);

    rSRCPND = 0x80000000;

       rINTPND = 0x80000000;  

       

 

    EnableSubIrq(BIT_SUB_TC);

     //EnableIrq(BIT_ADC);

    rINTMSK = 0x7fffffff;

    /****************stylus down************************/

    

    

    /****************stylus up**************************/

 

       /*设置触摸屏为等待中断模式,等待触摸笔抬起*/

    rADCTSC =0xd3;    //Waiting for interrupt

       rADCTSC=rADCTSC|(1<<8); // Detect stylus up interrupt signal.

       

       while(1)         //to check Pen-up state

       {

              if(rSUBSRCPND & (BIT_SUB_TC))   //check if ADC is finished with interrupt bit

              {

                                   Uart_Printf("Stylus Up Interrupt~!\n");

                                   break;     //if Stylus is up(1) state

              }

       }     

       /****************stylus up**************************/

       

       Uart_Printf("count=%03d  XP=%04d, YP=%04d\n", count++, xdata, ydata);  

       

       rADCDLY=saveAdcdly; 

       /*设置触摸屏为等待中断模式,等待下次触摸笔按下*/

    rADCTSC =0xd3;    //Waiting for interrupt

    

       ClearSubPending(BIT_SUB_TC);  

    //ClearPending(BIT_ADC);

    rSRCPND = 0x80000000;

       rINTPND = 0x80000000;

 

    EnableSubIrq(BIT_SUB_TC);

     //EnableIrq(BIT_ADC);

    rINTMSK = 0x7fffffff;

}

 

 

/*************************************************

Function name: Set_Clk()

Parameter    : void

Description     : 设置CPU的时钟频率

Return            : void

Argument     : void

Autor & date : Daniel

**************************************************/

void Set_Clk(void)

{

       int i;

       U8 key;

       U32 mpll_val = 0 ;

       i = 2 ;                  //don't use 100M!

                               //boot_params.cpu_clk.val = 3;

       switch ( i ) {

       case 0:     //200

              key = 12;

              mpll_val = (92<<12)|(4<<4)|(1);

              break;

       case 1:     //300

              key = 13;

              mpll_val = (67<<12)|(1<<4)|(1);

              break;

       case 2:     //400

              key = 14;

              mpll_val = (92<<12)|(1<<4)|(1);

              break;

       case 3:     //440!!!

              key = 14;

              mpll_val = (102<<12)|(1<<4)|(1);

              break;

       default:

              key = 14;

              mpll_val = (92<<12)|(1<<4)|(1);

              break;

       }

       

       //init FCLK=400M, so change MPLL first

       ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);   //set the register--rMPLLCON

       ChangeClockDivider(key, 12);    //the result of rCLKDIVN [0:1:0:1] 3-0 bit

       cal_cpu_bus_clk();    //HCLK=100M   PCLK=50M

}

/*************************************************

Function name: cal_cpu_bus_clk

Parameter    : void

Description     : 设置PCLK\HCLK\FCLK的频率

Return            : void

Argument     : void

Autor & date : Daniel

**************************************************/

static void cal_cpu_bus_clk(void)

{

       static U32 cpu_freq;

    static U32 UPLL;

       

       U32 val;

       U8 m, p, s;

       

       val = rMPLLCON;

       m = (val>>12)&0xff;

       p = (val>>4)&0x3f;

       s = val&3;

 

       //(m+8)*FIN*2 不要超出32位数!

       FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;     //FCLK=400M  FIN=12000000

       

       val = rCLKDIVN;

       m = (val>>1)&3;

       p = val&1;      

       val = rCAMDIVN;

       s = val>>8;

       

       switch (m) {

       case 0:

              HCLK = FCLK;

              break;

       case 1:

              HCLK = FCLK>>1;

              break;

       case 2:

              if(s&2)

                     HCLK = FCLK>>3;

              else

                     HCLK = FCLK>>2;

              break;

       case 3:

              if(s&1)

                     HCLK = FCLK/6;

              else

                     HCLK = FCLK/3;

              break;

       }

       

       if(p)

              PCLK = HCLK>>1;

       else

              PCLK = HCLK;

       

       if(s&0x10)

              cpu_freq = HCLK;

       else

              cpu_freq = FCLK;

              

       val = rUPLLCON;

       m = (val>>12)&0xff;

       p = (val>>4)&0x3f;

       s = val&3;

       UPLL = ((m+8)*FIN)/((p+2)*(1<<s));

       UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;

}

 

你可能感兴趣的:(ini)