1. 程式人生 > >新型按鍵掃描程式改良

新型按鍵掃描程式改良

硬體基礎

四個獨立按鍵

邏輯圖

說明:與bsp_key.c 的程式碼有一點出入

Created with Raphaël 2.1.2開始KEYx_TRIGER?記錄鍵值KEYx_CONTINE?計數器減數是否有鍵值?計數器減為0?如果有鍵值為長按結束如果有鍵值為短按yesnoyesnoyesnoyesno

程式

bsp_key.h

/**
*****************************************************************************
* @文  件: bsp_key.h 
* @作  者: 00Jackey
* @版  本: V1.0.0
* @日  期: 8-May-2018
* @描  述: 按鍵處理驅動介面檔案
******************************************************************************
* @修改記錄:
*   2018/05/08:初始版本
*    
*
******************************************************************************
**/
#ifndef _BSP_KEY_H_ #define _BSP_KEY_H_ #ifdef _cplusplus extern "C" { #endif //C庫 #include <stdint.h> //巨集定義 #define KEYDOWN_LONG_TIME 100 //以每20ms呼叫一次。 二秒鐘種為按鍵長按 //定義列舉 typedef enum { KEY0_TRIGER = 0, KEY1_TRIGER = 1, KEY2_TRIGER = 2, KEY3_TRIGER = 3, KEY0_CLICKED = 10, KEY1_CLICKED = 11
, KEY2_CLICKED = 12, KEY3_CLICKED = 13, KEY0_LONG_PRES = 20, KEY1_LONG_PRES = 21, KEY2_LONG_PRES = 22, KEY3_LONG_PRES = 23, KEY_NONE = 255 }KEY_VALUE_ENUM; //定義結構體 typedef struct{ uint16_t Triger; uint16_t Continue; KEY_VALUE_ENUM KeyValue; }KEY_STATE_STRUCT; //介面函式 void Key_init(void
); KEY_VALUE_ENUM Key_getValue(void); void Key_put(KEY_VALUE_ENUM cKeyVal); KEY_VALUE_ENUM Key_get(void); //外部引用 extern KEY_STATE_STRUCT KeyStateStruct; #ifdef _cplusplus } #endif #endif

bsp_key.c

/**
*****************************************************************************
* @文  件: bsp_key.c 
* @作  者: 00Jackey
* @版  本: V1.0.0
* @日  期: 20-July-2018
* @描  述: 按鍵處理驅動
******************************************************************************
* @修改記錄:
*   2018/07/20:初始版本
*   2018/07/23:增加短按、長按、觸發
*
******************************************************************************
**/

//按鍵標頭檔案
#include "bsp_key.h"

//硬體驅動
#include "hardware.h"

//巨集定義
#define KEY0        0x01
#define KEY1        0x02
#define KEY2        0x04
#define KEY3        0x08


//全域性變數
KEY_STATE_STRUCT KeyStateStruct = {
    .Triger = 0,
    .Continue = 0,
    .KeyValue = KEY_NONE,
};



/*
******************************************************************************
*   函 數 名: Key_init
*   功能說明: 按鍵IO初始化, 按下為低電平 釋放為高電平
*   形    參: 無
*   返 回 值: 無
******************************************************************************
*/
void Key_init(void)
{

    GPIO_InitTypeDef gpioInitStructure;

    gpioInitStructure.GPIO_Mode = GPIO_Mode_IPU;
    gpioInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    gpioInitStructure.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;

    GPIO_Init(GPIOC, &gpioInitStructure);

}

/*
******************************************************************************
*   函 數 名: Key_parse
*   功能說明: 鍵值解析,觸發、短按、長按
*   形    參: 無
*   返 回 值: 鍵值
******************************************************************************
*/
#define JUDGE_KEY_VALUE(A,X,Y,Z)\
    if(KeyStateStruct.Continue & A){\
        if(sKeyDownLastTime > 0){\
            sKeyDownLastTime -= 1;\
        }else{\
            sKeyValue = Z;\
            sKeyDownLastTime = KEYDOWN_LONG_TIME;\
        }\
    }else{\
        if(sKeyDownLastTime != KEYDOWN_LONG_TIME){\
            if(sKeyValue == X){\
                sKeyValue = Y;\
            }\
        }\
    }\

KEY_VALUE_ENUM Key_parse(void)
{
    static KEY_VALUE_ENUM sKeyValue = KEY_NONE;
    static int32_t sKeyDownLastTime = KEYDOWN_LONG_TIME;

    KEY_VALUE_ENUM rKeyValue = KEY_NONE;

    if(KeyStateStruct.Triger & KEY0){
        sKeyValue = KEY0_TRIGER;
    }

    if(KeyStateStruct.Continue & KEY0){    
        if(sKeyDownLastTime > 0){
            sKeyDownLastTime -= 1;
        }else{
            sKeyValue = KEY0_LONG_PRES;
            sKeyDownLastTime = KEYDOWN_LONG_TIME;
        }
    }else{
        if(sKeyDownLastTime != KEYDOWN_LONG_TIME){
            if(sKeyValue == KEY0_TRIGER){
                sKeyValue = KEY0_CLICKED;
            }
        }
    }

    if(KeyStateStruct.Triger & KEY1){
        sKeyValue = KEY1_TRIGER;
    }

    JUDGE_KEY_VALUE(KEY1,KEY1_TRIGER,KEY1_CLICKED,KEY1_LONG_PRES);

    if(KeyStateStruct.Triger & KEY2){
        sKeyValue = KEY2_TRIGER;
    }

    JUDGE_KEY_VALUE(KEY2,KEY2_TRIGER,KEY2_CLICKED,KEY2_LONG_PRES);

    if(KeyStateStruct.Triger & KEY3){
        sKeyValue = KEY3_TRIGER;
    }

    JUDGE_KEY_VALUE(KEY3,KEY3_TRIGER,KEY3_CLICKED,KEY3_LONG_PRES);

    rKeyValue = sKeyValue;                                                          //負值需要返回的鍵值

    if(((KeyStateStruct.Continue & 0x000F) == 0)&&(KeyStateStruct.Triger == 0)){    //按鍵釋放長按計算還原
        sKeyDownLastTime = KEYDOWN_LONG_TIME;
        sKeyValue = KEY_NONE;  
    }

    return rKeyValue;
}

/*
******************************************************************************
*   函 數 名: Key_loopRead
*   功能說明: 按鍵電平掃描
*   形    參: 無
*   返 回 值: 無
******************************************************************************
*/
void Key_loopRead(void)
{
    uint16_t ReadData = ~((GPIOC->IDR) & 0x000F);
    KeyStateStruct.Triger = ReadData & (ReadData ^ KeyStateStruct.Continue);
    KeyStateStruct.Continue = ReadData;
}

/*
******************************************************************************
*   函 數 名: Key_getValue
*   功能說明: 按鍵電平掃描
*   形    參: 無
*   返 回 值: 鍵值
******************************************************************************
*/
KEY_VALUE_ENUM Key_getValue(void)
{
    Key_loopRead();

    return Key_parse();
}

/*
******************************************************************************
*   函 數 名: Key_put
*   功能說明: 配置按鍵全域性變數
*   形    參: 無
*   返 回 值: 鍵值
******************************************************************************
*/
void Key_put(KEY_VALUE_ENUM cKeyVal)
{
    KeyStateStruct.KeyValue = cKeyVal;
}

/*
******************************************************************************
*   函 數 名: Key_get
*   功能說明: 獲取按鍵全域性變數
*   形    參: 無
*   返 回 值: 鍵值
******************************************************************************
*/
KEY_VALUE_ENUM Key_get(void)
{
    KEY_VALUE_ENUM  rValue;
    rValue = KeyStateStruct.KeyValue;
    KeyStateStruct.KeyValue = KEY_NONE;
    return rValue;
}

應用

/** 
  * @name   void UserInterface_menuRefresh (void)
  * @brief  選單更新函式
  * @param  none
  * @retval none
  */
void UserInterface_loop (void)
{
    KEY_VALUE_ENUM tKeyValue;

    tKeyValue = Key_get();
    if(tKeyValue != KEY_NONE)
        KeyCodeAction(tKeyValue);

    Delay_mSec(PAGE_REFRESH_TIME);
}