126 lines
4.6 KiB
C
126 lines
4.6 KiB
C
/********************************************************************************
|
||
Copyright (C), Sinowealth Electronic. Ltd.
|
||
Author: Sino
|
||
Version: V0.0
|
||
Date: 2020/04/26
|
||
History:
|
||
V2.0 2020/04/26 Preliminary
|
||
********************************************************************************/
|
||
#include "Main.h"
|
||
|
||
|
||
BOOL bKeyFlg;
|
||
U16 data uiKeyValidCnt;
|
||
U16 data uiKeyInvalidCnt;
|
||
U8 data ucKeyValue;
|
||
U8 data ucKeyOldValue;
|
||
U8 data ucKeyValueBK;
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: ScanKey
|
||
* 参 数: 无
|
||
* 返回值: 无
|
||
* 描 述: 1. 短按时,按键必须弹起后,才能识别为短按按键。
|
||
2. 长按和长按持续,按键无需弹起,就能识别为长按按键或长按持续。
|
||
3. 按键有优先级,多个按键被同时按下时,仅处理第一个被按下的按键。
|
||
4.同一个按键一直被按着,先触发长按,后触发长按持续,长按和长按持续都会被触发。
|
||
5. bKeyFlg:当检测到有效按键后,置位1
|
||
6. ucKeyValue:高4bit表示按键状态(短按、长按、长按继续、长按结束);低4bit表示键值
|
||
7. ucKeyValueBK 保存按键状态:无按键、有按键1、有按键2
|
||
8. uiKeyValidCnt 按键按下滤波计数器
|
||
9. uiKeyInvalidCnt 按键弹起滤波计数器
|
||
*************************************************************************************************/
|
||
void KeyScan(void)
|
||
{
|
||
if(!bKeyFlg)
|
||
{
|
||
ucKeyValueBK = KEYVAL_NULL; //先默认无按键按下
|
||
|
||
#ifdef KEY_NUM1_DEF //1个按键
|
||
if(!KEY_1_IO_RD)
|
||
{
|
||
ucKeyValueBK = KEYVAL_1;
|
||
}
|
||
#endif
|
||
#ifdef KEY_NUM2_DEF //2个按键
|
||
if(!KEY_1_IO_RD)
|
||
{
|
||
ucKeyValueBK = KEYVAL_1; //按键按下后,获取新键值
|
||
}
|
||
else if(!KEY_2_IO_RD)
|
||
{
|
||
ucKeyValueBK = KEYVAL_2; //按键按下后,获取新键值
|
||
}
|
||
#endif
|
||
#ifdef KEY_NUM3_DEF //3个按键
|
||
if(!KEY_1_IO_RD)
|
||
{
|
||
ucKeyValueBK = KEYVAL_1;
|
||
}
|
||
else if(!KEY_2_IO_RD)
|
||
{
|
||
ucKeyValueBK = KEYVAL_2;
|
||
}
|
||
else if(!KEY_3_IO_RD)
|
||
{
|
||
ucKeyValueBK = KEYVAL_3;
|
||
}
|
||
#endif
|
||
if(ucKeyValueBK != ucKeyOldValue) //ucKeyValueBK中存放了新的键值,如果新键值跟老键值不同,
|
||
{
|
||
uiKeyInvalidCnt++; //按键弹起滤波计数器,当按键第一次按下时会清0,当按键弹起时会一直计数
|
||
if(uiKeyValidCnt >= KEY_S_TIME) //按键按下滤波计数器,当按键被按下后一直计数,按键弹起后停止计数
|
||
{ //按下又弹起且未触发长按时,如果uiKeyValidCnt >= KEY_S_TIME,则可能是短按
|
||
if(uiKeyInvalidCnt >= KEY_S_TIME) //按键弹起滤波计数器达到短按消抖时间,则认为是一次按下和弹起都消抖过的有效按键
|
||
{
|
||
if(uiKeyValidCnt >= KEY_L_TIME) //在此区分是短按,还是长按结束
|
||
{
|
||
ucKeyValue = ucKeyOldValue | KEY_STATE_LE; //按下的时间超过长按时间,认为是长按已经结束了。该状态目前未使用
|
||
}
|
||
else
|
||
{
|
||
ucKeyValue = ucKeyOldValue | KEY_STATE_S; //按下的时间没有超过长按时间,认为是一次有效的短按按键
|
||
}
|
||
bKeyFlg = 1; //短按有效,暂停按键检测,去处理按键事件
|
||
goto scanend;
|
||
}
|
||
// else
|
||
// {
|
||
// uiKeyValidCnt++; //该行应该删掉,否则当KEY_S_TIME等于KEY_L_TIME的一半及以上时,会把短按误识别为长按结束。
|
||
// }
|
||
}
|
||
else //每当按键按下的时间连短按消抖时间都不够时,认为是无效按键,重新初始化
|
||
{
|
||
goto scanend;
|
||
}
|
||
}
|
||
else //ucKeyValueBK中存放了新的键值,新键值跟老键值相同,说明是同一个按键。
|
||
{
|
||
if(ucKeyValueBK != KEYVAL_NULL) //继续处理被按下的按键
|
||
{
|
||
uiKeyInvalidCnt = 0; //清弹起计数器
|
||
uiKeyValidCnt++; //累加按下计数器
|
||
if(uiKeyValidCnt == KEY_L_TIME) //当按下时间达到长按滤波时间时,认为此按键为长按键
|
||
{
|
||
ucKeyValue = ucKeyOldValue | KEY_STATE_L;
|
||
bKeyFlg = 1;
|
||
}
|
||
else if(uiKeyValidCnt == KEY_LC_TIME) //当按下时间达到长按持续滤波时间时,认为此按键为长按持续
|
||
{
|
||
uiKeyValidCnt = KEY_L_TIME;
|
||
ucKeyValue = ucKeyOldValue | KEY_STATE_LC;
|
||
bKeyFlg = 1;
|
||
}
|
||
}
|
||
else //新键值是空键值,说明全部按键都释放了
|
||
{
|
||
ucKeyValue = KEYVAL_NULL; //全部按键都释放了,需要重新初始化检测寄存器
|
||
scanend:
|
||
uiKeyValidCnt = 0;
|
||
uiKeyInvalidCnt = 0;
|
||
ucKeyOldValue = ucKeyValueBK;
|
||
}
|
||
}
|
||
}
|
||
}
|