[程序源码] 分享一个通用的按键驱动程序

[复制链接]
2624|10
 楼主| mcu5i51 发表于 2016-5-9 09:14 | 显示全部楼层 |阅读模式
很少发贡献类的东东,这是自己写了几年的一个按键通用驱动,好久没有改动了,目前可以满足应用;
这个驱动模块可以提供按键的单次,连续,抬起,以及按下的有效时间,只是处理按键代码,如果用单个字节,可以表示8个可以组合的按键或255个没有组合的按键,不过由于我用的多数按键在4个左右,没有对255的键码做优化,好了上代码:
  1. #ifndef _KEY_H
  2. #define _KEY_H

  3. #include "Typedef.h"

  4. #define K1 0x01
  5. #define K2 0x02
  6. #define K3 0x04
  7. #define K4 0x08

  8. #define K5 0x10
  9. #define K6 0x20
  10. #define K7 0x40
  11. #define K8 0x80

  12. #define K_TIM(T)        (T/5)
  13. #define K_ONE_TIM          (K_TIM(24))
  14. #define K_CON_TIM          (K_TIM(700))
  15. #define K_MAX_TIM        (K_TIM(10000))


  16. typedef struct  
  17. {
  18.         u8 Key;                // 按键状态
  19.         u16 Tim;        // 按键时间
  20.         u8 One;                // 单次有效按键,只用一次
  21.         u8 Up;                // 按键放开,只用一次
  22.         u8 Con;                // 连续有效按键,
  23. }KeyType;

  24. extern KeyType Key;

  25. //////////////////////
  26. void Key_Init(void);
  27. u8 GetKeyPin(void);                 // 按键引脚
  28. void KeyDrv(void);                // 驱动

  29. ////////////////////////
  30. KeyType GetKey(void);


  31. #endif
  1. #include "io.h"

  2. #include "stdlib.h"
  3. #include "key.h"

  4. static KeyType KeyVol;
  5. KeyType Key;

  6. //////////////////////////////////////
  7. //        Key IO 操作
  8. //////////////////////////////////////
  9. void Key_Init(void)
  10. {
  11.         IO_Key_Init( );
  12. }

  13. u8 GetKeyPin(void)
  14. //按键引脚
  15. {       
  16.         return IO_GetKeyPin( );
  17. }

  18. /////////////////////////////////////////////////////////////
  19. /////////////////////////////////////////////////////////////

  20. KeyType GetKey(void)
  21. {
  22.         static KeyType _key;
  23.        
  24. // 禁用中断,也可以用标志位实现
  25. //        disable_interrupt( );
  26.         _key = KeyVol;
  27.         KeyVol.One = 0;
  28.         KeyVol.Up = 0;       
  29. //        enableInterrupts( );                        //开中断
  30.         return _key;
  31. }

  32. void KeyDrv(void)
  33. //驱动
  34. {
  35.         static u8 Tmp_u8;
  36.         Tmp_u8 = GetKeyPin();
  37.        
  38.         //没有按键        调用频率,最高到最低排列,减少CPU占用时间
  39.         if(Tmp_u8 == 0)
  40.         {
  41.                 //按键放开
  42.                 if(KeyVol.Key != 0)        KeyVol.Up = KeyVol.Key;       
  43.                
  44.                 KeyVol.Con = 0;        KeyVol.Tim = 0;KeyVol.Key = 0;
  45.                 return;
  46.         }

  47.         //按键没变
  48.         if(Tmp_u8 == KeyVol.Key)
  49.         {
  50.                 //最大按键有效时间
  51.                 if(KeyVol.Tim < K_MAX_TIM) KeyVol.Tim++;               
  52.                 //按键连按有效       
  53.                 if(KeyVol.Tim > K_CON_TIM)        {KeyVol.Con = Tmp_u8;return;}                       
  54.                 //按键首次有效
  55.                 if(KeyVol.Tim == K_ONE_TIM)        {KeyVol.One = Tmp_u8;}               
  56.                 return;
  57.         }
  58.         //按键改变
  59.         {KeyVol.Key = Tmp_u8;        KeyVol.Tim = 0;        return;}
  60. }
修改以下两个函数,对应硬件
void Key_Init(void)
u8 GetKeyPin(void)    //按键引脚

void KeyDrv(void) 这个是周期调用的,一般我是和LED动态显示一起处理,调好.H文件的时间定义就好了;

KeyType GetKey(void) 用户调用,返回按键值



没有测试的一个例子:

main()
{
int cont;
   Timer_Inti();  //200HZ
   Key_Init();
   
   while(1)
  {
     Key = GwtKey();
    switch(Key.One) 单次有效,如果怕与连续有冲突可以用Key.up,就是按键放开
    {
       case: break;.....
    }
   
    switch(Key.One | Key.Con) 单次和连续有效,表现为按下K1后数值加1,之后大约800MS左右就连续加1,速度是主循环的时间,常用100MS处理一次就是10HZ
    {
       case K1:
          Cont ++;
        break;.....
    }
       if(Key.Tim > TIM(2)  && (Key.Con == K2)  ){长按2秒处理}
       print(cont);
    wait(100);

  }
}







wsnsyy 发表于 2016-5-9 09:24 | 显示全部楼层
抄来用一下看看
 楼主| mcu5i51 发表于 2016-5-9 09:44 | 显示全部楼层
一个简单的测试工程,51的简单,不过没有实测,也就是静态分析正常

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
逍遥派掌门 发表于 2016-5-12 16:52 | 显示全部楼层
思路不错,但是楼主没有考虑按键的震荡,补上就更好了。
 楼主| mcu5i51 发表于 2016-5-13 08:30 | 显示全部楼层
逍遥派掌门 发表于 2016-5-12 16:52
思路不错,但是楼主没有考虑按键的震荡,补上就更好了。

按键的震荡,不是很明白什么意思,如果是指的去抖动的话,已经有了
any012 发表于 2016-5-13 14:23 | 显示全部楼层
感谢分享,先下载下来看看。
好像下载了楼主好几个程序了。
hgjinwei 发表于 2016-5-14 10:09 | 显示全部楼层
KeyVol.Up 这个状态不可靠,可能存在干扰
如果GwtKey();执行的够频繁,KeyVol.Up 不一定能反应真实的按键释放次数。
不知楼主是否验证。

附件是本年写的一个按键驱动,尚未确认是否稳定(使用的时间还不够长,平台也不够多),
喜欢的人可以下载看看,希望有不可靠的反馈。

PS:#include "key.h"里面只是一些数据类型定义,比如"uint8","__CONST"等,可以自行加入。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
逍遥派掌门 发表于 2016-5-17 14:32 | 显示全部楼层
本帖最后由 逍遥派掌门 于 2016-5-17 15:40 编辑
mcu5i51 发表于 2016-5-13 08:30
按键的震荡,不是很明白什么意思,如果是指的去抖动的话,已经有了

去抖动,是在main里面的wait(100) 吗? 
如果是的话,这种方式不好。

洛理小子 发表于 2016-5-17 22:37 | 显示全部楼层
mark    以后学习下~~
 楼主| mcu5i51 发表于 2016-5-18 11:23 | 显示全部楼层
逍遥派掌门 发表于 2016-5-17 14:32
去抖动,是在main里面的wait(100) 吗? 
如果是的话,这种方式不好。

不是呀,这个驱动是在中断中调用的,比较读取的键值有效次数,达到之后就是有效按键了
any012 发表于 2016-5-19 13:24 | 显示全部楼层
楼主在3份楼分享的附件,我下载下来解压时总是失败...
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

1889

帖子

9

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