s3c2440之ADC 触摸屏操作

原理:

8通道的AD输入,转换为10位的二进制数据。在2.5MHZ的最大A/D转换时钟下,可以达到500KSPS。

2440的XP XM YP YM直接和触摸屏直接相连。ADC和触摸屏接口公用一个A/D转换器。

触摸屏接口模式:

1.     正常转换模式,就是普通的AD转换,通过读写ADCDAT0即可。

2.     分离的X/Y位置转换模式。X位置写往ADCDAT0,Y位置写往ADCDAT1。都会产生中断。

3.     连续的X/Y位置转换模式。触摸屏控制器连续转换X、Y位置。都写完后,产生一个中断。

ADC的操作规范:

ADC的启动包括手动操作和读结果时自动启动下一次转换。两种方法查询是否结束,查询状态位和转换结束时中断。

ADC编程步骤

1.     设置ADCCON,选择输入通道,设置AD转换时钟。

2.     设置ADCTSC,设为普通转换,不使用触摸屏。

3.     设置ADCCON启动AD转换,两种方式。

4.     转换结束时,读ADCDAT0获取结果。可以查询,也可以利用中断。

触摸屏操作规范:

XP YP要么作为模拟输入,要么接电源;XM YM要么接地,要么高阻。

1.     设置等待中断模式,设置ADCSTC寄存器即可,此时还需要设置第8位表明是pen down还是pen up中断。

2.     中断产生后,就会进入转换阶段,转换又分为X/Y分别转换和X/Y连续转换模式,在等待模式中上拉电阻有效,在触发中断后,上拉电阻无效。

可以为X.Y分别转换,设置ADCSTC=0x69 0x9a即可,X转换完会进入ADC中断,Y转换完也会进入ADC中断。

也可以设置连续的X.Y转换。此时ADCSTC的低2位设置为00,3位设置为AUTO_PST。


程序:


int main(void)
{	

	char ch;

	init_uart0();
    
    while (1)
    {
        printf("\r\n##### Test ADC and Touch Screem #####\r\n");
        printf("[A] Test ADC\n\r");
        printf("[T] Test Touch Screem\n\r");
        printf("Enter your selection: ");

        putchar((ch = getchar()));
        
        switch (ch)
        {
            case 'a':
            case 'A':
            {
                Test_Adc();
                break;
            }
            
            case 't':
            case 'T':
            {
                Test_Ts();
                break;
            }

            default: 
                break;
        }
    }  
}





// ADCCON
#define PRESCALE_DIS        (0 << 14)
#define PRESCALE_EN         (1 << 14)
#define PRSCVL(x)           ((x) << 6)
#define ADC_INPUT(x)        ((x) << 3)
#define ADC_START           (1 << 0)
#define ADC_ENDCVT          (1 << 15)

// ADCTSC
#define UD_SEN          (1 << 8)
#define DOWN_INT        (UD_SEN*0)
#define UP_INT          (UD_SEN*1)
#define YM_SEN          (1 << 7)
#define YM_HIZ          (YM_SEN*0)
#define YM_GND          (YM_SEN*1)
#define YP_SEN          (1 << 6)
#define YP_EXTVLT       (YP_SEN*0)
#define YP_AIN          (YP_SEN*1)
#define XM_SEN          (1 << 5)
#define XM_HIZ          (XM_SEN*0)
#define XM_GND          (XM_SEN*1)
#define XP_SEN          (1 << 4)
#define XP_EXTVLT       (XP_SEN*0)
#define XP_AIN          (XP_SEN*1)
#define XP_PULL_UP      (1 << 3)
#define XP_PULL_UP_EN   (XP_PULL_UP*0)
#define XP_PULL_UP_DIS  (XP_PULL_UP*1)
#define AUTO_PST        (1 << 2)
#define CONVERT_MAN     (AUTO_PST*0)
#define CONVERT_AUTO    (AUTO_PST*1)
#define XP_PST(x)       (x << 0)

#define NOP_MODE        0
#define X_AXIS_MODE     1
#define Y_AXIS_MODE     2
#define WAIT_INT_MODE   3


/* ÉèÖýøÈëµÈ´ýÖжÏģʽ£¬XP_PU,XP_Dis,XM_Dis,YP_Dis,YM_En
   ¶ÔÓÚS3C2440£¬Î»[8]Ϊ0¡¢1ʱ·Ö±ð±íʾµÈ´ýPen DownÖжϻòPen UpÖжÏ
 */
/* ½øÈë"µÈ´ýÖжÏģʽ"£¬µÈ´ý´¥ÃþÆÁ±»°´Ï */
#define wait_down_int() { rADCTSC = DOWN_INT | XP_PULL_UP_EN | \
                          XP_AIN | XM_HIZ | YP_AIN | YM_GND | \
                          XP_PST(WAIT_INT_MODE); }
/* ½øÈë"µÈ´ýÖжÏģʽ"£¬µÈ´ý´¥ÃþÆÁ±»ËÉ¿ª */
#define wait_up_int()   { rADCTSC = UP_INT | XP_PULL_UP_EN | XP_AIN | XM_HIZ | \
                          YP_AIN | YM_GND | XP_PST(WAIT_INT_MODE); }

/* ½øÈë×Ô¶¯(Á¬Ðø) X/YÖá×ø±êת»»Ä£Ê½ */
#define mode_auto_xy()  { rADCTSC = CONVERT_AUTO | XP_PULL_UP_DIS | XP_PST(NOP_MODE); }


/* 
 * ʹÓòéѯ·½Ê½¶ÁÈ¡A/Dת»»Öµ
 * ÊäÈë²ÎÊý£º
 *     ch: Ä£ÄâÐźÅͨµÀ£¬È¡ÖµÎª0~7
 */       
static int ReadAdc(int ch)
{
    // Ñ¡ÔñÄ£ÄâͨµÀ£¬Ê¹ÄÜÔ¤·ÖƵ¹¦ÄÜ£¬ÉèÖÃA/Dת»»Æ÷µÄʱÖÓ = PCLK/(49+1)
    rADCCON = PRESCALE_EN | PRSCVL(49) | ADC_INPUT(ch);

    // Çå³ýλ[2]£¬ÉèΪÆÕͨת»»Ä£Ê½
    rADCTSC &= ~(1<<2);

    // ÉèÖÃλ[0]Ϊ1£¬Æô¶¯A/Dת»»
    rADCCON |= ADC_START;

    // µ±A/Dת»»ÕæÕý¿ªÊ¼Ê±£¬Î»[0]»á×Ô¶¯Çå0
    while (rADCCON & ADC_START);

    // ¼ì²âλ[15]£¬µ±ËüΪ1ʱ±íʾת»»½áÊø
    while (!(rADCCON & ADC_ENDCVT));

    // ¶ÁÈ¡Êý¾Ý    
    return (rADCDAT0 & 0x3ff);
}

/* 
 * ²âÊÔADC
 * ͨ¹ýA/Dת»»£¬²âÁ¿¿É±äµç×èÆ÷µÄµçѹֵ
 */       
void Test_Adc(void)
{
    float vol;
    int t;

    printf("\r\nMeasuring the voltage of AIN2, press any key to exit\n\r");
    while (!awaitkey(0))    // ´®¿ÚÎÞÊäÈ룬Ôò²»¶Ï²âÊÔ
    {      
        vol = ((float)ReadAdc(1)*3.3)/1024.0;  // ¼ÆËãµçѹֵ
        t   = (vol - (int)vol) * 1000;   // ¼ÆËãСÊý²¿·Ö, ±¾´úÂëÖеÄprintfÎÞ·¨´òÓ¡¸¡µãÊý
        printf("AIN2 = %d.%-3dV\r\n", (int)vol, t);
    }
    printf("\r\n");
}

/* 
 * INT_TCµÄÖжϷþÎñ³ÌÐò
 * µ±´¥ÃþÆÁ±»°´ÏÂʱ£¬½øÈë×Ô¶¯(Á¬Ðø) X/YÖá×ø±êת»»Ä£Ê½£»
 * µ±´¥ÃþÆÁ±»ËÉ¿ªÊ±£¬½øÈëµÈ´ýÖжÏģʽ£¬ÔٴεȴýINT_TCÖжÏ
 */       
static void Isr_Tc(void)
{
    if (rADCDAT0 & 0x8000)
    {
        printf("Stylus Up!!\n\r");
        wait_down_int();    /* ½øÈë"µÈ´ýÖжÏģʽ"£¬µÈ´ý´¥ÃþÆÁ±»°´Ï */
    }
    else 
    {
        printf("Stylus Down: ");

        mode_auto_xy();     /* ½øÈë×Ô¶¯(Á¬Ðø) X/YÖá×ø±êת»»Ä£Ê½ */
    
        /* ÉèÖÃλ[0]Ϊ1£¬Æô¶¯A/Dת»»
         * ×¢Ò⣺ADCDLYΪ50000£¬PCLK = 50MHz£¬
         *       Òª¾­¹ý(1/50MHz)*50000=1msÖ®ºó²Å¿ªÊ¼×ª»»X×ø±ê
         *       ÔÙ¾­¹ý1msÖ®ºó²Å¿ªÊ¼×ª»»Y×ø±ê
         */
        rADCCON |= ADC_START;
    }
    
    // ÇåINT_TCÖжÏ
    rSUBSRCPND |= BIT_SUB_TC;
    rSRCPND    |= BIT_ADC;
    rINTPND    |= BIT_ADC;
}


/* 
 * INT_ADCµÄÖжϷþÎñ³ÌÐò
 * A/Dת»»½áÊøʱ·¢Éú´ËÖжÏ
 * ÏȶÁÈ¡X¡¢Y×ø±êÖµ£¬ÔÙ½øÈëµÈ´ýÖжÏģʽ
 */       
static void Isr_Adc(void)
{
    // ´òÓ¡X¡¢Y×ø±êÖµ    
    printf("xdata = %4d, ydata = %4d\r\n", (int)(rADCDAT0 & 0x3ff), (int)(rADCDAT1 & 0x3ff));

	wait_up_int();      /* ½øÈë"µÈ´ýÖжÏģʽ"£¬µÈ´ý´¥ÃþÆÁ±»ËÉ¿ª */


    // ÇåINT_ADCÖжÏ
    rSUBSRCPND |= BIT_SUB_ADC;
    rSRCPND    |= BIT_ADC;
    rINTPND    |= BIT_ADC;
}

/* 
 * ADC¡¢´¥ÃþÆÁµÄÖжϷþÎñ³ÌÐò
 * ¶ÔÓÚINT_TC¡¢INT_ADCÖжϣ¬·Ö±ðµ÷ÓÃËüÃǵĴ¦Àí³ÌÐò
 */       
void __irq AdcTsIntHandle(void)
{
    if (rSUBSRCPND & BIT_SUB_TC)
        Isr_Tc();

    if (rSUBSRCPND & BIT_SUB_ADC)
        Isr_Adc();
}

/* 
 * ²âÊÔ´¥ÃþÆÁ£¬´òÓ¡´¥µã×ø±ê
 */       
void Test_Ts(void)
{
    pHandleADC = AdcTsIntHandle;    // ÉèÖÃADCÖжϷþÎñ³ÌÐò
    rINTMSK &= ~BIT_ADC;          // ¿ªÆôADC×ÜÖжÏ
    rINTSUBMSK &= ~(BIT_SUB_TC);  // ¿ªÆôINT_TCÖжϣ¬¼´´¥ÃþÆÁ±»°´Ï»òËÉ¿ªÊ±²úÉúÖжÏ
    rINTSUBMSK &= ~(BIT_SUB_ADC); // ¿ªÆôINT_ADCÖжϣ¬¼´A/Dת»»½áÊøʱ²úÉúÖжÏ
    
    // ʹÄÜÔ¤·ÖƵ¹¦ÄÜ£¬ÉèÖÃA/Dת»»Æ÷µÄʱÖÓ = PCLK/(49+1)
    rADCCON = PRESCALE_EN | PRSCVL(49);

    /* ²ÉÑùÑÓʱʱ¼ä = (1/3.6864M)*50000 = 13.56ms
     * ¼´°´Ï´¥ÃþÆÁºó£¬ÔÙ¹ý13.56ms²Å²ÉÑù
     */
    rADCDLY = 50000;

    wait_down_int();    /* ½øÈë"µÈ´ýÖжÏģʽ"£¬µÈ´ý´¥ÃþÆÁ±»°´Ï */

    printf("\r\nTouch the screem to test, press any key to exit\n\r");    
    getchar();

    // ÆÁ±ÎADCÖжÏ
    rINTSUBMSK |= BIT_SUB_TC;
    rINTSUBMSK |= BIT_SUB_ADC;
    rINTMSK |= BIT_ADC;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值