[8/16-bit MCU] 添加按键处理程序并在LCD上显示

[复制链接]
 楼主| 仙女山 发表于 2015-12-22 20:02 | 显示全部楼层 |阅读模式
我的是第二批的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

我打算实现按键的长短按和连按的检测,所以需要建立一个按键处理状态机,首先进行初始化
 楼主| 仙女山 发表于 2015-12-22 20:02 | 显示全部楼层
  1. #define GetKey0                (button0?0:KEY0)
  2. #define GetKey1                (button1?0:KEY1)
  3. #define GetKey2                (button2?0:KEY2)
  4. #define GetKey3                (button3?0:KEY3)
  5. #define GetKey4                (button4?0:KEY4)
  6. #define GetKey5                (button5?0:KEY5)
  7. #define GetKey6                (button6?0:KEY6)
  8. // 控制按键时长
  9. #define LONG_PRESS_MAX 250 // 20ms*250=5s,长按最大
  10. #define LONG_PRESS 100 // 20ms*100=2s,长按
  11. #define SHORT_PRESS 5 // 20ms*5=100ms,短按
  12. #define MID_PRESS 50 // 20ms*50=1s,连按                第一次开始时间
  13. #define REPEAT_PRESS 25 // 20ms*25=500ms,连按灵敏参数 ,半秒钟触发一次

 楼主| 仙女山 发表于 2015-12-22 20:03 | 显示全部楼层
  1. #define FALSE        false
  2. #define TRUE        true      
  3. //私有变量
  4. unsigned char key_time[KEY_COUNT];
  5. unsigned long io_last,io_now;
  6. //全局变量
  7. unsigned short key_status; // Long[15...8]/Short[7...0]

  8. // 初始化
  9. void key_fun_init(void)
  10. { unsigned char i;
  11.         //初始化按键I/O口属性
  12.                 KEY_Initialize();
  13.         //初始化变量
  14.     io_last=0;
  15.     io_now=0;
  16.     key_status=0;
  17.                 for(i=0;i<KEY_COUNT;i++) key_time[i]=0;  
  18. }
 楼主| 仙女山 发表于 2015-12-22 20:04 | 显示全部楼层
按键长按,短按和连按的时间在宏定义里面可以修改
接着是按键扫描程序
  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.     }
 楼主| 仙女山 发表于 2015-12-22 20:04 | 显示全部楼层
  1.     else
  2.     {        //按键释放
  3.         if(key_time[0]>SHORT_PRESS)
  4.         {
  5.           if ((key_time[0]<LONG_PRESS))       key_status |= KEY_SET_SHORT;        //短按只在按键释放时响应,且只触发一次,
  6.         }
  7.         key_time[0] = 0;
  8.     }

  9.     // up和down键有连按和短按,没有长按
  10.     if ((io_now&KEY1) & (io_last&KEY1))
  11.     {
  12.         key_time[1]++;
  13.         if (key_time[1]>MID_PRESS)                      //持续按住过程中当时间大于MID_PRESS定义时触发一次短按
  14.         {                              
  15.             key_status |= KEY_UP_SHORT;
  16.             key_time[1] = key_time[1] - REPEAT_PRESS;   //设定出发周期,继续等待下一次触发
  17.         }
  18.     }
 楼主| 仙女山 发表于 2015-12-22 20:05 | 显示全部楼层
  1.     else
  2.     {
  3.         if (key_time[1]>SHORT_PRESS)
  4.         {                       
  5.             key_status |= KEY_UP_SHORT;            //释放时根据时间触发一次短按
  6.         }
  7.         key_time[1] = 0;                                //只要释放,都要重新计时
  8.     }

  9.     // up和down键有连按和短按,没有长按
  10.     if ((io_now&KEY2) & (io_last&KEY2))
  11.     {
  12.         key_time[2]++;
  13.         if (key_time[2]>MID_PRESS)
  14.         {
  15.             key_status |= KEY_DOWN_SHORT;
  16.             key_time[2] = key_time[2] - REPEAT_PRESS;
  17.         }
  18.     }
 楼主| 仙女山 发表于 2015-12-22 20:06 | 显示全部楼层
  1. else
  2.     {
  3.         if (key_time[2]>SHORT_PRESS)
  4.         {
  5.             key_status |= KEY_DOWN_SHORT;
  6.         }
  7.         key_time[2] = 0;
  8.     }
  9.                
  10.     // up和down键有连按和短按,没有长按
  11.     if ((io_now&KEY3) & (io_last&KEY3))
  12.     {
  13.         key_time[3]++;
  14.         if (key_time[3]>MID_PRESS)
  15.         {
  16.             key_status |= KEY_LEFT_SHORT;
  17.             key_time[3] = key_time[3] - REPEAT_PRESS;
  18.         }
  19.     }
  20.     else
  21.     {
  22.         if (key_time[3]>SHORT_PRESS)
  23.         {
  24.             key_status |= KEY_LEFT_SHORT;
  25.         }
  26.         key_time[3] = 0;
  27.     }
 楼主| 仙女山 发表于 2015-12-22 20:07 | 显示全部楼层
  1.     // up和down键有连按和短按,没有长按
  2.     if ((io_now&KEY4) & (io_last&KEY4))
  3.     {
  4.         key_time[4]++;
  5.         if (key_time[4]>MID_PRESS)
  6.         {
  7.             key_status |= KEY_RIGHT_SHORT;
  8.             key_time[4] = key_time[4] - REPEAT_PRESS;
  9.         }
  10.     }
  11.     else
  12.     {
  13.         if (key_time[4]>SHORT_PRESS)
  14.         {
  15.             key_status |= KEY_RIGHT_SHORT;
  16.         }
  17.         key_time[4] = 0;
  18.     }
 楼主| 仙女山 发表于 2015-12-22 20:08 | 显示全部楼层
  1.     // KEY1键只分长按和短按,没有连按
  2.     if ((io_now&KEY5) & (io_last&KEY5))
  3.     {   
  4.         key_time[5]++;
  5.         if (key_time[5]==LONG_PRESS) {key_status|= KEY_KEY1_LONG;}
  6.         if (key_time[5]>LONG_PRESS) key_time[5] = LONG_PRESS+1;        //只触发一次   
  7.     }
  8.     else
  9.     {        //按键释放
  10.         if(key_time[5]>SHORT_PRESS)
  11.         {
  12.           if ((key_time[5]<LONG_PRESS))       key_status |= KEY_KEY1_SHORT;        //短按只在按键释放时响应,且只触发一次,
  13.         }
  14.         key_time[5] = 0;
  15.     }
 楼主| 仙女山 发表于 2015-12-22 20:08 | 显示全部楼层
  1.     // KEY2键只分长按和短按,没有连按
  2.     if ((io_now&KEY6) & (io_last&KEY6))
  3.     {   
  4.         key_time[6]++;
  5.         if (key_time[6]==LONG_PRESS) {key_status|= KEY_KEY2_LONG;}
  6.         if (key_time[6]>LONG_PRESS) key_time[6] = LONG_PRESS+1;        //只触发一次   
  7.     }
  8.     else
  9.     {        //按键释放
  10.         if(key_time[6]>SHORT_PRESS)
  11.         {
  12.           if ((key_time[6]<LONG_PRESS))       key_status |= KEY_KEY2_SHORT;        //短按只在按键释放时响应,且只触发一次,
  13.         }
  14.         key_time[6] = 0;
  15.     }               
  16.            // 添加自己对于set_long,set_short,up_short,down_short的处理代码
  17.     // 处理完了不要忘记把相应的值置为FALSE
  18.     io_last = io_now;
  19. }
 楼主| 仙女山 发表于 2015-12-22 20:09 | 显示全部楼层
在主循环里周期性调用按键扫描函数即可,之后就可以通过判断key_status即可知道是那个或那些按键按下了。
  1. /*        处理完毕,清除标志位 */
  2. void key_flag_clr(void)
  3. {
  4. key_status=0;
  5. }

之后需要清掉key_status。
 楼主| 仙女山 发表于 2015-12-22 20:09 | 显示全部楼层
主循环
  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 *)">");      
 楼主| 仙女山 发表于 2015-12-22 20:10 | 显示全部楼层
  1. if(key_status&KEY_KEY1_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
  2.                         Lcd7585_write_string(42,4,(char *)" KEY1 ");        
  3.                         if(key_status&KEY_KEY2_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
  4.                         Lcd7585_write_string(42,2,(char *)" KEY2 ");        
  5.                         key_flag_clr();
  6.                 }
  7.         }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

340

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部