標題: 再來一個原創(chuàng)單片機按鍵狀態(tài)機程序:單擊雙擊長按(帶抬起檢測) [打印本頁]

作者: jizhongbiao    時間: 2019-12-27 15:16
標題: 再來一個原創(chuàng)單片機按鍵狀態(tài)機程序:單擊雙擊長按(帶抬起檢測)
//頭文件(.h)
#ifndef  __KEY__
#define  __KEY__

#define DEBUG_KEY //key文件的調(diào)試開關

sbit KEY1 = P1^0;
#define KEY_DOWN             0
#define KEY_UP         1

//按鍵值
typedef enum
{
        NONE_CLICK = 0,
        SINGLE_CLICK ,
        DOUBLE_CLICK,
        LONG_PRESS,
        NUM_KEY,
}KEY_VALUE_EN;

typedef enum
{
        KEY_IDLE = 0,
        KEY_FILTER,
        KEY_FIRST,                //第一次按下
        KEY_CHECK_FREE,//抬起檢測(長按)
        NUM_KEY_STAUS,
}KEY_STATUS_EN;


//按鍵掃描狀態(tài)
typedef struct
{
        unsigned char Statu;
        unsigned char CntDly;
        unsigned char KeyValue;

}TASK_KEY_STATU_ST;
void Task_Keyscan(void);
void Switch_KeyState(unsigned char state);

#endif

//.C文件
/****************************************
版權:微信:mcu6666
PS:承接單片機開發(fā)項目
*****************************************/
#include "..\Public\CH554.H"                                                         
#include "..\Public\Debug.H"
#include "key.h"
#include "UART1.H"

TASK_KEY_STATU_ST gstKey1 = {0};


/***********************************************
功能:按鍵掃描
作者:jzb2019年12月27日
備注:50ms運行一次這個函數(shù),理論上可以擴展到n連擊
        最大響應延時500ms(單擊時)
***********************************************/
void Task_Keyscan(void)
{
        switch (gstKey1.Statu)
                {
                        case KEY_IDLE:
                                {
                                        if(KEY1 == KEY_DOWN)
                                                {
                                                        Switch_KeyState(KEY_FILTER);//按鍵按下了去抖
                                                }
                                }
                        break;
                        case KEY_FILTER:
                                {
                                        if(KEY1 == KEY_DOWN)
                                                {
                                                        gstKey1.CntDly++;
                                                        if(gstKey1.CntDly >= 60)
                                                                {
                                                                        gstKey1.KeyValue = LONG_PRESS;//長按
                                                                        #ifdef DEBUG_KEY
                                                                        UART1_SendString("LONG_PRESS\n");
                                                                        #endif
                                                                        Switch_KeyState(KEY_CHECK_FREE);//抬起檢測
                                                                }
                                                }
                                        else
                                                {
                                                        if(gstKey1.CntDly == 0)
                                                                {
                                                                        Switch_KeyState(KEY_IDLE);//如果沒有計數(shù)則證明是毛刺濾掉
                                                                }
                                                        else
                                                                {
                                                                        Switch_KeyState(KEY_FIRST);//轉(zhuǎn)到第一次按下狀態(tài)
                                                                }
                                                }
                                }
                        break;
                        case KEY_FIRST:
                                {
                                        if(KEY1 == KEY_UP)//釋放了
                                                {        
                                                        gstKey1.CntDly++;
                                                        if(gstKey1.CntDly > 10)//500ms
                                                                {
                                                                        gstKey1.KeyValue = SINGLE_CLICK;
                                                                        #ifdef DEBUG_KEY
                                                                        UART1_SendString("SINGLE\n");
                                                                        #endif
                                                                        Switch_KeyState(KEY_IDLE);//回到空閑
                                                                }
                                                }
                                        else//按下了
                                                {
                                                        if(gstKey1.CntDly == 0)//沒有計數(shù)證明是沒有釋放按鍵的動作
                                                                {

                                                                }
                                                        else//這個分支里面已經(jīng)是第二次按下了
                                                                {
                                                                        gstKey1.KeyValue = DOUBLE_CLICK;
                                                                        #ifdef DEBUG_KEY
                                                                        UART1_SendString("DOUBLE\n");
                                                                        #endif
                                                                        Switch_KeyState(KEY_CHECK_FREE);//抬起檢測
                                                                }
                                                }
                                }
                        break;
                        case KEY_CHECK_FREE:
                                {
                                        if(KEY1 == KEY_UP)
                                                {        
                                                        Switch_KeyState(KEY_IDLE);
                                                }
                                }
                        break;
                    default :
                                  {
                                        Switch_KeyState(KEY_IDLE);
                                  }
                        break;        
                }
}

/****************************************************************************
功能:執(zhí)行切換狀態(tài)的動作,同時清掉當前狀態(tài)內(nèi)的計數(shù)
入口:要切換的狀態(tài)
作者:jzb 2019年12月27日
備注:暫時先不考慮通用的問題,直接操作全局變量如果擴展按鍵再說
*****************************************************************************/
void Switch_KeyState(unsigned char state)
{
        gstKey1.CntDly = 0;
        gstKey1.Statu = state;
}


作者: 綠眼睛3    時間: 2024-4-26 21:34
Debug.H沒放出來




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1