GPIO按键的长按、短按、连发——C程序

不借助GPIO中断,采用轮询的方式,实现按键的长按、短按、连发

 

参考:https://blog.csdn.net/qq_31151689/article/details/85228441

百度快照:http://cache.baiducontent.com/c?m=9d78d513d99603f405fa950e1a66d571695297134dc0a46468d5e35fe3654c324171e2cb30521213a3c36b6671b83958fd814765367337c799dff84ccabae27938895723061d913666c46facdc3023d567d004e6f55fa1f8b12592ddcfce8f0a0e9f44050dd1b1dd061714bd33a7522ca0e58e4f615e13b9ea3361f5526a7adf651be719aefd643941d2ad831d51c92dd0611b91a936&p=85769a479d8211a05bed9362544f97&newp=90759a46d6c416e04ea4f82d02148f231610db2151d7d31f6b82c825d7331b001c3bbfb423261403d7cf7d6604af4f5beef7307237012ba3dda5c91d9fb4c57479df68223970&user=baidu&fm=sc&query=gpio%B0%B4%BC%FC%B3%A4%B0%B4%B6%CC%B0%B4C%D3%EF%D1%D4&qid=a2d95b6400011865&p1=8

 

#include 
#include 

// 定义长按键的TICK数, 以及连发间隔的TICK数, 单位是毫秒ms
#define KEY_DEBOUNCE_PERIOD     20   // 延时消抖时间
#define KEY_LONG_PERIOD         1000
#define KEY_CONTINUE_PERIOD     200

#define TRUE    1
#define FALSE   0

typedef unsigned int Bool;

typedef enum {
    LOW = 0,
    HIGH
} KEY_LEVEL_E;

typedef enum
{
    KEY1 = 0,
    KEY2,
    KEY3,
    KEY4,
    KEY_MAX_NUM
} KEY_NUM_E;

// 定义按键返回值状态(按下,长按,连发,释放,无动作)
typedef enum {
    KEY_NULL = 0,
    KEY_DOWN,
    KEY_LONG,
    KEY_CONTINUE,
    KEY_UP
} KEY_VALUE_E;

typedef enum {
    KEY_STATE_INIT = 0,
    KEY_STATE_WOBBLE,
    KEY_STATE_PRESS,
    KEY_STATE_LONG,
    KEY_STATE_CONTINUE,
    KEY_STATE_RELEASE
} KEY_STATE_E;

typedef struct
{
    KEY_NUM_E eKeyId;
    KEY_LEVEL_E eKeyLevel;         //key level(low or high)
    unsigned int downTick;
    unsigned int upTick;
    KEY_STATE_E eKeyCurState;      //key cur state(fsm)
    KEY_STATE_E eKeyLastState;     //key last state(fsm)
    Bool bStateChangedFlag;        //state changed flag
    KEY_VALUE_E eLastKeyValue;     //key value
} KEY_HANDLE_T;

typedef void (*pf)(void);

typedef struct
{
    pf keyDownAction;
    pf keyLongAction;
    pf keyContinueAction;
    pf keyUpAction;
} KEY_FUNCTION_T;

KEY_HANDLE_T keyList[KEY_MAX_NUM] =
{
    {KEY1, LOW, 0, 0, KEY_STATE_INIT, KEY_STATE_INIT, FALSE, KEY_NULL},
    {KEY2, LOW, 0, 0, KEY_STATE_INIT, KEY_STATE_INIT, FALSE, KEY_NULL},
    {KEY3, LOW, 0, 0, KEY_STATE_INIT, KEY_STATE_INIT, FALSE, KEY_NULL},
    {KEY4, LOW, 0, 0, KEY_STATE_INIT, KEY_STATE_INIT, FALSE, KEY_NULL}
};


// 用于获取当前时间, 单位是毫秒ms
unsigned int getTime0(void)
{
    struct timespec time;

    clock_gettime(CLOCK_MONOTONIC, &time);

    return ((time.tv_sec * 1000) + (time.tv_nsec/1000000));
}

unsigned int timeDiffFromNow(unsigned int time0)
{
    unsigned int cur = 0;
    struct timespec time;

    clock_gettime(CLOCK_MONOTONIC, &time);

    cur = (time.tv_sec * 1000) + (time.tv_nsec/1000000);

    return cur - time0;
}

void keyScan(KEY_HANDLE_T* key)
{
    // gpioReadPin()需根据你的平台来写
    if(HIGH == gpioReadPin(key->eKeyId))
    {
        // 根据原理图, HIGH代表松开
        key->eKeyLevel = HIGH;
    }
    else
    {
        // 根据原理图, LOW代表按下
        key->eKeyLevel = LOW;
    }

    // 获取当前key是按下还是松开
    KEY_LEVEL_E level = key->eKeyLevel;

    key->eLastKeyValue = KEY_NULL;

    switch(key->eKeyCurState)
    {
        case KEY_STATE_INIT:
            if(LOW == level)
            {
                key->downTick = getTime0();

                key->bStateChangedFlag = TRUE;
                key->eKeyCurState = KEY_STATE_WOBBLE;
            }
            break;

        case KEY_STATE_WOBBLE:
            if(LOW == level)
            {
                if(timeDiffFromNow(key->downTick) >= KEY_DEBOUNCE_PERIOD)
                {
                    key->bStateChangedFlag = TRUE;
                    key->eKeyCurState = KEY_STATE_PRESS;
                }
            }
            else
            {
                key->bStateChangedFlag = TRUE;
                key->eKeyCurState = KEY_STATE_INIT;
            }
            break;

        case KEY_STATE_PRESS:
            if(TRUE == key->bStateChangedFlag)
            {
                key->bStateChangedFlag = FALSE;
                key->eLastKeyValue = KEY_DOWN;
            }

            if(LOW == level)
            {
                if(timeDiffFromNow(key->downTick) >= KEY_LONG_PERIOD)
                {
                    key->bStateChangedFlag = TRUE;
                    key->eKeyCurState = KEY_STATE_LONG;
                }
            }
            else
            {
                key->upTick = getTime0();

                key->bStateChangedFlag = TRUE;
                key->eKeyCurState = KEY_STATE_RELEASE;
            }
            break;

        case KEY_STATE_LONG:
            if(TRUE == key->bStateChangedFlag)
            {
                key->bStateChangedFlag = FALSE;
                key->eLastKeyValue = KEY_LONG;
            }

            if(LOW == level)
            {
                if(timeDiffFromNow(key->downTick) >= (KEY_LONG_PERIOD + KEY_CONTINUE_PERIOD))
                {
                    key->downTick = getTime0();

                    key->bStateChangedFlag = TRUE;
                    key->eKeyCurState = KEY_STATE_CONTINUE;
                }
            }
            else
            {
                key->upTick = getTime0();

                key->bStateChangedFlag = TRUE;
                key->eKeyCurState = KEY_STATE_RELEASE;
            }
            break;

        case KEY_STATE_CONTINUE:
            if(TRUE == key->bStateChangedFlag)
            {
                key->bStateChangedFlag = FALSE;
                key->eLastKeyValue = KEY_CONTINUE;
            }

            if(LOW == level)
            {
                if(timeDiffFromNow(key->downTick) >= KEY_CONTINUE_PERIOD)
                {
                    key->downTick = getTime0();

                    key->bStateChangedFlag = TRUE;
                    key->eKeyCurState = KEY_STATE_CONTINUE;
                }
            }
            else
            {
                key->upTick = getTime0();

                key->bStateChangedFlag = TRUE;
                key->eKeyCurState = KEY_STATE_RELEASE;
            }
            break;

        case KEY_STATE_RELEASE:
            if(timeDiffFromNow(key->upTick) >= KEY_DEBOUNCE_PERIOD) // 松开按键也来个消抖
            {
                if(TRUE == key->bStateChangedFlag)
                {
                    key->bStateChangedFlag = FALSE;
                    key->eLastKeyValue = KEY_UP;
                }

                key->bStateChangedFlag = TRUE;
                key->eKeyCurState = KEY_STATE_INIT;
            }
            else
            {
                if(LOW == level)
                {
                    key->eKeyCurState = key->eKeyLastState;
                }
            }
            break;

        default:
            break;
    }

    key->eKeyLastState = key->eKeyCurState;
}

void key1DownAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key1LongAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key1ContinueAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key1UpAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key2DownAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key2LongAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key2ContinueAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key2UpAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key3DownAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key3LongAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key3ContinueAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key3UpAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key4DownAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key4LongAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key4ContinueAction(void)
{
    printf("%s\n", __FUNCTION__);
}

void key4UpAction(void)
{
    printf("%s\n", __FUNCTION__);
}

KEY_FUNCTION_T keyMapList[KEY_MAX_NUM] =
{
    {key1DownAction, key1LongAction, key1ContinueAction, key1UpAction}, //KEY1
    {key2DownAction, key2LongAction, key2ContinueAction, key2UpAction}, //KEY2
    {key3DownAction, key3LongAction, key3ContinueAction, key3UpAction}, //KEY3
    {key4DownAction, key4LongAction, key4ContinueAction, key4UpAction}, //KEY4
};

void keyMapHandle(KEY_HANDLE_T *key, KEY_FUNCTION_T *keyMap)
{
    unsigned char keyValue = key->eLastKeyValue;

    if(KEY_NULL == keyValue)
    {
        return;
    }
    else
    {
        switch(keyValue)
        {
            case KEY_DOWN:
                if(keyMap->keyDownAction != NULL)
                {
                    keyMap->keyDownAction();
                }
                break;

            case KEY_LONG:
                if(keyMap->keyLongAction != NULL)
                {
                    keyMap->keyLongAction();
                }
                break;

            case KEY_CONTINUE:
                if(keyMap->keyContinueAction != NULL)
                {
                    keyMap->keyContinueAction();
                }
                break;

            case KEY_UP:
                if(keyMap->keyUpAction != NULL)
                {
                    keyMap->keyUpAction();
                }
                break;

            default:
                break;
        }
    }
}

int main(void)
{
    KEY_NUM_E keyId = KEY_MAX_NUM;

    while(1)
    {
        for(keyId=KEY1; keyId

 

你可能感兴趣的:(linux,c语言,嵌入式)