单片机
返回首页

2440触摸屏的设置

2016-12-01 来源:eefocus

一、触摸屏原理:

    可以参考相关资料,本人参考的是阿南的<<>入门与实践>>中有关触摸屏的内容。

二、2440触摸屏的设置

   1、ADCON: ADC 控制寄存器

#define ADCPRS 24

   rADCCON=(1<<14)+(ADCPRS<<6);

   使能读启动操作。

   AD转换器的预分频值为24,注意:

   AD转换频率=PCLK/(分频值+1),且AD的最高频率为2.5M,这里PCLK=50M,所以AD的转换频率为2M.

  2、ADCTSC ADC 触摸屏控制寄存器

   rADCTSC=0xd3;

当笔尖落下时触摸屏控制器产生中断 (INT_TC) 信号。

YM输出驱动器使能

YP输出驱动器禁止

XM输出驱动器禁止

XP输出驱动器禁止

等待中断模式

注意:自动x,y方向测量是指当测完x跟y后产生ADC中断。

 3、ADCDLY ADC 启动或初始化延时寄存器

   rADCDLY=50000;

   设置一个适当的便可

 4、设置中断服务函数

pISR_ADC = (int)AdcTsAuto;  //设置中断函数地址

rINTMSK=~BIT_ADC;       //ADC Touch Screen Mask bit clear

       rINTSUBMSK=~(BIT_SUB_TC); //触摸屏中断

三、触摸屏检测及校正

1、触摸屏的检测思路类似于按键检测,以下为检测一个点的思路:

(1)、设置等待中断,按下有效

(2)、按下进入中断后读取x,y数据

(3)、读取完成后设置成弹起中断,等待一个动作结束

(4)、结束后进入下一次准备。


   程序如下:

void __irq AdcTsAuto(void)

{

    //解摸屏按下,产生中断

       U32 saveAdcdly;

       if(rADCDAT0&0x8000)

              rADCTSC&=0xff;  // Set stylus down interrupt bit

    //关闭XP上拉,启动自动顺序x/y转换

       rADCTSC=(1<<3)|(1<<2);         //Pull-up disable, Seq. X,Y postion measure.

    //设置延时时间

       saveAdcdly=rADCDLY;

       rADCDLY=40000; 

               

    //开始AD转换

       rADCCON|=0x1;                   //start ADC

    //AD转换启动后开始位会被清0

       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~!!

       //查询INT_ADC中断,直到查到结束中断标志     

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

    //产生中断标志说明x,y已经转换结束,读取数据。

       xdata=(rADCDAT0&0x3ff);

      ydata=(rADCDAT1&0x3ff);

       //按下标志

       touchedflag=TRUE;

       //check Stylus Up Interrupt.

    //清中断,并且重开中断,再次设置等待中断,这一次设置等待弹起中断。

       rSUBSRCPND|=BIT_SUB_TC;

       ClearPending(BIT_ADC);

       rINTSUBMSK=~(BIT_SUB_TC);

       rINTMSK=~(BIT_ADC);

                      

       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

              }

       }    

 

   //此时,一个触摸屏动作检测已经完成,输出坐标信息。

       Uart_Printf('count=%03d  XP=%d, YP=%d\n', count++, xdata, ydata);    //X-position Conversion data           

 

    //再次设置成按下中断,等待下一次动作

       rADCDLY=saveAdcdly;

       rADCTSC=rADCTSC&~(1<<8); // Detect stylus Down interrupt signal.

       rSUBSRCPND|=BIT_SUB_TC;

       rINTSUBMSK=~(BIT_SUB_TC); // Unmask sub interrupt (TC)    

       ClearPending(BIT_ADC);

}

 

2、触摸屏的校正

触摸屏校正的目的是为了把触摸屏上的坐标跟LCD上坐标一一对应起来。


如上图,假设LCD与触摸屏的点是一一对应的,LCD上四个角的点为人为设置的点(实际只需要上左上跟右下两个点就可以了,还有两个点是用来做平均的),触摸屏上四个角的点为LCD上四个点对应转换来的数值。(ax,ay)为正常工作时点击的点,(x,y)为(ax,ay)对应的坐标。

那么LCD与触摸屏的关系为:

x=x0+(x1-x0)*(ax-ax0)/(ax1-ax0)

y=y0+(y1-y0)*(ay-ay0)/(ay1-ay0)

具体步骤:

以320*240的屏举例:

(1)、设置四个LCD点(30,30)、(30,210)、(290,210)、(290,30)

(2)、在屏幕上依次画出这四个点(以四个点为中心点的十字形),并且依次点击这四个点,分别记下四个点转换出来的数值。(ax0,ay0),(ax0,ax1),(ax1,ay1),(ax1,ay0)

(3)、由x=x0+(x1-x0)*(ax-ax0)/(ax1-ax0),可以把(x1-x0)/(ax1-ax0)转换成常量系数Kx,那么

x=x0+(ax-ax0)*Kx,Kx=(x1-x0)/(ax1-ax0) ,这样只需记下x0,ax0,Kx三个值便可。

同样的:

y=y0+(y1-y0)*(ay-ay0)/(ay1-ay0), y=y0+(ay-ay0)*Ky, Ky=(y1-y0)/(ay1-ay0),只需记下y0,ay0,Ky便可.

(4)、校正完成,正常工作时当点击触摸屏时产生(ax,ay),则

x=x0+(ax-ax0)*Kx

y=y0+(ay-ay0)*Ky

便可以很容易求出实际坐标。

 

校正程序如下:

//触摸屏校正

//x=x0+(x1-x0)*(ax-ax0)/(ax1-ax0)

//x=x0+(ax-ax0)*Kx

//Kx=(x1-x0)/(ax1-ax0)

//x0,ax0,Kx

//同理

//y=y0+(y1-y0)*(ay-ay0)/(ay1-ay0)

//y=y0+(ay-ay0)*Ky

//Ky=(y1-y0)/(ay1-ay0)

//y0,ay0,Ky

volatile U32 touchedflag=FALSE;

//必要的参数

typedef struct cali

{

       int   x0;

       int   ax0;

       float       Kx;

       int   y0;

       int   ay0;

       float Ky;

      

}TCpara;

typedef struct Point

{

       int x;

       int y;

}POINT;

//LCD四个校正点

POINT LCDPoint[4]=

{

       30    ,30,    //左上

       30    ,210,   //左下

       290  ,210,   //右下

       290  ,30    //右上

};

TCpara TCcal;

void touchsrc_calibration()

{    

       U32 i;

       //int x=30,y=30;

       //int LCDx1=30,LCDy1=30,LCDx2=30,LCDy2=150,LCDx3=290,LCDy3=210;

       //TCx3=0,TCy3=0,TCx4=0,TCy4=0;

       //float A,B,C,D,E,F,K;

       //float K

       Lcd_ClearScr(0);

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

       {

       //分别画出四个点         Glib_Line(LCDPoint[i].x-10,LCDPoint[i].y,LCDPoint[i].x+10,LCDPoint[i].y,(U32)(255<<11));

       Glib_Line(LCDPoint[i].x,LCDPoint[i].y-10,LCDPoint[i].x,LCDPoint[i].y+10,(U32)(255<<11));

       //等待按下

              while(!touchedflag);

              touchedflag=FALSE;

       //分别记下LCD四个点对应的触摸屏的值,因为TQ2440触摸屏的x,接到了控制器的y上,y接到了x上,所以这里反过来记。

              switch(i)

              {

                     case 0:

                     TCx0+=ydata;

                     TCy0+=xdata;

                     break;

                    

                     case 1:

                     TCx0+=ydata;

                     TCy1+=xdata;

                     break;

                    

                     case 2:

                     TCx1+=ydata;

                     TCy1+=xdata;

                     break;

                    

                     case 3:

                     TCx1+=ydata;

                     TCy0+=xdata;

                     break;

                    

                     default:

                     break;

              }

              Lcd_ClearScr(0);

       }

       //得出左上与右下两个点的AD值,注意,其余两个点是为左上与右下两个点服务的。

       TCx0=TCx0>>1;

       TCx1=TCx1>>1;

       TCy0=TCy0>>1;

       TCy1=TCy1>>1;

       //记下LCD初始点

       TCcal.x0 =LCDPoint[0].x;

       TCcal.y0 =LCDPoint[0].y;

       //记下触摸屏初始点

       TCcal.ax0=TCx0;

       TCcal.ay0=TCy0;

    //算出Kx,Ky

       TCcal.Kx =(float)(LCDPoint[2].x-LCDPoint[0].x)/(TCx1-TCx0);

       TCcal.Ky =(float)((LCDPoint[2].y)-LCDPoint[0].y)/(TCy1-TCy0);//(TCy0-TCy1);

       Uart_Printf('TCcal.x0=%d,TCcal.y0=%d\n',TCcal.x0,TCcal.y0);

       Uart_Printf('TCcal.ax0=%d,TCcal.ay0=%d\n',TCcal.ax0,TCcal.ay0);

       Uart_Printf('TCcal.Kx=%d,TCcal.Ky=%d\n',TCcal.Kx,TCcal.Ky);

 

}

 

//打印坐标

void PrintTouchSrcPoint()

{

       int TCx,TCy,x,y;

    //等待按下

       while(!touchedflag);

       touchedflag=FALSE;

       TCx=ydata;

       TCy=xdata;

       //算出x,y坐标

       x=TCcal.x0+(TCx-TCcal.ax0)*TCcal.Kx;

       y=TCcal.y0+(TCy-TCcal.ay0)*TCcal.Ky;

       if((x>=0 && x<320) && (y>=0 && y<240))

       {

       //y=239-y;

       Glib_Rectangle(x-1,y-1,x+1,y+1,(U32)(255<<11));

       Glib_FilledRectangle(x-1,y-1,x+1,y+1,(U32)(255<<11));

       }

       Uart_Printf('x=%d,y=%d\n',x,y);

}

小结:

1、  通过本章学习,理解了四线电阻式触摸屏的原理。并且完成触摸屏检测与校正的实验。

2、  参考了阿南的<<>入门与实践>>中触摸屏部分以及网络资源。


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 光控音效发生器电路

  • 离子检测器电路分析

  • 非常简单的150W功放电路图

  • 一个简单的警笛电路图

  • 如何使用LED驱动器LM3915制作振动计

  • 一个简单的立体声平衡指示器电路

    相关电子头条文章