找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1629|回复: 0
打印 上一主题 下一主题
收起左侧

单片机状态机按键程序 支持短按和长按,可移植性好

[复制链接]
跳转到指定楼层
楼主
ID:196103 发表于 2022-9-29 11:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
状态机按键程序,可移植性好,支持短按和长按。亲测可用。
单片机源程序如下:
  1. #include <iom16.h>
  2. #include <intrinsics.h>
  3. #include <stdbool.h>//位变量头文件
  4. #include <iomacro.h>
  5. #include "keyboard.h"

  6. #define key_state_init 0   //按键的初始状态
  7. #define key_state_ok 1   //按键被按下的状态
  8. #define key_state_long 2   //按键被长按状态
  9. //#define key_state_continue 3   //按键被连续按下状态
  10. #define key_state_release 4   //按键释放的状态

  11. unsigned char KeyRead()
  12. {
  13.   static unsigned int key_timenum=0;//按键长按时间变量
  14.   static unsigned char key_state=0; //按键的状态
  15.   static unsigned char key_num=0;//保存按键按键释放时的值
  16.   static bool key_LONG=0;//记录长按释放
  17.   unsigned char  key_return=0;        //按键返回值       
  18.   unsigned char key_press; //保存按键按下的端口值       

  19.   key_press =(port^0xFF)&0XFF; // 读按键I/O电平

  20.   switch (key_state)
  21.   {
  22.     case key_state_init://按键的初始状态
  23.         if(key_press)//如果按键被按下
  24.         {
  25.           key_state=key_state_ok;//则把key_state按键状态置为按键确认状态
  26.         }
  27.          break;
  28.     case key_state_ok://按键确认状态
  29.         if(key_press)//如果按键被按下
  30.         {
  31.           key_num=key_press;// 按键I/O电平保存
  32.           key_state=key_state_long;//则把key_state按键状态置为按键被长按状态
  33.         }
  34.         else
  35.           key_state=key_state_init;        //如果按键是抖动则返回按键的初始状态
  36.         
  37.          break;
  38.     case key_state_long://按键被长按状态
  39.         if(key_press)//如果按键被按下
  40.         {
  41.           if(!key_LONG)//如果上次有长按事件发生,长按时间就不再计时。
  42.           {
  43.               if (++key_timenum>=KEY_LONG_PERIOD)//达到长按设置值时
  44.               {
  45.                 key_timenum=0;
  46.                 key_return=(key_press+KEY_LONGSIGN);//返回按键值加个数来区别单按和长按
  47.                 key_LONG=1;//标记长按事件发生
  48.               }
  49.           }
  50.           else
  51.             key_return=(key_press+KEY_LONGSIGN);//返回按键值加个数来区别单按和长按
  52.         }
  53.         else
  54.           key_state=key_state_release;        //则把key_state按键状态置为按键被释放状态       
  55.          break;               
  56.     case key_state_release://按键释放状态

  57.         if (key_LONG)//如果有长按事件发生
  58.         {
  59.           if(!key_press)//如果按键全部释放
  60.           {
  61.             key_return=0;//返回值清0
  62.             key_state=key_state_init;//则把key_state按键状态置为按键初始状态
  63.             key_timenum=0;//计数清0
  64.             key_LONG=0;//长按标记清0
  65.           }
  66.           else//如果按键没有释放
  67.           {
  68.              key_state=key_state_release;//则继续把key_state按键状态置为按键被释放状态       
  69.           }  
  70.         }
  71.         else//如果没有长按事件发生
  72.         {
  73.           if(!key_press)//如果按键全部释放
  74.           {
  75.             key_return=key_num;
  76.             key_state=key_state_init;//则把key_state按键状态置为按键初始状态
  77.             key_timenum=0;//计数清0
  78.           }
  79.           else
  80.           {
  81.             key_state=key_state_release;//则继续把key_state按键状态置为按键被释放状态       
  82.           }  
  83.         }                       
  84.          break;
  85.     }
  86.     return key_return;                 
  87. }
复制代码
  1. #ifndef __KEYBOARD_H__
  2. #define __KEYBOARD_H__

  3. #define K1 0X01//设定按键位置
  4. #define K2 0X02//设定按键位置
  5. #define K3 0X04//设定按键位置
  6. #define K4 0X08//设定按键位置
  7. #define K5 0X10//设定按键位置
  8. #define K6 0X20//设定按键位置
  9. #define K7 0X40//设定按键位置
  10. #define K8 0X80//设定按键位置
  11. #define L_K1 0X01+KEY_LONGSIGN//设定按键位置
  12. #define L_K2 0X02+KEY_LONGSIGN//设定按键位置
  13. #define L_K3 0X04+KEY_LONGSIGN//设定按键位置
  14. #define L_K4 0X08+KEY_LONGSIGN//设定按键位置
  15. #define L_K5 0X10+KEY_LONGSIGN//设定按键位置
  16. #define L_K6 0X20+KEY_LONGSIGN//设定按键位置
  17. #define L_K7 0X40+KEY_LONGSIGN//设定按键位置
  18. #define L_K8 0X80+KEY_LONGSIGN//设定按键位置
  19. #define port PINA//设定按键端口
  20. #define KEY_LONGSIGN 5//设定长按按键与普通按键差值
  21. #define KEY_LONG_PERIOD 150//定义长按键时间,消抖时间*时间数
  22. unsigned char KeyRead();
  23. #endif
复制代码

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏6 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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