|
看了uid:130230的狀態(tài)機(jī)按鍵掃描,感覺(jué)應(yīng)該可以實(shí)現(xiàn)我想要的功能:多按鍵檢測(cè)長(zhǎng)按,短按和連按(按下不放連加或連減),之前看到的例程多為短按和長(zhǎng)按組合,或短按和連按組合,沒(méi)有看到過(guò)長(zhǎng)按和連按如何識(shí)別,一直很糾結(jié)。
之前發(fā)過(guò)比較簡(jiǎn)單有效的狀態(tài)機(jī)按鍵檢測(cè)的例程,但那個(gè)例程里沒(méi)有加入長(zhǎng)按檢測(cè),如果哪位高手有興趣,也可以在我之前的貼子里修改,不勝感激!
http://www.zg4o1577.cn/bbs/dpj-225323-1.html
下面這個(gè)例程是uid:130230高手寫(xiě)的,原例程只有一個(gè)按鍵,現(xiàn)在我把我需要的按鍵放進(jìn)去了,還加了一些注釋?zhuān)恢览斫獾膶?duì)不對(duì)?還請(qǐng)各位大神們多多指點(diǎn),先謝謝了!
.h文件
#ifndef __key_H__
#define __key_H__
#include "xx.h"
#define PD 0x22|(P1&0x51)|(P2<<1&0x80)|(P3<<2&0x0c) //P1.0/P3.0 p3.1/P4.2 p4.3組合5個(gè)按鍵為1個(gè)字節(jié)數(shù)據(jù)
// |0101 0001 |0100 0000 |0000 0011
// 0010 0010 |0101 0001 |1000 0000 |0000 1100 1100 1101 移位后或:1111 1111 PD = 0xff;
sbit up = P2^6; //0111 1111 7f
sbit unit = P1^0; //1111 1110 fe
sbit down = P3^0; //1111 1011 fb
sbit md = P1^6; //1011 1111 bf
sbit k5 = P3^1; //1111 0111 f7
sbit k6 = P1^4; //1110 1111 ef
sbit md1 = P1^5;
//按鍵值
typedef enum
{
NONE_CLICK = 0, //無(wú)按鍵
SINGLE_CLICK , //單擊
DOUBLE_CLICK, //雙擊
LONG_PRESS, //長(zhǎng)按
LIANFA_CLICK, //連發(fā)
NUM_KEY,
}KEY_VALUE_EN;
//按鍵狀態(tài)
typedef enum
{
KEY_IDLE = 0, //空閑
KEY_FILTER, //去抖
KEY_FIRST, //第一次按下
KEY_CHECK_FREE, //抬起檢測(cè)(長(zhǎng)按)
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文件
#include "key.h"
TASK_KEY_STATU_ST gstKey1 = {0}; //任務(wù)鍵狀態(tài)
/***********************************************
功能:按鍵掃描
作者:jzb2019年12月27日
備注:50ms運(yùn)行一次這個(gè)函數(shù),理論上可以擴(kuò)展到n連擊
最大響應(yīng)延時(shí)500ms(單擊時(shí))
***********************************************/
void Task_Keyscan(void)
{
unsigned char key;
key=PD&0xFF;
switch (gstKey1.Statu)
{
case KEY_IDLE: //按鍵空閑
{
if(key!= 0xFF)
{
Switch_KeyState(KEY_FILTER);//按鍵按下了去抖
}
}
break;
case KEY_FILTER:
{
if(key!= 0xFF)
{
gstKey1.CntDly++;
if(gstKey1.CntDly >= 60)
{
gstKey1.KeyValue = LONG_PRESS;//長(zhǎng)按
Switch_KeyState(KEY_CHECK_FREE);//抬起檢測(cè)
}
}
else
{
if(gstKey1.CntDly == 0)
{
Switch_KeyState(KEY_IDLE);//如果沒(méi)有計(jì)數(shù)則證明是毛刺濾掉
}
else
{
Switch_KeyState(KEY_FIRST);//轉(zhuǎn)到第一次按下?tīng)顟B(tài)
}
}
}
break;
case KEY_FIRST:
{
if(key == 0xff)//釋放了
{
gstKey1.CntDly++;
if(gstKey1.CntDly > 10)//500ms
{
gstKey1.KeyValue = SINGLE_CLICK; //單擊
Switch_KeyState(KEY_IDLE);//回到空閑
}
}
else//按下了
{
if(gstKey1.CntDly == 0)//沒(méi)有計(jì)數(shù)證明是沒(méi)有釋放按鍵的動(dòng)作
{
}
else//這個(gè)分支里面已經(jīng)是第二次按下了
{
gstKey1.KeyValue = DOUBLE_CLICK;
Switch_KeyState(KEY_CHECK_FREE);//抬起檢測(cè)
}
}
}
break;
case KEY_CHECK_FREE:
{
if(key == 0xff)
{
Switch_KeyState(KEY_IDLE);
}
}
break;
default :
{
Switch_KeyState(KEY_IDLE);
}
break;
}
}
/****************************************************************************
功能:執(zhí)行切換狀態(tài)的動(dòng)作,同時(shí)清掉當(dāng)前狀態(tài)內(nèi)的計(jì)數(shù)
入口:要切換的狀態(tài)
作者:jzb 2019年12月27日
備注:暫時(shí)先不考慮通用的問(wèn)題,直接操作全局變量如果擴(kuò)展按鍵再說(shuō)
*****************************************************************************/
void Switch_KeyState(unsigned char state)
{
gstKey1.CntDly = 0;
gstKey1.Statu = state;
}
|
|