按键有两种方式:查询和中断
按键查询操作
一、首先在电路图中找到按键SW1、SW2、SW3 和 SW4,分别对应相应的信号口为 EINT0、EINT2、EINT11、EINT19,在核心板电路图上找到相应的端口 GPF0,GPF2,GPG3 和 GPG11,接下来需要进行配置的寄存器是 GPFCON、GPFUP、GPGCON、GPGUP,因为使用按键查询操作,所以设置为 Input
二、按键的查询操作类似于LED灯的操作,当你按下哪个按键时,就可以将按键值赋给它,以便查询后面的操作
三、按键查询的去抖动和去重复的操作
按键中断操作
一、找到 I/O控制寄存器对其进行相应的设置,设置为特定功能 EINT[0]、EINT[2]、EINT[11]、EINT[19]
二、配置EXTINT0寄存器,设置中断的触发方式时选择下降沿触发,这样能够保证按键及时准确
三、按键3和按键4共享一个中断源,所以外部中断屏蔽和挂起也需要进行相应的设置,即EINTMASK和EINTPEND要进行配置
四、按键1~4 要进行屏蔽、源挂起和中断挂起的操作,配置寄存器 INTMSK、SRCPND、INTPND
五、将中断处理函数的函数名加载到内存地址当中,以便CPU自动执行中断处理函数
中断处理函数注意点:
1、必须要有 __irq 关键字
2、函数不能带有参数
3、必须用 static 关键字声明函数
4、不要进行过于复杂的运算和打印输出
5、不能有返回值
CPU会自动执行中断处理函数,不需要由外部进行调用
为了方便实现一个模块的管理,将按键查询和按键中断操作统一写在一个源程序中,用预定义进行区分
KEY.C 代码如下
- /* Copyright (C), 2008-2010, wanczy Tech. Co., Ltd.
- File name : key.c
- Author : cy
- version : V1.0
- Date : 2010-6-23
- Description : key module function implement
- History :
- 1 Date 2010-6-23
- Author cy
- Modification
- */
- #include "2440addr.h"
- #include "uart.h"
- #include "key.h"
- #include "led.h"
- /********************* 以下是按键查询代码 ************************/
- #ifdef KEYPOLL
- /*
- Function name : key_init
- Description : key init
- Input parameter : none
- Return : none
- Others :
- */
- void key_init(void)
- {
- volatile unsigned int val;
- val = rGPFCON; /* SW1,SW2 */
- val &= ~((3)|(3<<4));
- rGPFCON = val;
- val = rGPGCON; /* SW3,SW4 */
- val &= ~((3<<6)|(3<<22));
- rGPFCON = val;
- }
- /*
- Function name : key_scan
- Description : return a key value to Main
- Input parameter : none
- Return : the int value
- Others :
- */
- int key_scan(void)
- {
- int key;
- unsigned int val;
- val = (~rGPFDAT)&((1)|(1<<2));
- switch(val)
- {
- case 1:
- {
- key = SW1;
- break;
- }
- case (1<<2):
- {
- key = SW2;
- break;
- }
- default:
- {
- key = NOKEY;
- break;
- }
- }
- val = (~rGPGDAT)&((1<<11)|(1<<3));
- switch(val)
- {
- case (1<<3):
- {
- key = SW3;
- break;
- }
- case (1<<11):
- {
- key = SW4;
- break;
- }
- }
- return key;
- }
- int key_old = NOKEY,key_new= NOKEY;
- /*
- Function name : key_getvalue
- Description : key
- Input parameter : none
- Return : the int value
- Others :
- */
- int get_keyvalue(void)
- {
- int key1,key2;
- key1 = key_scan(); /*recieve the key value when scan the key*/
- Delay(40); /* 进行去抖动操作 */
- key2 = key_scan();
- if(key1!=key2)
- {
- return NOKEY;
- }
- key_new = key2;
- if(key_old!=key_new)
- {
- key_old = key_new; /*disable the key repeat*/
- return key_new;
- }
- return NOKEY;
- }
- /*********************************************************************/
- /*==================== 以下是按键中断处理函数 ========================*/
- #elif defined KEYIRQ //If not define KEYPOLL, define KEYIRQ
- int keyvalue=NOKEY,keyflag=0;
- static void __irq EINT0(void) //按键1中断函数
- {
- rSRCPND |= BIT_EINT0;
- rINTPND |= BIT_EINT0;
- keyvalue = SW1;
- keyflag = 1;
- }
- static void __irq EINT2(void) //按键2中断函数
- {
- rSRCPND |= BIT_EINT2;
- rINTPND |= BIT_EINT2;
- keyvalue = SW2;
- keyflag = 1;
- }
- static void __irq EINT11_19(void) //按键3,4中断处理函数
- {
- //进行手动置1操作
- rSRCPND |= BIT_EINT8_23;
- rINTPND |= BIT_EINT8_23;
- //因为按键3和4共用一个中断源,所以要对响应的中断进行判断
- if(rEINTPEND==(1<<11))
- {
- rEINTPEND |= (1<<11);
- keyvalue = SW3;
- keyflag = 1;
- }
- else if(rEINTPEND==(1<<19))
- {
- rEINTPEND |=(1<<19);
- keyvalue = SW4;
- keyflag = 1;
- }
- }
- /*============================================================*/
- void irq_init(void)
- {
- rGPFCON= ((rGPFCON & ~((3<<0)|(3<<4)))|(2<<0)|(2<<4)); //EINT[0], EINT[2]
- rGPGCON= ((rGPGCON & ~((3<<6)|(3<<22)))|(2<<22)|(2<<6)); //EINT[11], EINT[19]
- rEXTINT0= ((rEXTINT0 & ~((7<<0)|(7<<8)))|(2<<0)(2<<8));// Falling edge triggered
- rEXTINT1= ((rEXTINT1 & ~(7<<12))|(2<<12)); //Falling edge triggered
- rEXTINT2= ((rEXTINT2 & ~(7<<12))|(2<<12)); // Falling edge triggered
- rEINTMASK = (rEINTMASK & ~((1<<11)|(1<<19))); //EINT11, EINT19 Disable the MASK
- rEINTPEND |= (1<<11)|(1<<19); //EINT11, EINT19 occur interrupt
- rINTMSK &= ~((BIT_EINT8_23)|(BIT_EINT2)|(BIT_EINT0)); //Disable MASK
- //SRCPND,INTPND进行置1操作
- rSRCPND |= (BIT_EINT8_23)|(BIT_EINT2)|(BIT_EINT0);
- rINTPND |= (BIT_EINT8_23)|(BIT_EINT2)|(BIT_EINT0);
- //将中断处理函数名加载到内存中断地址中
- pISR_EINT0= (unsigned )EINT0;
- pISR_EINT2= (unsigned )EINT2;
- pISR_EINT8_23= (unsigned )EINT11_19;
- }
- /*
- Function name : get_keyvalue
- Description : key
- Input parameter : none
- Return : the int value
- Others :
- */
- int get_keyvalue(void) //返回获取的键值
- {
- if(keyflag==0)
- return NOKEY;
- else
- {
- keyflag=0;
- return keyvalue;
- }
- }
- #endif
KEY.H 代码如下
- #ifndef _KEY_H
- #define _KEY_H
- #define SW1 1
- #define SW2 2
- #define SW3 3
- #define SW4 4
- #define NOKEY 0
- #define KEYIRQ
- //define KEYPOLL
- extern void key_init(void);
- extern int key_scan(void);
- extern void irq_init(void);
- extern int get_keyvalue(void);
- #endif