mini2440裸机编程--------触摸屏驱动

来源:互联网 发布:java中%是什么意思 编辑:程序博客网 时间:2024/05/17 05:11

       mini2440上连接的是一个电阻式触摸屏,电阻式触摸屏是基于AD转换实现的,即某个位置按下之后,这点的电压会发生改变,通过电压就可以判断出是哪一个点被按下了,arm可以得到这个点的坐标。因为触摸屏和lcd是两个设备,因此,触摸屏得到的坐标一般不能够与lcd上的坐标对应起来,所以需要我们在程序中手动的进行校正(虽然不对应,但是他们之间的关系式线性的,因此通过三个点的采样,就可以把系数确定下来。)

      s3c2440是不支持中断嵌套的。

      arm与触摸屏通过tsxp\tsxm  tsyp\tsym 四根线相连接,数据手册中有一句话:When Touch Screen device is used; XM or PM is only connected ground for Touch Screen I/F.s3c2440一共有4种触摸屏接口模式,其中,自动(连续)XY坐标转换模式和等待中断模式是我们用到的。

(1)等待中断模式是在触笔落下时产生一个中断,在这种模式下,A/D触摸屏控制寄存器ADCTSC的值应为0xD3,在系统响应中断后,XY坐标的测量模式必须为无操作模式,即寄存器ADCTSC的低两位必须清零。

(2)自动(连续)XY坐标转换模式是系统依次转换触点的X轴坐标和Y轴坐标,其中X轴坐标值写入寄存器ADCDAT0的低10位中,Y轴坐标写入寄存器ADCDAT1的低10位中,在这种模式下,系统同样会产生中断信号。

在一般情况下,为实现触摸屏功能,先是设置为等待中断模式,在产生int_tc中断后,在中断函数中再设置为自动(连续)XY坐标转换模式,依次读取触点的坐标值。

    与触摸屏的功能实现相关的有两个中断:int_adc和int_tc,这两个中断源属于subinterrupt source,都属于int_adc,因此在配置中断的时候就需要按照sub中断源的配置方法进行配置。其中,int_tc是在触摸屏被按下或被释放时产生,一个时刻只能检测其中一种事件,具体是检测触摸屏按下还是释放,需要我们在寄存器ADCTSC的第8位能够设置。int_adc是在ad转换完成之后产生的。

寄存器ADCTSC的第3位可以选择上拉电阻的使能,在等待中断模式下,上拉电阻要有效,在触发中断后,上拉电阻要无效。寄存器ADCTSC的第2位用于选择自动(连续)XY坐标转换模式。触笔抬起/落下中断状态寄存器ADCUPDN的低2位能够判断触笔在何种状态下引起的中断。A/D延时寄存器ADCDLY可以设置开始中断到真正开始A/D转换这段时间的延时长度,它的时钟源频率为3.68MHz

实现触摸屏功能的流程是这样的:

1. 设置触摸屏为等待中断模式,配置ADCTSC为检测触摸屏被按下 产生中断。

2. 产生中断后,证明触摸屏被按下。在中断函数中修改ADCTSC和ADCCON,配置触摸屏为连续转换功能。同时要屏蔽int_adc中断。因为我们是在中断函数中,所以,通过while循环检测srcpnd 和 subsrcpnd寄存器来检测是否产生了adc转换完成的中断。也就是屏蔽中断,但是通过检测是否产生中断,来判断adc转换是否完成。

3. adc转换结束后,提取想要的数据。然后配置ADCSTC为检测触摸屏被释放产生中断,同时也要继续屏蔽中断。通过检测srcpnd和subsrcpnd来判断是否产生了触摸屏被释放的中断。当检测到触摸屏被释放后,结束中断函数。

当然,采用其他方法来实现我觉也是可以的,比如说检测到触摸屏被按下后,就结束中断函数。也就是把上面的三个步骤,分别在三个中断函数中实现,也是可行的。


此外,涉及到触摸屏的校正,转载赵老师的方法如下:

比较常见的校正方法是三点校正法,它的原理是:

       设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

具体操作,就是先在lcd上显示三个点,然后等用于点击这三个点之后,采集这三个点的实际坐标和理论坐标,这样就可以计算得到上面的参数。


下面附上我的代码。

static void __irq touchscreen_irq(void){   int xdata, ydata;   rADCTSC = (1<<3)|(1<<2);         //上拉电阻无效,自动连续XY坐标转换模式开启       rADCDLY = 40000;                    //延时             rADCCON|=0x1;                 //开始A/D转换        while(rADCCON & 0x1);               //检查A/D转换是否开始       while(!(rADCCON & 0x8000));        //等待A/D转换的结束                    while(!(rSRCPND & (BIT_ADC))) ;     //判断A/D中断的悬挂位        xdata=(rADCDAT0&0x3ff);                //读取X轴坐标   ydata=(rADCDAT1&0x3ff);                //读取Y轴坐标   uart_printf("xdata = %x,  ydata = %x adcdata0 = %x ", xdata, ydata, rADCDAT0);          rSUBSRCPND|=BIT_SUB_TC;   ClearPending(BIT_ADC);                            rADCTSC =0xd3;               //再次设置等待中断模式,这一次是判断触笔的抬起       rADCTSC = rADCTSC|(1<<8);      //设置触笔抬起中断        while(1)         //等待触笔的抬起       {              if(rSUBSRCPND & (0x1<<9))     //检查A/D触摸屏中断悬挂              {                     break;                   //如果触笔抬起,则跳出该循环              }       }        uart_printf("adcdata0 = %x ", rADCDAT0);rSUBSRCPND = 1<<9;ClearPending(BIT_ADC); uart_printf("irq finish\r\n");rADCTSC=0xd3;  // important here}void touchscreen_init(void){rADCDLY=50000;               //设置延时    rADCCON=(1<<14)+(9<<6);              //设置A/D预分频     rADCTSC=0xd3;                 //设置触摸屏为等待中断模式。     pISR_ADC = (U32)touchscreen_irq;rINTSUBMSK &= ~(BIT_SUB_TC);rSUBSRCPND = 1<<9;ClearPending(BIT_ADC);EnableIrq(BIT_ADC);}void touchscreen_test(void) {   touchscreen_init();}




原创粉丝点击