Board logo

标题: S3C2440-按键 [打印本页]

作者: 我是MT    时间: 2014-3-22 09:07     标题: S3C2440-按键

使用按键控制跑马灯。扫描哪个按键被按下有两种方式。一个是查询扫描,一个是中断扫描。查询扫描就是不断轮询哪个引脚变成低电平了。中断扫描主要通过中断方式实现。



查询扫描程序:

#define rGPFCON (*(volatile unsigned *)0x56000050)
#define rGPFDAT (*(volatile unsigned *)0x56000054)
#define rGPFUP (*(volatile unsigned *)0x56000058)
#define rGPBCON (*(volatile unsigned *)0x56000010)
#define rGPBDAT (*(volatile unsigned *)0x56000014)
#define rGPBUP (*(volatile unsigned *)0x56000018)  
int KeyMain(){
        void Delay(unsigned int x);
        unsigned char ledtab[]={0xf7,0xef,0xdf,0xbf};
        unsigned int t;
        rGPBCON = 0xffc3fc;             //0,2 为输入,3,4,5,6为输出
        rGPBDAT = 0x7fe;               
        rGPFCON = 0xd54c;               //5,6为输入
        rGPFDAT = 0xff;                  
        rGPBUP &= 0xf9f;
        rGPFUP &= 0x82;


        while(1){
                while(((rGPBDAT & 0x7ff) == 0x7fe) && ((rGPFDAT & 0xff) == 0xff));    //不断轮询,如果找到往下执行,看是那个被按下
                if((rGPBDAT & (0x1<<5)) == 0){               
                        rGPFDAT = ledtab[0];         
                        Delay(70);
                }
                if((rGPBDAT & (0x1<<6)) == 0){                          //取出rGPBDAT的第6位,看是不是0
                        rGPFDAT = ledtab[1];
                        Delay(70);
                }
                if((rGPFDAT & (0x1<<0)) == 0){
                        rGPFDAT = ledtab[2];
                        Delay(70);
                }
                if((rGPFDAT & (0x1<<2)) == 0){
                        rGPFDAT = ledtab[3];
                        Delay(70);
                }
                rGPFDAT = 0xff;                                       //恢复,以便重新响应按键
        }
}
void Delay(unsigned int x){
        unsigned int i, j, k;
        for(i =0; i <= x; i++)
                for(j = 0; j <= 0xff; j++)
                        for(k = 0; k <= 0xff; k++)
                                ;
}

中断扫描程序:

#define rGPFCON (*(volatile unsigned *)0x56000050)   
#define rGPFDAT (*(volatile unsigned *)0x56000054)   
#define rGPFUP (*(volatile unsigned *)0x56000058)  
#define SRCPND (*(volatile unsigned *)0x4a000000)
#define INTPND (*(volatile unsigned *)0x4a000010)
#define INTMSK (*(volatile unsigned *)0x4a000008)
#define _ISR_STARTADDRESS 0x33ffff00
#define pISR_EINT0 (*(unsigned *)(_ISR_STARTADDRESS+0x20))
#define pISR_EINT2 (*(unsigned *)(_ISR_STARTADDRESS+0x28))
#define U32 unsigned int

void delay(U32 x){
        int i,j,k;
        for(i = 0; i < x; i++)
                for(j = 0; j < 0xff; j++)
                        for(k = 0; k < 0xff; k++)
                                ;
}

void __irq EINT0_ISR(void){
        SRCPND |= 1;                 //SRCPND 通过写入数据清零,如果不清零,会反复进行请求
        INTPND |= 1;                 //INDPND 通过置1清零
        rGPFDAT = 0xf7;
        delay(1000);
        rGPFDAT = 0xff;
        delay(1000);
}

void __irq EINT2_ISR(void){     //使用__irq这个关键字定义终端服务例程,这样系统会自动为我们保留一些变量,并能在中断处理完后正确的返回
        SRCPND |= 1<<2;
        INTPND |= 1<<2;
        rGPFDAT = 0xef;
        delay(1000);
        rGPFDAT = 0xff;
        delay(1000);
}

int Main(){   
        rGPFCON &= 0xfc0c;    //0 2 3 4
        rGPFCON |= (1<<1)|(1<<5)|(1<<6)|(1<<8);
        rGPFUP = 0xe2;
        SRCPND |= (1<<0)|(1<<2);
        INTPND |= (1<<0)|(1<<2);
        INTMSK &= ("(0x1<<0)) & ("(0x1<<2));     //开中断
        pISR_EINT0 = (U32)EINT0_ISR;             //给中断服务例程入口地址
        pISR_EINT2 = (U32)EINT2_ISR;
        while(1);
        return 0;
}

李万鹏




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0