c语言连发器,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
總結
以上是生活随笔為你收集整理的c语言连发器,GPIO按键的长按、短按、连发——C程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言中将变量的数值打印到.txt文件
- 下一篇: vod硬件服务器,点播视频 (VOD)