《经典按键程序.doc》由会员分享,可在线阅读,更多相关《经典按键程序.doc(6页珍藏版)》请在金锄头文库上搜索。
1、经典按键程序.txt蜜蜂整日忙碌,受到赞扬;蚊子不停奔波,人见人打。多么忙不重要,为什么忙才重要。项目里经常处理按键消抖, 本来这个消抖的过程是与具体按下的键无关的, 可以前的代码总是在消抖的同时处理具体的按键值, 再加上长按 短按 组合键混在一起, 成一锅粥. 最近在一个项目中痛下决心, 想弄个通用版本的, 这样下个项目只要将文件包含一下, 处理具体按键值就可以了, 不必再关心消抖部分的代码了. 另外还发现, 这样做可以同时做出几套不同的按键处理方式. 思路是: 按照面向过程的编程方式, 将数据与过程分离. 把和按键状态相关的东西统统塞到结构里, 把消抖的代码放在一个函数中. /key.h
2、头文件- #ifndef _KEY_H #define _KEY_H #define _KEY_NONE 0 #define _HAS_NO_KEY 0 #define _HAS_KEY_DOWN 1 #define _HAS_KEY_SURE 2 #define _HAS_KEY_WAITUP 3 #define _REENTER 1 #define _NO_REENTER 2 typedef struct WORD PreDownKey; /上次检测到的键 BYTE KeyState; /状态 WORD SameKeyCntr; /同一键检测到按下的次数 WORD CurKey; /当前检
3、测到的键, 用于处理长按的情况 BYTE (*KeyDownCallBack)(WORD, WORD); /键确认按下的回调函数指针 void (*KeyUpCallBack)(WORD); /键抬起的回调函数指针 struct_KeyInfo; void DitherlessKey(struct_KeyInfo* pInfo); /消抖的处理函数 #endif/_KEY_H /消抖动的代码- #include Key.h /定时消抖的按键处理函数, 通常在定时中断中调用, void DitherlessKey(struct_KeyInfo* pInfo) switch(pInfo-KeySt
4、ate) case _HAS_NO_KEY: pInfo-SameKeyCntr = 0; if(pInfo-CurKey != _KEY_NONE) pInfo-KeyState = _HAS_KEY_DOWN; /进入有键按下状态 break; case _HAS_KEY_DOWN: if(pInfo-PreDownKey = pInfo-CurKey) pInfo-KeyState = _HAS_KEY_SURE; /确认键已按下状态 else pInfo-KeyState = _HAS_NO_KEY; /回到无键状态 break; case _HAS_KEY_SURE: if(pInf
5、o-CurKey = pInfo-PreDownKey) pInfo-KeyState = _HAS_KEY_WAITUP; if(pInfo-KeyDownCallBack) /这里回调函数的返回值决定了是否允许出现长按的情况 if(_REENTER = pInfo-KeyDownCallBack(pInfo-CurKey, pInfo-SameKeyCntr) pInfo-KeyState = _HAS_KEY_SURE; +pInfo-SameKeyCntr; else pInfo-KeyState = _KEY_NONE; break; case _HAS_KEY_WAITUP: if
6、(pInfo-CurKey != pInfo-PreDownKey) pInfo-KeyState = _HAS_NO_KEY; if(pInfo-KeyUpCallBack) pInfo-KeyUpCallBack(pInfo-PreDownKey); break; default: break; pInfo-PreDownKey = pInfo-CurKey; /保存上次按键值 return; /应用代码片段- . /声明按键回调函数 BYTE KeyDownCallBack(WORD Key, WORD Times); BYTE KeyDownCallBack2(WORD Key, WO
7、RD Times); /按键处理数据结构 static struct_KeyInfo g_KeyInfo1 = 0, 0, 0, 0, KeyDownCallBack; static struct_KeyInfo g_KeyInfo2 = 0, 0, 0, 0, KeyDownCallBack2; / /TIMER2 initialize - prescale:1024 / WGM: Normal / desired value: 100Hz / actual value: 101.024Hz (1.0%) #pragma interrupt_handler timer2_ovf_isr:iv
8、_TIM2_OVF void timer2_ovf_isr(void) WORD temp; _TIMER2_LOAD; /reload counter value temp = Read165() _KEY_MASK; /输入信息 g_KeyInfo1.CurKey = temp & 0x00FF; DitherlessKey(&g_KeyInfo1); g_KeyInfo2.CurKey = temp & 0xFF00; /同一个消抖函数处理不同的按键 DitherlessKey(&g_KeyInfo2); /在回调函数中处理具体的键值 BYTE KeyDownCallBack(WORD
9、Key, WORD Times) switch(Key) case _KEY_F2: if(Times 200) /长按 2s return _REENTER; /2s内允许长按 break; case _KEY_CLR_CNTR: if(Times 1000) /四个键长按10s return _REENTER; /允许长按 default: break; g_DownKey = Key; /输出按键信息, 给主循环处理. 这个回调函数是由定时中断中的代码调用的. return _NO_REENTER; /其余键, 不允许长按 BYTE KeyDownCallBack2(WORD Key, WORD Times) switch(Key) case _KEY_I: if(Times = 20) /数值 x 10 ms g_DownKey |= _KEY_I; else if(Times = 300) /长按3s时执行一个动作, 只会执行一次 g_I+; break; default: