数码相框项目模块【三】 KEY

按键有两种方式:查询和中断

按键查询操作

一、首先在电路图中找到按键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 代码如下

Code:
  1. /*  Copyright (C), 2008-2010, wanczy  Tech. Co., Ltd.  
  2. File  name  :   key.c  
  3. Author      :   cy  
  4. version     :   V1.0  
  5. Date        :   2010-6-23  
  6. Description :  key module function  implement    
  7. History     :           
  8. 1  Date         2010-6-23   
  9.    Author       cy  
  10.    Modification    
  11. */  
  12.   
  13. #include "2440addr.h"   
  14. #include "uart.h"   
  15. #include "key.h"   
  16. #include "led.h"   
  17.   
  18.   
  19.   
  20.   
  21. /********************* 以下是按键查询代码 ************************/  
  22.   
  23. #ifdef   KEYPOLL   
  24.   
  25. /*  
  26. Function  name  :   key_init  
  27. Description     :   key init  
  28. Input parameter :   none  
  29. Return          :   none          
  30. Others          :                                             
  31. */  
  32.   
  33. void key_init(void)   
  34. {   
  35.     volatile unsigned int val;   
  36.     val = rGPFCON;              /* SW1,SW2 */  
  37.     val &= ~((3)|(3<<4));     
  38.     rGPFCON = val;   
  39.        
  40.     val = rGPGCON;             /* SW3,SW4 */  
  41.     val &= ~((3<<6)|(3<<22));     
  42.     rGPFCON = val;   
  43.        
  44. }   
  45.   
  46. /*  
  47. Function  name  :   key_scan  
  48. Description     :   return a key value to Main  
  49. Input parameter :   none  
  50. Return          :   the int value     
  51. Others          :                                             
  52. */  
  53.   
  54. int key_scan(void)   
  55. {   
  56.    int key;     
  57.    unsigned int val;   
  58.    val = (~rGPFDAT)&((1)|(1<<2));   
  59.       
  60.    switch(val)   
  61.    {   
  62.         case 1:   
  63.             {   
  64.                 key = SW1;   
  65.                 break;   
  66.             }   
  67.         case (1<<2):   
  68.             {   
  69.                 key = SW2;   
  70.                 break;   
  71.             }   
  72.         default:   
  73.             {   
  74.                 key = NOKEY;   
  75.                 break;   
  76.             }   
  77.    }   
  78.       
  79.   val = (~rGPGDAT)&((1<<11)|(1<<3));           
  80.   switch(val)   
  81.    {   
  82.         case (1<<3):   
  83.             {   
  84.                 key = SW3;   
  85.                 break;   
  86.             }   
  87.         case (1<<11):   
  88.             {   
  89.                 key = SW4;   
  90.                 break;   
  91.             }   
  92.   
  93.    }    
  94.     return key;   
  95. }   
  96.   
  97. int key_old = NOKEY,key_new= NOKEY;   
  98.   
  99. /*  
  100. Function  name  :   key_getvalue  
  101. Description     :   key    
  102. Input parameter :   none   
  103. Return          :   the int value         
  104. Others          :                                             
  105. */  
  106.   
  107. int get_keyvalue(void)   
  108. {   
  109.     int key1,key2;   
  110.        
  111.     key1 = key_scan();   /*recieve the key value when scan the key*/  
  112.     Delay(40);          /* 进行去抖动操作 */  
  113.     key2 = key_scan();   
  114.        
  115.     if(key1!=key2)       
  116.     {   
  117.         return NOKEY;   
  118.     }   
  119.        
  120.     key_new = key2;   
  121.        
  122.     if(key_old!=key_new)   
  123.     {   
  124.         key_old = key_new;   /*disable the key repeat*/  
  125.         return key_new;   
  126.     }   
  127.     return NOKEY;   
  128. }   
  129.   
  130. /*********************************************************************/  
  131.   
  132.   
  133.   
  134.   
  135. /*==================== 以下是按键中断处理函数 ========================*/  
  136.   
  137.   
  138. #elif defined  KEYIRQ    //If not define KEYPOLL, define KEYIRQ   
  139.   
  140. int keyvalue=NOKEY,keyflag=0;   
  141.   
  142.   
  143. static void __irq EINT0(void)  //按键1中断函数   
  144. {   
  145.     rSRCPND |= BIT_EINT0;   
  146.     rINTPND |= BIT_EINT0;   
  147.        
  148.     keyvalue = SW1;   
  149.     keyflag = 1;   
  150.   
  151.        
  152. }   
  153.   
  154. static void __irq EINT2(void//按键2中断函数   
  155. {   
  156.     rSRCPND |= BIT_EINT2;   
  157.     rINTPND |= BIT_EINT2;    
  158.        
  159.     keyvalue = SW2;   
  160.     keyflag = 1;   
  161.        
  162. }   
  163.   
  164. static void __irq EINT11_19(void//按键3,4中断处理函数   
  165. {   
  166.     //进行手动置1操作   
  167.        
  168.     rSRCPND |= BIT_EINT8_23;     
  169.     rINTPND |= BIT_EINT8_23;   
  170.        
  171.     //因为按键3和4共用一个中断源,所以要对响应的中断进行判断   
  172.        
  173.     if(rEINTPEND==(1<<11))     
  174.     {   
  175.         rEINTPEND |= (1<<11);   
  176.         keyvalue = SW3;   
  177.         keyflag = 1;   
  178.     }   
  179.     else if(rEINTPEND==(1<<19))   
  180.     {   
  181.         rEINTPEND |=(1<<19);   
  182.         keyvalue = SW4;   
  183.         keyflag = 1;   
  184.     }   
  185.        
  186. }   
  187.   
  188. /*============================================================*/  
  189.   
  190. void irq_init(void)   
  191. {   
  192.        
  193.     rGPFCON= ((rGPFCON & ~((3<<0)|(3<<4)))|(2<<0)|(2<<4));     //EINT[0], EINT[2]   
  194.     rGPGCON= ((rGPGCON & ~((3<<6)|(3<<22)))|(2<<22)|(2<<6)); //EINT[11], EINT[19]   
  195.           
  196.        
  197.     rEXTINT0= ((rEXTINT0 & ~((7<<0)|(7<<8)))|(2<<0)(2<<8));// Falling edge triggered         
  198.     rEXTINT1= ((rEXTINT1 & ~(7<<12))|(2<<12));              //Falling edge triggered   
  199.     rEXTINT2= ((rEXTINT2 & ~(7<<12))|(2<<12));              // Falling edge triggered   
  200.        
  201.        
  202.     rEINTMASK = (rEINTMASK & ~((1<<11)|(1<<19)));           //EINT11, EINT19 Disable the MASK   
  203.     rEINTPEND |= (1<<11)|(1<<19);             //EINT11, EINT19 occur interrupt                
  204.        
  205.        
  206.     rINTMSK &= ~((BIT_EINT8_23)|(BIT_EINT2)|(BIT_EINT0));   //Disable  MASK   
  207.     //SRCPND,INTPND进行置1操作   
  208.     rSRCPND |= (BIT_EINT8_23)|(BIT_EINT2)|(BIT_EINT0);   
  209.     rINTPND |= (BIT_EINT8_23)|(BIT_EINT2)|(BIT_EINT0);   
  210.        
  211.     //将中断处理函数名加载到内存中断地址中   
  212.        
  213.     pISR_EINT0= (unsigned )EINT0;   
  214.     pISR_EINT2= (unsigned )EINT2;   
  215.     pISR_EINT8_23= (unsigned )EINT11_19;   
  216. }   
  217.   
  218. /*  
  219. Function  name  :   get_keyvalue  
  220. Description     :   key    
  221. Input parameter :   none   
  222. Return          :   the int value         
  223. Others          :                                             
  224. */  
  225.   
  226. int get_keyvalue(void//返回获取的键值   
  227. {   
  228.     if(keyflag==0)   
  229.         return NOKEY;   
  230.     else  
  231.     {   
  232.         keyflag=0;   
  233.         return keyvalue;   
  234.     }   
  235. }   
  236.   
  237. #endif   
  238.   


KEY.H  代码如下

Code:
  1. #ifndef _KEY_H   
  2. #define _KEY_H   
  3.   
  4. #define SW1   1   
  5. #define SW2   2   
  6. #define SW3   3   
  7. #define SW4   4   
  8. #define NOKEY 0   
  9.   
  10. #define KEYIRQ   
  11. //define KEYPOLL   
  12.   
  13. extern void key_init(void);   
  14. extern int key_scan(void);   
  15. extern void irq_init(void);   
  16. extern int get_keyvalue(void);   
  17.   
  18. #endif  

 

你可能感兴趣的:(数码相框)