zoukankan      html  css  js  c++  java
  • 2440裸机编程之 触摸屏

     

    摸屏由于其体积小、轻便和接口简单的特点,成为一种在嵌入式系统中应用广泛的输

    入设备。本实例首先介绍四线电阻式触摸屏的结构和工作原理,然后介绍S3C2440A 通过内
    部集成的触摸屏控制寄存器的设置,来完成对触摸屏触摸位置坐标的读取。


    典型触摸屏的工作组件一般由3 部分组成。两层透明的阻性导体层、两层
    导体之间的隔离层和电极。阻性导体层选用阻性材料,如将铟锡氧化物(1TO)涂在衬底上构
    成,或者上层衬底用塑料,下层衬底用玻璃。隔离层为粘性绝缘液体材料,如聚脂薄膜。电
    极选用导电性能极好的材料(如银粉墨)构成,其导电性能大约为ITO 的1 000 倍。






    工作原理:见下图
    1.获取X坐标:X+和X-加上正负电压,X方向就会形成电势梯度网络;Y-接高阻,Y+接输入,一旦屏幕上某点被按下,绝缘液体被排开,上下两个导体层在此点导通,Y+获取此点在X方向上的电势,即此点的X坐标,通过ADC转换成数字量输入给系统。
    同理
    1.获取Y坐标:Y+和Y-加上正负电压,Y方向就会形成电势梯度网络;X-接高阻,X+接输入,一旦屏幕上某点被按下,绝缘液体被排开,上下两个导体层在此点导通,X+获取此点在Y方向上的电势,即此点的Y坐标,通过ADC转换成数字量输入给系统。
    这样,通过ADC转换成数字量输入给系统。





    这里做个试验,笔尖接触 触摸屏,然后串口打印坐标值。
    注意X测量时,依据上述原理,XP接参考电平,XM接地,YP接ADC通道5,YM接高阻,上拉功能取消,这些都在寄存器中设置ADCTSC。
    同理,Y测量时,YP接参考电平,YM接地,XP接ADC通道7,XM接高阻,上拉功能取消.
    其他用到的是ADC相关的寄存器。
    //********************************************************************

    #define adc_frequency 2000000

    U16 x_tsc,y_tsc;

    void Main(void)
    {
    int i;
    ……硬件初始化……

    Uart_Printf("\n触摸屏中断+坐标提取实验\n");

    tsc_int_init(); //触摸屏中断初始化
    tsc_init(); //触摸屏初始化
    while(1);

    }

    void tsc_int_init(void) //触摸屏中断初始化
    {
    rSUBSRCPND |= 1<<9; //INT_TC清0

    rSRCPND |= 1<<31; //INT_ADC清0
    rINTPND |= 1<<31; //INT_ADC清0

    pISR_ADC = (U32)TSC_ISR; //申请中断向量

    rINTMSK = rINTMSK & ~(1<<31); //禁止ADC的屏蔽

    rINTSUBMSK = rINTSUBMSK & ~(1<<9); //禁止TSC的屏蔽

    rADCTSC = 0x0d3 ; //等待中断模式的特定设置
    }


    void TSC_ISR(void) __irq //触摸屏中断例程
    {
    rINTMSK |= 1<<31; //ADC中断的屏蔽
    rINTSUBMSK |= 1<<9 | 1<<10; //TSC和ADC_S中断屏蔽

    tsc_get(); //得到触点坐标
    Uart_Printf("x=%d,y=%d\n",x_tsc,y_tsc);

    rSUBSRCPND |= 1<<9; //INT_TC清0
    rSRCPND |= 1<<31; //INT_ADC清0
    rINTPND |= 1<<31; //INT_ADC清0

    rINTMSK = rINTMSK & ~(1<<31); //禁止ADC的屏蔽
    rINTSUBMSK = rINTSUBMSK & ~(1<<9); //禁止TSC的屏蔽
    rINTSUBMSK = rINTSUBMSK & ~(1<<10); //禁止ADC_S的屏蔽

    }


    void tsc_init(void) //触摸屏初始化
    {
    rADCDLY= 0x5000;//必须要延时
    rADCCON = (PCLK/adc_frequency - 1)<<6 | 1<<14 ; //设置ADC频率,预分频有效
    }

    void tsc_get(void)
    {
    rADCCON = rADCCON & ~(7<<3) | 7<<3 ; //选择XP通道
    rADCTSC = (0<<7)|(1<<6)|(1<<5)|(0<<4)|(1<<3)|(0<<2)|1 ; //X测量模式:YM=Z, YP=AIN[5] ,XM=GND, XP=V, PULL_UP=DISABLE, NORMAL, X-position (ENABLE=GND/V)
    rADCCON|=0x1; //启动ADC
    while(rADCCON & 0x1); //等待启动
    while(!(rADCCON & 0x8000)); //等待是否转换完毕
    x_tsc = rADCDAT0&0x3FF; //得到转换结果

    rADCCON = rADCCON & ~(7<<3) | 5<<3 ; //选择YP通道
    rADCTSC = (1<<7)|(0<<6)|(0<<5)|(1<<4)|(1<<3)|(0<<2)|2 ; //Y测量模式:YM=GND, YP=V ,XM=Z, XP=AIN[7], PULL_UP=DISENBLE, NORMAL, Y-position (DISABLE=AIN/Z)
    rADCCON|=0x1; //启动ADC
    while(rADCCON & 0x1); //等待启动
    while(!(rADCCON & 0x8000)); //等待是否转换完毕
    y_tsc = rADCDAT1&0x3FF; //得到转换结果

    tsc_int_init(); //触摸屏中断初始化
    Delay(10);
    while(!((rADCDAT0 & 0X8000) & (rADCDAT1 & 0X8000) ));//等待笔尖抬起
    }


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

    结果如图:






    下面做个LCD和触摸屏TSC结合的实验,每当触摸屏某点被按下,在LCD的此点显示一个小正方形。
    注意LCD的XY坐标与TSC的XY坐标不一样,需要转化,我研究了一下之间的关系,不是太精准,仅供参考:(x_lcd, y_lcd) = ( 1.0084*y_tsc - 150,-0.82*x_tsc +600,12345)。
    //********************************************************************

    #define adc_frequency 2000000



    #define CLKVAL (6) //VCLK=HCLK÷[(CLKVAL+1)×2]
    #define PNRMODE (3) //TFT LCD panel
    #define BPPMODE (12) //16 bpp for TFT
    #define ENVID (1) //输出和控制 有效

    #define VBPD (29) //垂直同步信号后肩
    #define LINEVAL (480) //垂直尺寸
    #define VFPD (13) //垂直同步信号前肩
    #define VSPW (3) //垂直同步信号脉宽

    #define HBPD (40) //水平同步信号后肩
    #define HOZVAL (800) //水平尺寸
    #define HFPD (40) //水平同步信号前肩

    #define HSPW (48) //水平同步信号脉宽

    #define FRM565 (1) //565格式
    #define PWREN (1) //GPG供电使能(用于掉电模式)
    #define BSWP (0) //字节不交换:
    //#define HWSWP (1) //半字交换 16位用不到


    #define OFFSIZE (0) //若不用虚拟屏幕,则为0
    #define PAGEWIDTH (HOZVAL)//虚拟屏幕的宽 单位半字 若不用虚拟屏幕,则和实际一致

    U16 x_tsc,y_tsc;


    void Main(void)
    {
    int i;
    ……硬件初始化……

    Uart_Printf("\n触摸屏和LCD综合实验\n\n");
    Uart_Printf(" 触摸处将显一个方块\n\n");

    tsc_int_init(); //触摸屏中断初始化
    tsc_init(); //触摸屏初始化
    lcd_init(); //LCD初始化

    //test();

    while(1);

    }

    void test(void)
    {
    int i;
    for(i=50;i<480;i+=50)
    zhengfangxing(400,i,3000);

    }

    void tsc_int_init(void) //触摸屏中断初始化
    {
    rSUBSRCPND |= 1<<9; //INT_TC清0

    rSRCPND |= 1<<31; //INT_ADC清0
    rINTPND |= 1<<31; //INT_ADC清0

    pISR_ADC = (U32)TSC_ISR; //申请中断向量

    rINTMSK = rINTMSK & ~(1<<31); //禁止ADC的屏蔽

    rINTSUBMSK = rINTSUBMSK & ~(1<<9); //禁止TSC的屏蔽

    rADCTSC = 0x0d3 ; //等待中断模式的特定设置
    }


    void TSC_ISR(void) __irq //触摸屏中断例程
    {
    rINTMSK |= 1<<31; //ADC中断的屏蔽
    rINTSUBMSK |= 1<<9 | 1<<10; //TSC和ADC_S中断屏蔽

    tsc_get(); //得到触点坐标
    Uart_Printf("x=%d,y=%d\n",x_tsc,y_tsc);

    zhengfangxing( 1.0084*y_tsc - 150,-0.82*x_tsc +600,12345);//实验获得转换关系,精度有待提高

    rSUBSRCPND |= 1<<9; //INT_TC清0
    rSRCPND |= 1<<31; //INT_ADC清0
    rINTPND |= 1<<31; //INT_ADC清0

    rINTMSK = rINTMSK & ~(1<<31); //禁止ADC的屏蔽
    rINTSUBMSK = rINTSUBMSK & ~(1<<9); //禁止TSC的屏蔽
    rINTSUBMSK = rINTSUBMSK & ~(1<<10); //禁止ADC_S的屏蔽

    }


    void tsc_init(void) //触摸屏初始化
    {
    rADCDLY= 0x5000;//必须要延时
    rADCCON = (PCLK/adc_frequency - 1)<<6 | 1<<14 ; //设置ADC频率,预分频有效
    }

    void tsc_get(void)
    {
    rADCCON = rADCCON & ~(7<<3) | 7<<3 ; //选择XP通道
    rADCTSC = (0<<7)|(1<<6)|(1<<5)|(0<<4)|(1<<3)|(0<<2)|1 ; //X测量模式:YM=Z, YP=AIN[5] ,XM=GND, XP=V, PULL_UP=DISABLE, NORMAL, X-position (ENABLE=GND/V)
    rADCCON|=0x1; //启动ADC
    while(rADCCON & 0x1); //等待启动
    while(!(rADCCON & 0x8000)); //等待是否转换完毕
    x_tsc = rADCDAT0&0x3FF; //得到转换结果

    rADCCON = rADCCON & ~(7<<3) | 5<<3 ; //选择YP通道
    rADCTSC = (1<<7)|(0<<6)|(0<<5)|(1<<4)|(1<<3)|(0<<2)|2 ; //Y测量模式:YM=GND, YP=V ,XM=Z, XP=AIN[7], PULL_UP=DISENBLE, NORMAL, Y-position (DISABLE=AIN/Z)
    rADCCON|=0x1; //启动ADC
    while(rADCCON & 0x1); //等待启动
    while(!(rADCCON & 0x8000)); //等待是否转换完毕
    y_tsc = rADCDAT1&0x3FF; //得到转换结果

    tsc_int_init(); //触摸屏中断初始化
    Delay(10);
    while(!((rADCDAT0 & 0X8000) & (rADCDAT1 & 0X8000) ));//等待笔尖抬起
    }

    void lcd_init(void)
    {
    rGPCCON = 0xAAAAAAAA; //LCD功能
    rGPDCON = 0xAAAAAAAA; //LCD功能
    rGPGCON = rGPGCON & ~(3<<8) | 3<<8 ; //LCD电源功能

    rLCDCON1 = rLCDCON1 & ~(0x3ff<<8) | CLKVAL<<8 ; //LCD频率
    rLCDCON1 = rLCDCON1 & ~(0x3<<5) | PNRMODE<<5 ; //显示模式
    rLCDCON1 = rLCDCON1 & ~(0xf<<1) | BPPMODE<<1 ; //BPP模式(每个像素用几位表示)
    rLCDCON1 = rLCDCON1 & ~(1) | 0 ; //关闭输出

    rLCDCON2 = rLCDCON2 & ~(0xff<<24) | VBPD<<24 ; //与LCD属性一致
    rLCDCON2 = rLCDCON2 & ~(0x3ff<<14) | (LINEVAL-1)<<14 ; //垂直尺寸
    rLCDCON2 = rLCDCON2 & ~(0xff<<6) | VFPD<<6 ; //与LCD属性一致
    rLCDCON2 = rLCDCON2 & ~(0x3f) | VSPW ; //与LCD属性一致

    rLCDCON3 = rLCDCON3 & ~(0x7f<<19) | HBPD<<19 ; //与LCD属性一致
    rLCDCON3 = rLCDCON3 & ~(0x7ff<<8) | (HOZVAL-1)<<8 ; //水平尺寸
    rLCDCON3 = rLCDCON3 & ~(0xff) | HFPD ; //与LCD属性一致

    rLCDCON4 = rLCDCON4 & ~(0xff) | HSPW ; //与LCD属性一致

    rLCDCON5 = rLCDCON5 & ~(1<<11) | FRM565<<11 ; //模式:565或5551
    rLCDCON5 = rLCDCON5 & ~(1<<3) | PWREN<<3 ; //供电引脚使能 ( GPG4 )
    rLCDCON5 = rLCDCON5 & ~(1<<1) | BSWP ; //字节是否交换


    rLCDSADDR1 = rLCDSADDR1 & ~(0x1ff<<21) | ( ( (U32)pixel>>22 )&0x1ff )<<21 ; //缓存区首地址高位[30:22]->rLCDSADDR1[29:21]
    rLCDSADDR1 = rLCDSADDR1 & ~(0x1fffff) | ( (U32)pixel>>1 )&0x1fffff ; //缓存区首地址低位[21:1]->rLCDSADDR1[20:0]

    rLCDSADDR2 = rLCDSADDR2 & ~(0x1fffff) | ( ((U32)pixel+LINEVAL*HOZVAL*2)>>1 )&0x1fffff ; //缓存区(尾地址+1)低位[21:1]->rLCDSADDR2[20:0]

    rLCDSADDR3 = rLCDSADDR3 & ~(0x7ff<<11) | OFFSIZE<<11 ; //虚拟屏幕偏移长度
    rLCDSADDR3 = rLCDSADDR3 & ~(0x7ff) | PAGEWIDTH ; //虚拟屏幕宽度

    rLCDCON1 = rLCDCON1 & ~(1) | ENVID ; //开启输出,这个要最后做,不然有问题
    }

    U8 make_pixel(U16 x,U16 y,U32 color)
    {
    if(x<HOZVAL && y<LINEVAL)
    {
    pixel[y][x] = color;
    return 1;
    }
    else return 0;
    }


    void rectangle(U16 x1,U16 x2,U16 y1,U16 y2,U32 color)
    {
    U16 x;
    for(;y1<=y2;y1++)
    for(x=x1;x<=x2;x++)
    make_pixel(x,y1,color);
    }

    void zhengfangxing(U16 x, U16 y,U32 color)
    {
    rectangle(x-10,x+10,y-10,y+10,color);
    }

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

    实验运行基本正常:

    博乐Bar
  • 相关阅读:
    DOSD用scratch的方式训练通用目标检测,性能很高
    caffemodel模型
    NetScope脱机(localhost)使用[转】
    class前置声明
    const函数
    CUDA开发
    caffe2学习
    faster rcnn讲解很细
    控制台输出覆盖当前行显示
    UA池 代理IP池 scrapy的下载中间件
  • 原文地址:https://www.cnblogs.com/huanzxj/p/2853509.html
Copyright © 2011-2022 走看看