• TQ2440之触摸屏


    1.触摸屏原理

    S3C2440A内置一个带8个模拟输入通道的10位逐次逼近型(recycling type)CMOS模数转换器。在2.5MHz的模数转换时钟频率下,转换速率可达到500KSPS(Kilo Samples Per Second),并且支持片内采样保持功能和省电模式。S3C2440A还带有触摸屏接口,可以控制/选择触摸屏的XP,XM,YP,YM输入以进行X,Y位置转换。

    AD转换器频率=GCLK/(p+1);

    AD转换时间=1/(AD转换器频率/5)=5*(p+1)/GCLK;

    GCLK是系统主时钟频率,一般为50Mhz,p(0~255)是预分频值,除以5表示每次转换需要5个时钟周期。AD转换器的设计最大时钟频率为2.5MHz,在系统时钟为50Mhz、AD转换器时钟频率为2.5Mhz时,p最大为19;最大转换频率为0.5MHz,所以最大转换速率为0.5M个采样每秒,即500KSPS。

    触摸屏有四种转换模式:

    • 普通转换模式:与普通AD转换器的使用一样,通过设置ADCCON来初始化,并以一个读和写ADCDAT0的操作完成。
    • X/Y分别转换模式:分为X位置转换模式和Y位置转换模式,这两种模式下,触摸屏分别把X、Y位置转换数据写入到ADCDAT0和ADCDAT1中之后,向中断控制器发起中断请求。
    • 自动X/Y位置转换:触摸屏依次转换X和Y位置,把转换的结果分别写入到ADCCON0和ADCDAT1中,然后向中断控制器发起中断请求。
    • 等待中断模式:设置ADCTSC为0xD3,当触控笔按下时,想中断控制器发起中断请求。本篇文章主要讲等待中断模式。

    触摸屏初始化: 

    #define ADCPRS 9
    void Init_Touchpanel(void)
    {   
        rADCDLY=50000; //ADC转换启动延时值
        rADCCON=(1<<14)+(ADCPRS<<6);   //预分频使能, 预分频值为ADCPRS
        rADCTSC=0xd3;  //等待中断模式
    
        pISR_ADC = (int)AdcTsAuto;//中断入口函数
        rINTMSK &= ~BIT_ADC;       //使能ADC中断
        rINTSUBMSK &= ~(BIT_SUB_TC);//使能ADC子中断
    }

    中断服务程序:

    void __irq AdcTsAuto(void)
    {
        U32 saveAdcdly;
    
        rADCTSC=(1<<3)|(1<<2);         //XP上拉禁止,自动测量x方向和y方向
        saveAdcdly=rADCDLY;
        rADCDLY=40000;                 //延时
        rADCCON|=0x1;                   //开始ADC转换
        while(rADCCON & 0x1);        //成功启动后此位被清零
        while(!(rADCCON & 0x8000));     //等待ADC转换结束        
        while(!(rSRCPND & (BIT_ADC)));  //等待ADC转换完成中断标志位
        xdata=(rADCDAT0 & 0x3ff);         //读取转换后的值
         ydata=(rADCDAT1 & 0x3ff);
        flagTS=1;//此标志用于触摸屏校准标志
        rSUBSRCPND|=BIT_SUB_TC;//清中断
        ClearPending(BIT_ADC);
        rINTSUBMSK&=~(BIT_SUB_TC);//使能中断
        rINTMSK&=~(BIT_ADC);
        rADCTSC =0xd3;    //再次设置成等待中断模式
        rADCTSC=rADCTSC|(1<<8); //检测笔尖抬起中断
        while(1)        //to check Pen-up state
        {
            if(rSUBSRCPND & (BIT_SUB_TC))    //监测到
            {
                break;//退出循环
            }
        }               
    
        rADCDLY=saveAdcdly; 
        rADCTSC=rADCTSC&~(1<<8); // 禁止检测笔尖抬起中断
        rSUBSRCPND|=BIT_SUB_TC;//清中断
        rINTSUBMSK&=~(BIT_SUB_TC);
        ClearPending(BIT_ADC);
    }

    2.触摸屏校准

    我们在点击触摸屏时,实际上得到的是该点的电压值,而不是该点的位置坐标,需要一定的计算才能得到该点的实际坐标。

     这里介绍一下三点法校准。

    设LCD上每个点PD的坐标为[XD,YD],触摸屏上每个点PT的坐标为[XT,YT]。要实现触摸屏上的坐标转换为LCD上的坐标,需要下列公式进行转换:

    XD=A×XT+B×YT+C;YD=D×XT+E×YT+F;

    因为其中一共有六个参数(A,B,C,D,E,F),因此只需要三个取样点就可以求得这六个参数。这六个参数一旦确定下来,只要给出任意触摸屏上的坐标点PT,代入这个公式,就可以得到它所对应的LCD上像素点的坐标PD。

    已知LCD上的三个取样点为:PD0,PD1,PD2,它们所对应的触摸屏上的三个点为:PT0,PT1,PT2。A,B,C,D,E,F这六个参数最终的结果都是一个分式,而且都有一个共同的分母,为:K=(XT0-XT2)×(YT1-YT2)-(XT1-XT2)×(YT0-YT2)

    那么这六个参数分别为:              

                  A=[(XD0-XD2)×(YT1-YT2)-(XD1-XD2)×(YT0-YT2)] / K

                  B=[(XT0-XT2)×(XD1-XD2)-(XD0-XD2)×(XT1-XT2)] / K

                  C=[YT0×(XT2×XD1-XT1×XD2)+YT1×(XT0×XD2-XT2×XD0)+YT2×(XT1×XD0-XT0×XD1)] / K

                  D=[(YD0-YD2)×(YT1-YT2)-(YD1-YD2)×(YT0-YT2)] / K

                  E=[(XT0-XT2)×(YD1-YD2)-(YD0-YD2)×(XT1-XT2)] / K

                  F=[YT0×(XT2×YD1-XT1×YD2)+YT1×(XT0×YD2-XT2×YD0)+YT2×(XT1×YD0-XT0×YD1)] / K

    计算A、B、C、D、E、F的值 :

    void TSCal(void)
    {
        int i=0;
        int xt[3],yt[3];
        Lcd_ClearScr(0xFFFF);
        drawCross(32,24,0xFF0000);
        drawCross(160,216,0xFF0000);
        drawCross(288,120,0xFF0000);
        //依次读取三个采样点的坐标值
        for(i=0;i<3;i++)
        {     
            while(flagTS==0);
            xt[i]=xdata;
            yt[i]=ydata;
            Uart_Printf("xdata=%d
    ",xdata);
            Uart_Printf("ydata=%d
    ",ydata);
            flagTS=0;              
        }
        //计算参数
        K=(xt[0]-xt[2])*(yt[1]-yt[2])-(xt[1]-xt[2])*(yt[0]-yt[2]);
        A=(32-288)*(yt[1]-yt[2])-(160-288)*(yt[0]-yt[2]);
        B=(xt[0]-xt[2])*(160-288)-(32-288)*(xt[1]-xt[2]);
        C=yt[0]*(xt[2]*160-xt[1]*288)+yt[1]*(xt[0]*288-xt[2]*32)+yt[2]*(xt[1]*32-xt[0]*160);
        D=(24-120)*(yt[1]-yt[2])-(216-120)*(yt[0]-yt[2]);
        E=(xt[0]-xt[2])*(216-120)-(24-120)*(xt[1]-xt[2]);
        F=yt[0]*(xt[2]*216-xt[1]*120)+yt[1]*(xt[0]*120-xt[2]*24)+yt[2]*(xt[1]*24-xt[0]*216);
    }

    将计算出来的A、B、C、D、E、F的值存入EEPROM,0x1f地址存放是否存储过的标志位。读取0x1f地址的值赋予iic_buffer[0],如果iic_buffer[0]不等于0x55,证明数据没有存储到EEPROM,则计算A、B、C、D、E、F的值,并写入EEPROM,如果等于0x55证明数据已经写入EEPROM,直接读取即可,这样就不用每次都校验触摸屏了。

    void CalcuateTouch(void)
    {
        flagTS = 0;
        Rd24C080(0xa0,0x1f,&(iic_buffer[0]));
        if(iic_buffer[0]!=0x55)
        {
            TSCal();
            Wr24C080(0xa0,0x1f,0x55);
            iic_writekey(0xa0,0x20,A);
            iic_writekey(0xa0,0x30,B);
            iic_writekey(0xa0,0x40,C);
            iic_writekey(0xa0,0x50,D);
            iic_writekey(0xa0,0x60,E);
            iic_writekey(0xa0,0x70,F);
            iic_writekey(0xa0,0x80,K);        
        }
        else
        {
            A = iic_readkey(0xa0,0x20);
            B = iic_readkey(0xa0,0x30);
            C = iic_readkey(0xa0,0x40);
            D = iic_readkey(0xa0,0x50);
            E = iic_readkey(0xa0,0x60);
            F = iic_readkey(0xa0,0x70);
            K = iic_readkey(0xa0,0x80);
        }
        Lcd_ClearScr(0xFFFF);        
    }

    这时A、B、C、D、E、F的值都已经计算出来,将触摸屏ADC值带入公式就可以得到LCD上的物理位置。

  • 相关阅读:
    隐式类型转换
    STL::allocator rebind
    Proxy Class(代理类)
    C++ 没有合适的默认构造函数(无参数构造函数)
    E
    C
    Multiplication Puzzle POJ
    Brackets POJ
    Halloween Costumes LightOJ
    ACwing 139. 回文子串的最大长度(二分+Hash)
  • 原文地址:https://www.cnblogs.com/zpehome/p/3420334.html
Copyright © 2020-2023  润新知