/******************************************************************************** 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; } } } }