S3C2440-按键
哈尔滨理工大学软件工程专业08-7李万鹏原创作品,转载请标明出处
http://blog.csdn.net/woshixingaaa/archive/2010/12/14/6075129.aspx
使用按键控制跑马灯。扫描哪个按键被按下有两种方式。一个是查询扫描,一个是中断扫描。查询扫描就是不断轮询哪个引脚变成低电平了。中断扫描主要通过中断方式实现。
查询扫描程序:
#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; }