merry_zsp 发表于 2019-10-31 09:43

基于 N76E003 的按键按键状态机

  前端时间要用按键,搞了个状态机(如图):

merry_zsp 发表于 2019-10-31 09:44

main.c
#include <N76E003.H>
#include <SFR_Macro.h>                  //N76E003 SFR寄存器设置宏定义
#include <Function_define.h>            //功能定义
#include "data.h"
#include "interrupt.h"
#include "button.h"
/*--------------------------------------------------------*/
// 初始化所有
void Init_All(void){
    InitMcu();                // 初始化MCU
    Init_button();            // 键盘初始化
}
/*******************************************************************/
// 发布版本
void main(void){
    Init_All();
    while(1){
      ;
    }
}

merry_zsp 发表于 2019-10-31 09:44

data.h
/*--------------------------------------------------------------------------
data.h
--------------------------------------------------------------------------*/
#ifndef __DATA_H__
#define __DATA_H__


/*----------------------------------------------------*/
// 按键状态(状态定义)
#defineButton_DOWN                0      // 按键按下
#defineButton_UP                  1      // 按键抬起
// 按键功能模式(软件模式定义)
#defineButton_mode_NoOperation      0      // 无动作
#defineButton_mode_ShortPress            1      // 短按
#defineButton_mode_longPress            2      // 长按
#defineButton_mode_evenPress            3      // 连续快按(双击)
// 键盘消抖时间
#define Button_TimeDebounce                20/2    // 单位 ms 去抖动时间
#define Button_TimeShort_even            100/2    // 单位 ms 短按转连续按时间
#define Button_TimeEvenPressinterval    5000/2    // 单位 ms 双击判断阈值
#define Button_TimeState_reset            60000/2    // 单位 ms 60s 无动作 退出设置
// 键盘状态机模式
#defineButton_status_S0                0      // 等待按键按下
#defineButton_status_S1                1      // 去抖验证
#defineButton_status_S2                2      // 按下时间(计算是不是长按)
#defineButton_status_S3                3      // 快安判断(判断是不是短按)
#defineButton_status_S4                4      // 快安去抖
#defineButton_status_S5                5      // 等待快安退出
/*----------------------------------------------------*/
#define Unit_cycle                  32000      // 中断处理周期
/*----------------------------------------------------*/
struct Button_data{
    unsigned int Button_LiftTime;                // 抬起时间
    unsigned int Button_PressTime;                // 按下时间
    unsigned char Button_State_machine_mode:3;    // 按键状态模式(状态机)
    unsigned char Button_statusmode:2;            // 0无动作 1短按 2连发 3长按
    unsigned char Button_status:1;                // 按键的状态(按键松开,界面刷新)

};
/*------------------------ 系统时间 ----------------------------*/
struct OS_DATA{
    // 系统初始化
    unsigned char u8TH0_Tmp;                  // 中断高8位
    unsigned char u8TL0_Tmp;                  // 中断低8位
    // 键盘
    struct Button_data Button0;

};

extern struct OS_DATA DATA;
#endif

merry_zsp 发表于 2019-10-31 09:45

data.c
1 #include "data.h"
2
3 struct OS_DATA DATA;            // 系统数据

merry_zsp 发表于 2019-10-31 09:45

interrupt.h
/*--------------------------------------------------------------------------
interrupt.h
--------------------------------------------------------------------------*/

#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__

/*----------------------------------------------------*/
void InitMcu(void);
#endif

merry_zsp 发表于 2019-10-31 09:45

interrupt.c
#include <N76E003.H>
#include <SFR_Macro.h>                  //N76E003 SFR寄存器设置宏定义
#include <Function_define.h>            //功能定义
#include "data.h"
#include "interrupt.h"
#include "button.h"

/*--------------------------------------------------------*/
#define T0_INIT      Unit_cycle
#define T0_ms         500
/*--------------------------------------------------------*/
//初始化单片机
void InitMcu(void){
    TIMER0_MODE1_ENABLE;                         //定时器0的模式1
    set_T0M;                                    //设置定时器0的时钟为系统时钟
    //u8TH0_Tmp和u8TL0_Tmp 宏变量 中断可调用
    //Init_OS_Date();已经初始化
    DATA.u8TH0_Tmp = (65536-T0_INIT)/256;            //计算T0高8位数据
    DATA.u8TL0_Tmp = (65536-T0_INIT)%256;            //计算T0低8位数据
    TH0 = DATA.u8TH0_Tmp;                            //数据装入定时器0(计数器0)数据
    TL0 = DATA.u8TL0_Tmp;
    set_ET0;                                    //开启定时器0中断
    set_EA ;                                    //开启总中断
    set_TR0;                                    //启动定时器0
}
/**************************************************************************
Function:    TIM1_UPD_OVF_IRQHandler
Description: TIM1溢出中断 10ms
Input:       no
Output:      no
Return:      no
**************************************************************************/
//定时器 ms
void Timer0_ISR ( void ) interrupt 1//interrupt address is 0x000B
{
    //获取定时器数据
    TH0 = DATA.u8TH0_Tmp;
    TL0 = DATA.u8TL0_Tmp;
    // 按键时间模块
    All_Buttonrefresh();
}
/******************************************************************/

merry_zsp 发表于 2019-10-31 09:45

button.h
/*---------------------------------------------------------
    button.h
    按键控制
---------------------------------------------------------*/
#ifndef _BUTTON_H_
#define _BUTTON_H_
/*----------------------------------------数据初始化------------------------------------------*/
#define button0_Num 5
sbit button0 = P1^button0_Num;      // 按键
#define Git_button0 button0
/*----------------------------------------数据获取部分------------------------------------------*/

/*----------------------------------------键盘初始化------------------------------------------*/
void Init_button(void);
void All_Buttonrefresh(void);

#endif

merry_zsp 发表于 2019-10-31 09:46

button.c
#include <N76E003.H>
#include <SFR_Macro.h>                  //N76E003 SFR寄存器设置宏定义
#include <Function_define.h>            //功能定义
#include "button.h"
#include "data.h"

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

/*----------------------------------------按键初始化------------------------------------------*/
// 初始化按键
void Init_button(void){
    //button1
    P1M1 |= (0x00 << button0_Num);      // 设置为1
    P1M2 &= ~(0x01 << button0_Num);      // 设置为0
}
/*----------------------------------------功能模块------------------------------------------*/
// 获取按键
void Button_Process(struct Button_data* Button,bit status){
    switch(Button->Button_State_machine_mode){
      case Button_status_S0:{      // 等待按键按下
            if(Button_UP == status){      
                Button->Button_status = Button_UP;      // 按键状态抬起
                Button->Button_State_machine_mode = Button_status_S0;      // 无操作
                Button->Button_statusmode = Button_mode_NoOperation;      // 按键无动作
                DATA.Button0.Button_LiftTime = DATA.Button0.Button_LiftTime + 1;    // 低状态计数
            }
            else if(Button_DOWN == status){            // 按键按下
                Button->Button_State_machine_mode = Button_status_S1;    // 切换去抖模块   
                Button->Button_PressTime = Button_TimeDebounce;            // 设置去抖时间
            }
      }break;
      case Button_status_S1:{      // 去抖验证
            if(Button->Button_PressTime){Button->Button_PressTime = Button->Button_PressTime - 1;}    // 等待时间
            else if(0 == Button->Button_PressTime){      // 去抖时间到
                if(Button_UP == status){
                  Button->Button_State_machine_mode = Button_status_S0;      // 无操作
                  DATA.Button0.Button_LiftTime = 0;      // 清空按键抬起计数
                }
                else if(Button_DOWN == status){            // 短按成立
                  Button->Button_status = Button_DOWN;                  // 按键按下
                  Button->Button_State_machine_mode = Button_status_S2;    // 切换等待按键松开
                  Button->Button_PressTime = 0;            // 清零按下时间
                }
            }
      }break;
      case Button_status_S2:{      // 按下时间(计算是不是长按)
            if(Button_DOWN == status){      // 按键按下
                // 计时
                Button->Button_PressTime = Button->Button_PressTime + 1;    // 按键计时
                if(Button->Button_PressTime > Button_TimeEvenPressinterval){
                  Button->Button_PressTime = Button_TimeEvenPressinterval;
                }
            }
            else if (Button_UP == status){      // 按键松开
                if(Button->Button_PressTime == Button_TimeEvenPressinterval){
                  Button->Button_status = Button_UP;
                  Button->Button_State_machine_mode = Button_status_S0;
                  DATA.Button0.Button_LiftTime = 0;      // 清空按键抬起计数
                  Button->Button_statusmode = Button_mode_longPress;      // 长按
                }else{
                  Button->Button_State_machine_mode = Button_status_S3;      // 短按 或 双击
                }
                Button->Button_LiftTime = 0;      // 按键松开计时
            }
      }break;
      case Button_status_S3:{      // 快安判断(判断是不是短按)
            Button->Button_LiftTime = Button->Button_LiftTime + 1;    //时间记录
            if(Button->Button_PressTime > Button_TimeShort_even){    // 大于快安值
                Button->Button_status = Button_UP;
                Button->Button_State_machine_mode = Button_status_S0;      // 短按
                DATA.Button0.Button_LiftTime = 0;      // 清空按键抬起计数
                Button->Button_statusmode = Button_mode_ShortPress;            // 短按
            }else{
                if(Button_DOWN == status){    // 按键按下
                  Button->Button_State_machine_mode = Button_status_S4;   // 双击去抖
                  Button->Button_PressTime = Button_TimeDebounce;            // 设置去抖时间
                }
            }
      }break;
      case Button_status_S4:{            // 双击去抖
            Button->Button_LiftTime = Button->Button_LiftTime + 1;    //时间记录
            if(Button->Button_PressTime){Button->Button_PressTime = Button->Button_PressTime - 1;}    // 等待时间
            else if(0 == Button->Button_PressTime){      // 去抖时间到
                if(Button_UP == status){      // 去抖失败
                  Button->Button_status = Button_UP;
                  Button->Button_State_machine_mode = Button_status_S0;      // 短按
                  DATA.Button0.Button_LiftTime = 0;      // 清空按键抬起计数
                  Button->Button_statusmode = Button_mode_ShortPress;      // 短按
                }
                else if(Button_DOWN == status){            // 双击成立
                  Button->Button_status = Button_DOWN;                  // 按键按下
                  Button->Button_State_machine_mode = Button_status_S5;    // 切换等待按键松开
                }
            }   
      }break;
      case Button_status_S5:{      // 等待快安退出
            if(Button_UP == status){
                Button->Button_status = Button_UP;
                Button->Button_State_machine_mode = Button_status_S0;      // 双击
                DATA.Button0.Button_LiftTime = 0;      // 清空按键抬起计数
                Button->Button_statusmode = Button_mode_evenPress;            // 双击
            }
      }break;
      default:{
            Button->Button_State_machine_mode = Button_status_S0;
            DATA.Button0.Button_LiftTime = 0;      // 清空按键抬起计数
      }break;      // 有问题转等待按键   
    }
    // Button->Button_status = status;
}
/*---------------------------------------- 中断调用模块 ------------------------------------------*/
// 批处理函数
void All_Buttonrefresh(void){
    Button_Process(&DATA.Button0,(bit)Git_button0);
}

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


非常感谢楼主分享
页: [1]
查看完整版本: 基于 N76E003 的按键按键状态机