/*********************************Copyright (c)***************************** ** ** 飞鹏电子工作室 ** 嵌入式项目 ** http://xpstudio2003.blog.163.com ** **项目名称: **编译环境: **-------------------------------------------------------------------------- **文 件 名: key.c **作 者: 曹香鹏 **创建日期: 2008年 **-------------------------------------------------------------------------- **维护记录: **文件说明: ** 首先按键有四个,单线接入,没有用矩阵. ** 按键使用状态机,四个状态 ** ** 按键返回码: 按键属性|按键值 (或操作) ** 属性包括:KEY_DOWN, KEY_UP, 长按键返回, 连发返回 ** 按键值 就是按键返回的值. ** ** 高四位表示属性,,低四位表示按键值. ** ** 曹香鹏,XPSTUDIO2009 ****************************************************************************/ #include "..\xpHFL.h" #include "key.h" /*********************************************************************** * 函数名称: GetKeyCode() * 函数功能: 获得按键物理编码 * 作 者: 曹香鹏,XPSTUDIO2008 ************************************************************************/ #define KEYPIN1 (PINA&(1<<3)) #define KEYPIN2 (PINA&(1<<2)) #define KEYPIN3 (PINA&(1<<1)) #define KEYPIN4 (PINA&(1<<0)) static INT8U GetKeyCode(void) { if(KEYPIN1==0) return 1; if(KEYPIN2==0) return 2; if(KEYPIN3==0) return 3; if(KEYPIN4==0) return 4; return 0; } //------------------------------------------------------------------------------- //以下为按键部分配置宏定义, #define KEY_DOUBLE_ENABLE 0 //为1 启用按键双击模式. //------------------------------------------------------------------------------- //以下为按键实现函数,请勿改动! /*********************************************************************** * 函数名称: INT8U GetKey() * 函数功能: 获得按键码 * 说 明: 使用状态机的方法来处理按键 * 支持部分按键连发 * 作 者: 曹香鹏,XPSTUDIO2008 ************************************************************************/ INT8U GetKey(void) { static INT8U KeyState = 0; //按键状态,状态机使用. static INT8U KeyPrev = 0; //保存上一次按键,防止出现乱码现象. static INT8U KeyHoldDly = 0; //按键连发时间 static BOOL bKeyBurst = FALSE; //标志连发开始 #if KEY_DOUBLE_ENABLE == 1 static INT8U KeyDbleTmp; //处理按键双击事件. static INT8U KeyDbleDly = 0; //按键双击间隔时间 #endif INT8U KeyPress = NO_KEY; //按键值 INT8U KeyReturn = NO_KEY; //按键返回值 KeyPress = GetKeyCode(); #if KEY_DOUBLE_ENABLE == 1 if(KeyDbleDly>0) {//处理双击按键的. KeyDbleDly --; if(KeyDbleDly ==0) KeyDbleTmp= NO_KEY; } #endif switch(KeyState) { //按键初始态00 case 0: if( KeyPress !=NO_KEY ) { KeyState = 1; KeyPrev = KeyPress; } break; //按键确认态01 case 1: if( KeyPress !=NO_KEY ) { //与上次按键不同,是乱码 if(KeyPrev != KeyPress) { KeyState = 0; } else { //双击处理在按键按下之前. #if KEY_DOUBLE_ENABLE == 1 if(KeyPress == KeyDbleTmp) { KeyReturn = KEY_DOUBLE | KeyPress; KeyDbleTmp = NO_KEY; KeyDbleDly = 0; break; } #endif //以下为按键按下处理 KeyState = 2; KeyReturn = KEY_DOWN | KeyPress; //返回按键按下键值 //保存上次按键按下的键,处理双击用. #if KEY_DOUBLE_ENABLE == 1 KeyDbleTmp = KeyPress; KeyDbleDly = KEY_DOUBLE_SPACE; #endif } } else {//按键抬起,是抖动,不响应按键 KeyState = 0; } break; //按键连续态11 case 2: if( KeyPress !=NO_KEY ) {//这个地方也可以添加 (KeyPress == KEY_1) || (KeyPress == KEY_2) //这样可以对产生连发的按键进行限制 KeyHoldDly++; if( (bKeyBurst ==TRUE) && (KeyHoldDly>KEY_BURST_SPACE) ) { KeyHoldDly = 0; KeyReturn = KEY_BURST | KeyPress; //返回连发的值 KeyPrev = KeyPress; //记住上次的按键. break; } if(KeyHoldDly>KEY_BURST_FIRST) { bKeyBurst = TRUE; KeyHoldDly = 0; KeyReturn = KEY_HOLD | KeyPress; //返回长按后的值 break; } } //按键释放态10 case 3: if(KeyPress == NO_KEY ) { KeyState = 0; KeyHoldDly = 0; bKeyBurst = FALSE; KeyReturn = KEY_UP | KeyPrev; //返回按键抬起值 } break; default :break; } return KeyReturn; }