找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7797|回复: 6
收起左侧

单片机轮询按键程序

  [复制链接]
ID:77367 发表于 2015-4-19 02:22 | 显示全部楼层 |阅读模式
修改N次。可判断按下。长按。放手。
跟踪程序跟了N次才理解清楚。然后修改成现在这样。
  1. #include <reg52.h>
  2. #define uchar unsigned char
  3. //按键端口定义
  4. sbit io_key_1 = P2^0 ;
  5. sbit io_key_2 = P2^1 ;
  6. sbit io_key_3 = P2^2 ;
  7. sbit io_key_4 = P2^3 ;
  8. sbit P30 = P3^0;
  9. sbit P31 = P3^1;
  10. sbit P32 = P3^2;
  11. sbit P33 = P3^3;
  12.                   
  13. //定义长按键的TICK数,以及连_发间隔的TICK数
  14. #define KEY_LONG_PERIOD         100  
  15. #define KEY_CONTINUE_PERIOD     20
  16. #define KEY_DOUDONG             20
  17. //定义按键返回值状态(按下,长按,连_发,释放)
  18. #define KEY_DOWN            0x80  
  19. #define KEY_LONG            0x40  
  20. #define KEY_CONTINUE        0x20  
  21. #define KEY_UP              0x10      
  22. //定义按键状态
  23. #define KEY_STATE_INIT      0  
  24. #define KEY_STATE_WOBBLE    1  
  25. #define KEY_STATE_PRESS     2  
  26. #define KEY_STATE_LONG      3  
  27. #define KEY_STATE_CONTINUE  4  
  28. #define KEY_STATE_RELEASE   5  
  29. //按键值
  30. #define KEY_VALUE_1         0x0e
  31. #define KEY_VALUE_2         0x0d
  32. #define KEY_VALUE_3         0x0b
  33. #define KEY_VALUE_4         0x07
  34. #define KEY_NULL            0x0f
  35. static uchar s_u8KeyState = KEY_STATE_INIT;     //关键状态  
  36. static uchar s_u8KeyTimeCount = 0;      //关键时间计数
  37. static uchar s_u8LastKey = KEY_NULL;   //保存按键释放时候的键值
  38. void delay_nms(unsigned char k)
  39. {
  40.     unsigned int i,j;
  41.     for(i=0;i<k;i++)
  42.         for(j=0;j<120;j++)
  43.             ;
  44. }
  45. //按键初始化
  46. void KeyInit(void)
  47. {
  48.      io_key_1 = 1;
  49.      io_key_2 = 1;
  50.      io_key_3 = 1;
  51.      io_key_4 = 1;            
  52. }
  53. //按键扫描
  54. static uchar KeyScan(void)
  55. {
  56.      if(io_key_1 == 0)return KEY_VALUE_1;
  57.      if(io_key_2 == 0)return KEY_VALUE_2;
  58.      if(io_key_3 == 0)return KEY_VALUE_3;
  59.      if(io_key_4 == 0)return KEY_VALUE_4;
  60.      return KEY_NULL;
  61. }
  62. void GetKey(uchar *pKeyValue)
  63. {
  64.      static uchar s_u8KeyState = KEY_STATE_INIT ;
  65.      static uchar s_u8KeyTimeCount = 0 ;
  66.      static uchar s_u8LastKey = KEY_NULL ;   //保存按键释放时候的键值
  67.      static uchar s_doudong=0;
  68.      uchar KeyTemp = KEY_NULL ;
  69.      KeyTemp = KeyScan() ;         //获取键值
  70.      switch(s_u8KeyState)
  71.      {
  72.          case KEY_STATE_INIT :          //初始化S1状态
  73.                  {
  74.                      if(KEY_NULL != (KeyTemp))  //如果有按键按下 进入状态2
  75.                      {
  76.                          s_u8KeyState = KEY_STATE_WOBBLE ;
  77.                      }
  78.                  }
  79.          break ;
  80.          case KEY_STATE_WOBBLE :        //去抖动S2状态  
  81.                  {
  82.                     if(++s_doudong==KEY_DOUDONG)
  83.                     {
  84.                         s_doudong=0;
  85.                         s_u8KeyState = KEY_STATE_PRESS ;     
  86.                     }
  87.                     else
  88.                         s_u8KeyState = KEY_STATE_WOBBLE;   
  89.                  }
  90.          break ;
  91.          case KEY_STATE_PRESS :         //确认有按键按下S3状态 并返回按键值         
  92.                  {
  93.                      if(KEY_NULL != (KeyTemp))  
  94.                      {
  95.                          s_u8LastKey = KeyTemp ; //保存键值,以便在释放按键状态返回键值
  96.                          KeyTemp |= KEY_DOWN ;   //按键按下
  97.                          s_u8KeyState = KEY_STATE_LONG ;    //保存下次进入长按状态
  98.                      }
  99.                      else   //如果没有按键按下 返回初始化S1
  100.                      {
  101.                          s_u8KeyState = KEY_STATE_INIT ;
  102.                      }
  103.                  }
  104.          break ;
  105.          case KEY_STATE_LONG :          //进入长按
  106.                  {
  107.                      if(KEY_NULL != (KeyTemp))  //确认有按键按下  计数
  108.                      {
  109.                          if(++s_u8KeyTimeCount > KEY_LONG_PERIOD)   //到达阀值 返回长按键值
  110.                          {
  111.                              s_u8KeyTimeCount = 0 ;
  112.                              KeyTemp |= KEY_LONG ;   //长按键事件发生
  113.                              s_u8KeyState = KEY_STATE_LONG ;    //保存下次进入
  114.                          }
  115.                      }
  116.                      else
  117.                      {
  118.                          s_u8KeyState = KEY_STATE_RELEASE ;         //长按状态 按键放开
  119.                      }
  120.                  }
  121.          break ;
  122.          case KEY_STATE_CONTINUE :                                  //连发状态
  123.                  {
  124.                      if(KEY_NULL != (KeyTemp))
  125.                      {
  126.                          if(++s_u8KeyTimeCount > KEY_CONTINUE_PERIOD)
  127.                          {
  128.                              s_u8KeyTimeCount = 0 ;
  129.                              KeyTemp |= KEY_CONTINUE ;
  130.                          }
  131.                      }
  132.                      else       //如果没有按键 直接返回按键
  133.                      {
  134.                          s_u8KeyState = KEY_STATE_RELEASE ;
  135.                      }
  136.                  }
  137.          break ;
  138.          case KEY_STATE_RELEASE :           //短按返回
  139.                  {
  140.                      s_u8LastKey |= KEY_UP ;
  141.                      KeyTemp = s_u8LastKey ;
  142.                      s_u8KeyState = KEY_STATE_INIT ;
  143.                  }
  144.          break ;
  145.          default : break ;
  146.      }
  147.      *pKeyValue = KeyTemp ; //返回键值     
  148. }
  149. void Key_Proc(uchar key_value)
  150. {
  151.     switch(key_value)
  152.     {
  153.         case KEY_VALUE_1 | KEY_DOWN:
  154.             P3=0X0f;    //0000 1111
  155.             delay_nms(500);
  156.             break;
  157.         case KEY_VALUE_1 | KEY_LONG:
  158.             P3 = 0xf0;  //1111 0000
  159.             break;
  160.         case KEY_VALUE_1 | KEY_UP:
  161.             P3 = 0x33;  //0011 0011
  162.             break;
  163.         default:
  164.             break;
  165.     }
  166. }
  167. void main(void)
  168. {     
  169.     uchar KeyValue = KEY_NULL;
  170.     KeyInit();
  171.     P2=0xff;
  172.     P3=0x00;
  173.     while(1)                  
  174.     {   
  175.         GetKey(&KeyValue) ;
  176.         Key_Proc(KeyValue);                     
  177.     }
  178. }
复制代码



评分

参与人数 1黑币 +12 收起 理由
YJGG + 12

查看全部评分

回复

使用道具 举报

ID:98707 发表于 2016-3-1 18:21 | 显示全部楼层
很好的代码,学习了.51黑电子论坛上的好资料真多!
回复

使用道具 举报

ID:82098 发表于 2016-11-22 16:31 | 显示全部楼层
矩阵键盘可以用这个程序吗?
回复

使用道具 举报

ID:159270 发表于 2017-3-3 01:42 | 显示全部楼层
这个程序会阻塞的吗?
回复

使用道具 举报

ID:377382 发表于 2020-4-20 20:44 | 显示全部楼层
很不错的
回复

使用道具 举报

ID:748312 发表于 2020-5-10 17:24 | 显示全部楼层
下来测试下,谢谢提供
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表