[KungFu8位 MCU] 基于 N76E003 的按键按键状态机

[复制链接]
1481|12
 楼主| merry_zsp 发表于 2019-10-31 09:43 | 显示全部楼层 |阅读模式
  前端时间要用按键,搞了个状态机(如图):
980846-20190912110926287-1179339257.jpg

 楼主| merry_zsp 发表于 2019-10-31 09:44 | 显示全部楼层
main.c
  1. #include <N76E003.H>
  2. #include <SFR_Macro.h>                    //N76E003 SFR寄存器设置宏定义
  3. #include <Function_define.h>            //功能定义
  4. #include "data.h"
  5. #include "interrupt.h"
  6. #include "button.h"
  7. /*--------------------------------------------------------*/
  8. // 初始化所有
  9. void Init_All(void){
  10.     InitMcu();                // 初始化MCU
  11.     Init_button();            // 键盘初始化
  12. }
  13. /*******************************************************************/
  14. // 发布版本
  15. void main(void){
  16.     Init_All();
  17.     while(1){
  18.         ;
  19.     }
  20. }
 楼主| merry_zsp 发表于 2019-10-31 09:44 | 显示全部楼层
data.h
  1. /*--------------------------------------------------------------------------
  2. data.h
  3. --------------------------------------------------------------------------*/
  4. #ifndef __DATA_H__
  5. #define __DATA_H__


  6. /*----------------------------------------------------*/
  7. // 按键状态(状态定义)
  8. #define  Button_DOWN                0        // 按键按下
  9. #define  Button_UP                    1        // 按键抬起
  10. // 按键功能模式(软件模式定义)
  11. #define  Button_mode_NoOperation        0        // 无动作
  12. #define  Button_mode_ShortPress            1        // 短按
  13. #define  Button_mode_longPress            2        // 长按
  14. #define  Button_mode_evenPress            3        // 连续快按(双击)
  15. // 键盘消抖时间
  16. #define Button_TimeDebounce                20/2    // 单位 ms 去抖动时间
  17. #define Button_TimeShort_even            100/2    // 单位 ms 短按转连续按时间
  18. #define Button_TimeEvenPressinterval    5000/2    // 单位 ms 双击判断阈值
  19. #define Button_TimeState_reset            60000/2    // 单位 ms 60s 无动作 退出设置
  20. // 键盘状态机模式
  21. #define  Button_status_S0                0        // 等待按键按下
  22. #define  Button_status_S1                1        // 去抖验证
  23. #define  Button_status_S2                2        // 按下时间(计算是不是长按)
  24. #define  Button_status_S3                3        // 快安判断(判断是不是短按)
  25. #define  Button_status_S4                4        // 快安去抖
  26. #define  Button_status_S5                5        // 等待快安退出
  27. /*----------------------------------------------------*/
  28. #define Unit_cycle                    32000        // 中断处理周期
  29. /*----------------------------------------------------*/
  30. struct Button_data{
  31.     unsigned int Button_LiftTime;                // 抬起时间
  32.     unsigned int Button_PressTime;                // 按下时间
  33.     unsigned char Button_State_machine_mode:3;    // 按键状态模式(状态机)
  34.     unsigned char Button_statusmode:2;            // 0无动作 1短按 2连发 3长按
  35.     unsigned char Button_status:1;                // 按键的状态(按键松开,界面刷新)

  36. };
  37. /*------------------------ 系统时间 ----------------------------*/
  38. struct OS_DATA{
  39.     // 系统初始化
  40.     unsigned char u8TH0_Tmp;                    // 中断高8位
  41.     unsigned char u8TL0_Tmp;                    // 中断低8位
  42.     // 键盘
  43.     struct Button_data Button0;

  44. };

  45. extern struct OS_DATA DATA;
  46. #endif
 楼主| merry_zsp 发表于 2019-10-31 09:45 | 显示全部楼层
data.c
  1. 1 #include "data.h"
  2. 2
  3. 3 struct OS_DATA DATA;            // 系统数据
 楼主| merry_zsp 发表于 2019-10-31 09:45 | 显示全部楼层
interrupt.h
  1. /*--------------------------------------------------------------------------
  2. interrupt.h
  3. --------------------------------------------------------------------------*/

  4. #ifndef __INTERRUPT_H__
  5. #define __INTERRUPT_H__

  6. /*----------------------------------------------------*/
  7. void InitMcu(void);
  8. #endif
 楼主| merry_zsp 发表于 2019-10-31 09:45 | 显示全部楼层
interrupt.c
  1. #include <N76E003.H>
  2. #include <SFR_Macro.h>                    //N76E003 SFR寄存器设置宏定义
  3. #include <Function_define.h>            //功能定义
  4. #include "data.h"
  5. #include "interrupt.h"
  6. #include "button.h"

  7. /*--------------------------------------------------------*/
  8. #define T0_INIT        Unit_cycle
  9. #define T0_ms         500
  10. /*--------------------------------------------------------*/
  11. //初始化单片机
  12. void InitMcu(void){
  13.     TIMER0_MODE1_ENABLE;                         //定时器0的模式1
  14.     set_T0M;                                    //设置定时器0的时钟为系统时钟
  15.     //u8TH0_Tmp和u8TL0_Tmp 宏变量 中断可调用
  16.     //Init_OS_Date();已经初始化
  17.     DATA.u8TH0_Tmp = (65536-T0_INIT)/256;            //计算T0高8位数据
  18.     DATA.u8TL0_Tmp = (65536-T0_INIT)%256;            //计算T0低8位数据
  19.     TH0 = DATA.u8TH0_Tmp;                            //数据装入定时器0(计数器0)数据
  20.     TL0 = DATA.u8TL0_Tmp;
  21.     set_ET0;                                    //开启定时器0中断
  22.     set_EA ;                                    //开启总中断
  23.     set_TR0;                                    //启动定时器0
  24. }
  25. /**************************************************************************
  26. Function:    TIM1_UPD_OVF_IRQHandler
  27. Description: TIM1溢出中断 10ms
  28. Input:       no
  29. Output:      no
  30. Return:      no
  31. **************************************************************************/
  32. //定时器 ms
  33. void Timer0_ISR ( void ) interrupt 1  //interrupt address is 0x000B
  34. {
  35.     //获取定时器数据
  36.     TH0 = DATA.u8TH0_Tmp;
  37.     TL0 = DATA.u8TL0_Tmp;
  38.     // 按键时间模块
  39.     All_Buttonrefresh();
  40. }
  41. /******************************************************************/
 楼主| merry_zsp 发表于 2019-10-31 09:45 | 显示全部楼层
button.h
  1. /*---------------------------------------------------------
  2.     button.h
  3.     按键控制
  4. ---------------------------------------------------------*/
  5. #ifndef _BUTTON_H_
  6. #define _BUTTON_H_
  7. /*----------------------------------------  数据初始化  ------------------------------------------*/
  8. #define button0_Num 5
  9. sbit button0 = P1^button0_Num;        // 按键
  10. #define Git_button0 button0
  11. /*----------------------------------------  数据获取部分  ------------------------------------------*/

  12. /*----------------------------------------  键盘初始化  ------------------------------------------*/
  13. void Init_button(void);
  14. void All_Buttonrefresh(void);

  15. #endif
 楼主| merry_zsp 发表于 2019-10-31 09:46 | 显示全部楼层
button.c
  1. #include <N76E003.H>
  2. #include <SFR_Macro.h>                    //N76E003 SFR寄存器设置宏定义
  3. #include <Function_define.h>            //功能定义
  4. #include "button.h"
  5. #include "data.h"

  6. /*----------------------------------------  数据宏定义  ------------------------------------------*/

  7. /*----------------------------------------  按键初始化  ------------------------------------------*/
  8. // 初始化按键
  9. void Init_button(void){
  10.     //button1
  11.     P1M1 |= (0x00 << button0_Num);        // 设置为1
  12.     P1M2 &= ~(0x01 << button0_Num);        // 设置为0
  13. }
  14. /*----------------------------------------  功能模块  ------------------------------------------*/
  15. // 获取按键
  16. void Button_Process(struct Button_data* Button,bit status){
  17.     switch(Button->Button_State_machine_mode){
  18.         case Button_status_S0:{        // 等待按键按下
  19.             if(Button_UP == status){        
  20.                 Button->Button_status = Button_UP;        // 按键状态抬起
  21.                 Button->Button_State_machine_mode = Button_status_S0;        // 无操作
  22.                 Button->Button_statusmode = Button_mode_NoOperation;        // 按键无动作
  23.                 DATA.Button0.Button_LiftTime = DATA.Button0.Button_LiftTime + 1;    // 低状态计数
  24.             }
  25.             else if(Button_DOWN == status){            // 按键按下
  26.                 Button->Button_State_machine_mode = Button_status_S1;    // 切换去抖模块   
  27.                 Button->Button_PressTime = Button_TimeDebounce;            // 设置去抖时间
  28.             }
  29.         }break;
  30.         case Button_status_S1:{        // 去抖验证
  31.             if(Button->Button_PressTime){Button->Button_PressTime = Button->Button_PressTime - 1;}    // 等待时间
  32.             else if(0 == Button->Button_PressTime){        // 去抖时间到
  33.                 if(Button_UP == status){
  34.                     Button->Button_State_machine_mode = Button_status_S0;        // 无操作
  35.                     DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
  36.                 }
  37.                 else if(Button_DOWN == status){            // 短按成立
  38.                     Button->Button_status = Button_DOWN;                    // 按键按下
  39.                     Button->Button_State_machine_mode = Button_status_S2;    // 切换等待按键松开
  40.                     Button->Button_PressTime = 0;            // 清零按下时间
  41.                 }
  42.             }
  43.         }break;
  44.         case Button_status_S2:{        // 按下时间(计算是不是长按)
  45.             if(Button_DOWN == status){        // 按键按下
  46.                 // 计时
  47.                 Button->Button_PressTime = Button->Button_PressTime + 1;    // 按键计时
  48.                 if(Button->Button_PressTime > Button_TimeEvenPressinterval){
  49.                     Button->Button_PressTime = Button_TimeEvenPressinterval;
  50.                 }
  51.             }
  52.             else if (Button_UP == status){        // 按键松开
  53.                 if(Button->Button_PressTime == Button_TimeEvenPressinterval){
  54.                     Button->Button_status = Button_UP;
  55.                     Button->Button_State_machine_mode = Button_status_S0;
  56.                     DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
  57.                     Button->Button_statusmode = Button_mode_longPress;        // 长按
  58.                 }else{
  59.                     Button->Button_State_machine_mode = Button_status_S3;        // 短按 或 双击
  60.                 }
  61.                 Button->Button_LiftTime = 0;        // 按键松开计时
  62.             }
  63.         }break;
  64.         case Button_status_S3:{        // 快安判断(判断是不是短按)
  65.             Button->Button_LiftTime = Button->Button_LiftTime + 1;    //时间记录
  66.             if(Button->Button_PressTime > Button_TimeShort_even){    // 大于快安值
  67.                 Button->Button_status = Button_UP;
  68.                 Button->Button_State_machine_mode = Button_status_S0;        // 短按
  69.                 DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
  70.                 Button->Button_statusmode = Button_mode_ShortPress;            // 短按
  71.             }else{
  72.                 if(Button_DOWN == status){    // 按键按下
  73.                     Button->Button_State_machine_mode = Button_status_S4;   // 双击去抖
  74.                     Button->Button_PressTime = Button_TimeDebounce;            // 设置去抖时间
  75.                 }
  76.             }
  77.         }break;
  78.         case Button_status_S4:{            // 双击去抖
  79.             Button->Button_LiftTime = Button->Button_LiftTime + 1;    //时间记录
  80.             if(Button->Button_PressTime){Button->Button_PressTime = Button->Button_PressTime - 1;}    // 等待时间
  81.             else if(0 == Button->Button_PressTime){        // 去抖时间到
  82.                 if(Button_UP == status){        // 去抖失败
  83.                     Button->Button_status = Button_UP;
  84.                     Button->Button_State_machine_mode = Button_status_S0;        // 短按
  85.                     DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
  86.                     Button->Button_statusmode = Button_mode_ShortPress;        // 短按
  87.                 }
  88.                 else if(Button_DOWN == status){            // 双击成立
  89.                     Button->Button_status = Button_DOWN;                    // 按键按下
  90.                     Button->Button_State_machine_mode = Button_status_S5;    // 切换等待按键松开
  91.                 }
  92.             }   
  93.         }break;
  94.         case Button_status_S5:{        // 等待快安退出
  95.             if(Button_UP == status){
  96.                 Button->Button_status = Button_UP;
  97.                 Button->Button_State_machine_mode = Button_status_S0;        // 双击
  98.                 DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
  99.                 Button->Button_statusmode = Button_mode_evenPress;            // 双击
  100.             }
  101.         }break;
  102.         default:{
  103.             Button->Button_State_machine_mode = Button_status_S0;
  104.             DATA.Button0.Button_LiftTime = 0;        // 清空按键抬起计数
  105.         }break;        // 有问题转等待按键   
  106.     }
  107.     // Button->Button_status = status;
  108. }
  109. /*---------------------------------------- 中断调用模块 ------------------------------------------*/
  110. // 批处理函数
  111. void All_Buttonrefresh(void){
  112.     Button_Process(&DATA.Button0,(bit)Git_button0);
  113. }
qcliu 发表于 2019-11-13 12:04 | 显示全部楼层
非常不错的资料
tfqi 发表于 2019-11-13 12:44 | 显示全部楼层
非常不错的资料
wiba 发表于 2019-11-13 12:53 | 显示全部楼层
非常不错的资料
zljiu 发表于 2019-11-13 13:02 | 显示全部楼层
非常感谢楼主分享
rgjinxuan 发表于 2020-3-18 11:38 | 显示全部楼层

非常感谢楼主分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

75

主题

695

帖子

2

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