zoukankan      html  css  js  c++  java
  • 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上的物理位置。

  • 相关阅读:
    泛微云桥e-Bridge 目录遍历,任意文件读取
    (CVE-2020-8209)XenMobile-控制台存在任意文件读取漏洞
    selenium 使用初
    将HTML文件转换为MD文件
    Python对word文档进行操作
    使用java安装jar包出错,提示不是有效的JDK java主目录
    Windows server 2012安装VM tools异常解决办法
    ifconfig 命令,改变主机名,改DNS hosts、关闭selinux firewalld netfilter 、防火墙iptables规则
    iostat iotop 查看硬盘的读写、 free 查看内存的命令 、netstat 命令查看网络、tcpdump 命令
    使用w uptime vmstat top sar nload 等命令查看系统负载
  • 原文地址:https://www.cnblogs.com/zpehome/p/3420334.html
Copyright © 2011-2022 走看看