[原创] 【LPC54100】第二周-添加按键处理程序并在LCD上显示

shower.xu   2015-4-5 10:05 楼主
上一篇添加了一个小屏幕之后,这次计划把按键系统增加进去,毕竟作为最重要的输入交互部分,按键是整个系统必不可少的重要部分。



我的是第二批的LPC54100板子,板子上带了一个五位按键,一个复位按键,和两个功能键,一共8个,其中复位键我们不用处理,所以就是7个按键要处理。



我打算实现按键的长短按和连按的检测,所以需要建立一个按键处理状态机,首先进行初始化

  1. #include "key_fun.h"
  2. #include "bsp_key.h"

  3. #define KEY_COUNT                        7
  4. #define KEY0        0x0001
  5. #define KEY1        0x0002
  6. #define KEY2        0x0004
  7. #define KEY3        0x0008
  8. #define KEY4        0x0010
  9. #define KEY5        0x0020
  10. #define KEY6        0x0040

  11. // 需要修改部分
  12. #define button0                 KEY0_IN
  13. #define button1          (KEY1_IN)
  14. #define button2                KEY2_IN
  15. #define button3         KEY3_IN
  16. #define button4         (KEY4_IN)
  17. #define button5         KEY5_IN
  18. #define button6         KEY6_IN

  19. #define GetKey0                (button0?0:KEY0)
  20. #define GetKey1                (button1?0:KEY1)
  21. #define GetKey2                (button2?0:KEY2)
  22. #define GetKey3                (button3?0:KEY3)
  23. #define GetKey4                (button4?0:KEY4)
  24. #define GetKey5                (button5?0:KEY5)
  25. #define GetKey6                (button6?0:KEY6)
  26. // 控制按键时长
  27. #define LONG_PRESS_MAX 250 // 20ms*250=5s,长按最大
  28. #define LONG_PRESS 100 // 20ms*100=2s,长按
  29. #define SHORT_PRESS 5 // 20ms*5=100ms,短按
  30. #define MID_PRESS 50 // 20ms*50=1s,连按                第一次开始时间
  31. #define REPEAT_PRESS 25 // 20ms*25=500ms,连按灵敏参数 ,半秒钟触发一次

  32. #define FALSE        false
  33. #define TRUE        true       
  34. //私有变量
  35. unsigned char key_time[KEY_COUNT];
  36. unsigned long io_last,io_now;
  37. //全局变量
  38. unsigned short key_status; // Long[15...8]/Short[7...0]

  39. // 初始化
  40. void key_fun_init(void)
  41. { unsigned char i;
  42.         //初始化按键I/O口属性
  43.                 KEY_Initialize();
  44.         //初始化变量
  45.     io_last=0;
  46.     io_now=0;
  47.     key_status=0;
  48.                 for(i=0;i<KEY_COUNT;i++) key_time[i]=0;  
  49. }



按键长按,短按和连按的时间在宏定义里面可以修改
接着是按键扫描程序

  1. // 按键处理
  2. void key_scan(void)
  3. {
  4.     //按键端口上拉了,默认是高电平,有按键时变低。这里取反,有按键时变高。
  5.     io_now=0;
  6.           io_now=GetKey0|GetKey1|GetKey2|GetKey3|GetKey4|GetKey5|GetKey6;
  7.                 key_status=0;
  8.     // set键只分长按和短按,没有连按
  9.     if ((io_now&KEY0) & (io_last&KEY0))
  10.     {   
  11.         key_time[0]++;
  12.         if (key_time[0]==LONG_PRESS) {key_status|= KEY_SET_LONG;}
  13.         if (key_time[0]>LONG_PRESS) key_time[0] = LONG_PRESS+1;        //只触发一次   
  14.     }
  15.     else
  16.     {        //按键释放
  17.         if(key_time[0]>SHORT_PRESS)
  18.         {
  19.           if ((key_time[0]<LONG_PRESS))       key_status |= KEY_SET_SHORT;        //短按只在按键释放时响应,且只触发一次,
  20.         }
  21.         key_time[0] = 0;
  22.     }

  23.     // up和down键有连按和短按,没有长按
  24.     if ((io_now&KEY1) & (io_last&KEY1))
  25.     {
  26.         key_time[1]++;
  27.         if (key_time[1]>MID_PRESS)                      //持续按住过程中当时间大于MID_PRESS定义时触发一次短按
  28.         {                               
  29.             key_status |= KEY_UP_SHORT;
  30.             key_time[1] = key_time[1] - REPEAT_PRESS;   //设定出发周期,继续等待下一次触发
  31.         }
  32.     }
  33.     else
  34.     {
  35.         if (key_time[1]>SHORT_PRESS)
  36.         {                       
  37.             key_status |= KEY_UP_SHORT;            //释放时根据时间触发一次短按
  38.         }
  39.         key_time[1] = 0;                                //只要释放,都要重新计时
  40.     }

  41.     // up和down键有连按和短按,没有长按
  42.     if ((io_now&KEY2) & (io_last&KEY2))
  43.     {
  44.         key_time[2]++;
  45.         if (key_time[2]>MID_PRESS)
  46.         {
  47.             key_status |= KEY_DOWN_SHORT;
  48.             key_time[2] = key_time[2] - REPEAT_PRESS;
  49.         }
  50.     }
  51.     else
  52.     {
  53.         if (key_time[2]>SHORT_PRESS)
  54.         {
  55.             key_status |= KEY_DOWN_SHORT;
  56.         }
  57.         key_time[2] = 0;
  58.     }
  59.                
  60.     // up和down键有连按和短按,没有长按
  61.     if ((io_now&KEY3) & (io_last&KEY3))
  62.     {
  63.         key_time[3]++;
  64.         if (key_time[3]>MID_PRESS)
  65.         {
  66.             key_status |= KEY_LEFT_SHORT;
  67.             key_time[3] = key_time[3] - REPEAT_PRESS;
  68.         }
  69.     }
  70.     else
  71.     {
  72.         if (key_time[3]>SHORT_PRESS)
  73.         {
  74.             key_status |= KEY_LEFT_SHORT;
  75.         }
  76.         key_time[3] = 0;
  77.     }
  78.                
  79.     // up和down键有连按和短按,没有长按
  80.     if ((io_now&KEY4) & (io_last&KEY4))
  81.     {
  82.         key_time[4]++;
  83.         if (key_time[4]>MID_PRESS)
  84.         {
  85.             key_status |= KEY_RIGHT_SHORT;
  86.             key_time[4] = key_time[4] - REPEAT_PRESS;
  87.         }
  88.     }
  89.     else
  90.     {
  91.         if (key_time[4]>SHORT_PRESS)
  92.         {
  93.             key_status |= KEY_RIGHT_SHORT;
  94.         }
  95.         key_time[4] = 0;
  96.     }
  97.     // KEY1键只分长按和短按,没有连按
  98.     if ((io_now&KEY5) & (io_last&KEY5))
  99.     {   
  100.         key_time[5]++;
  101.         if (key_time[5]==LONG_PRESS) {key_status|= KEY_KEY1_LONG;}
  102.         if (key_time[5]>LONG_PRESS) key_time[5] = LONG_PRESS+1;        //只触发一次   
  103.     }
  104.     else
  105.     {        //按键释放
  106.         if(key_time[5]>SHORT_PRESS)
  107.         {
  108.           if ((key_time[5]<LONG_PRESS))       key_status |= KEY_KEY1_SHORT;        //短按只在按键释放时响应,且只触发一次,
  109.         }
  110.         key_time[5] = 0;
  111.     }
  112.     // KEY2键只分长按和短按,没有连按
  113.     if ((io_now&KEY6) & (io_last&KEY6))
  114.     {   
  115.         key_time[6]++;
  116.         if (key_time[6]==LONG_PRESS) {key_status|= KEY_KEY2_LONG;}
  117.         if (key_time[6]>LONG_PRESS) key_time[6] = LONG_PRESS+1;        //只触发一次   
  118.     }
  119.     else
  120.     {        //按键释放
  121.         if(key_time[6]>SHORT_PRESS)
  122.         {
  123.           if ((key_time[6]<LONG_PRESS))       key_status |= KEY_KEY2_SHORT;        //短按只在按键释放时响应,且只触发一次,
  124.         }
  125.         key_time[6] = 0;
  126.     }                
  127.                
  128.                
  129.                
  130.     // 添加自己对于set_long,set_short,up_short,down_short的处理代码
  131.     // 处理完了不要忘记把相应的值置为FALSE
  132.     io_last = io_now;
  133. }
在主循环里周期性调用按键扫描函数即可,之后就可以通过判断key_status即可知道是那个或那些按键按下了。
  1. /*        处理完毕,清除标志位 */
  2. void key_flag_clr(void)
  3. {
  4. key_status=0;
  5. }
之后需要清掉key_status。

主循环
  1. Lcd7585_write_string(0,7,(char *)"LPC541x Board");  
  2.         Lcd7585_write_string(0,6,(char *)" --by Shower.xu");   
  3.         while(1)
  4.         {   
  5.                 delay_xms(15);
  6.                 key_scan();
  7.                 if(key_status)
  8.                 {
  9.                         if(key_status&KEY_SET_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
  10.                         Lcd7585_write_string(12,3,(char *)"o");
  11.                         if(key_status&KEY_UP_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
  12.                         Lcd7585_write_string(12,4,(char *)"^");
  13.                         if(key_status&KEY_DOWN_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
  14.                         Lcd7585_write_string(12,2,(char *)"v");
  15.                         if(key_status&KEY_LEFT_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
  16.                         Lcd7585_write_string(2,3,(char *)"<");
  17.                         if(key_status&KEY_RIGHT_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
  18.                         Lcd7585_write_string(22,3,(char *)">");                
  19.                         if(key_status&KEY_KEY1_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
  20.                         Lcd7585_write_string(42,4,(char *)" KEY1 ");        
  21.                         if(key_status&KEY_KEY2_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
  22.                         Lcd7585_write_string(42,2,(char *)" KEY2 ");        
  23.                         key_flag_clr();
  24.                 }
  25.         }
这样就可以在lcd上显示出来按键状态了。
其中向左的按键因为和swd调试接口复用,所以.....,真是奇怪的设计
图片在这里
IMG_20150403_170643.jpg
代码在这里
4-Key2.rar (47.06 KB)
(下载次数: 28, 2015-4-5 10:04 上传)
视频在这里
[media]http://www.tudou.com/v/rMYC7T6B7gc/&rpid=100900070&resourceId=100900070_04_05_99/v.swf[/media]

回复评论 (1)

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复