📄 rd_usekey._c
字号:
/***********************************************************
* 函数库说明:按键处理函数库 *
* 版本: v2.00 *
* 作者: 傻孩子 *
* 创建日期: 2005年11月27日 *
* -------------------------------------------------------- *
* [支 持 库] *
* 支持库名称:RD_MacroAndConst.h *
* 需要版本: v0.01 &abv *
* 支持库说明:系统常用宏定义库 *
* *
* 支持库名称:RD_UseKey.h *
* 需要版本: ---- *
* 支持库说明:按键处理声明库 *
* -------------------------------------------------------- *
* [版本更新] *
* 修改: 傻孩子 *
* 修改日期: 2006年4月15日 *
* 版本: v1.3 *
* *
* 修改: 傻孩子 *
* 修改日期: 2006年4月23日 *
* 版本: v1.31 *
* *
* 修改: 傻孩子 *
* 修改日期: 2006年5月5日 *
* 版本: v1.32 *
* *
* 修改: 王卓然 *
* 修改日期: 2007年2月25日 *
* 版本: v2.00 *
* -------------------------------------------------------- *
* [版本历史] *
* v1.3以下 1、提供了对键盘缓冲区的支持。 *
* 2、支持长按键处理。 *
* 3、需要外部提供一个毫秒级的延时计数器。 *
* 4、需要外部提供一个有返回值得键盘扫描 *
* 函数,该函数需要做基本的去抖。 *
* 5、可以外部定义缓冲区大小,空键值。 *
* 6、增加了一个入口键盘扫描码的噪声抑制参 *
* KEY_PRESS_DELAY,该值为毫秒级的单向 *
* 递减数值,即如果值不为零,则减到0为。 *
* 如果键盘响应过于迟钝,可以适当改小该 *
* 参数值。 *
* v1.3 修改了头文件的组织形式,对外的接口模式 *
* 对一些时间计数器进行了分类和统一宏定义 *
* 允许外部通过宏定义将这些接口连接到实际 *
* 的计数器上。同时兼容从前的版本。 *
* v1.31 修正了按键去抖计数器会干扰外部单向计数 *
* 器的错误。 *
* v1.32 允许选择自动刷新按键和手动刷新按键两种模式 *
* v2.00 支持长按键以重复的间隔触发。 *
* -------------------------------------------------------- *
* [说明] *
* 1、在外部合适的位置(毫秒中断程序)增加 *
* USEKEY_INSERT_MS_TIMER_OVF_ISR_CODE来保证 *
* 头文件的正常使用。 *
* 2、可以通过定义KEY_BUFF_SIZE来设置键盘缓冲区 *
* 的大小。 *
* 3、可以通过定义KEY_PRESS_DELAY来设置去抖得 *
* 时间常数。 *
* 4、可以通过_USE_KEY_PRESS_SCAN_FUNC_INTERFACE *
* 来连接用于键盘扫描的函数。该函数必须返回 *
* 扫描码。 *
* 5、通过GetKeyCode()函数来获得缓冲区状态,当 *
* 该函数返回True时,可以从ReturnKeyNum和 *
* ReturnLongPressKeyNum中分别获取按键和长 *
* 按键的扫描码,两个值不能同时不为KeyNull *
* 6、允许通过_USE_KEY_MANUL_REFRESH来选择自动刷 *
* 新按键缓冲区的模式。 *
* 7、可以通过宏_USE_KEY_LONG_PRESS_DELAY_TIME来 *
* 定义长按键的最小判定时间。 *
* 9、可以通过宏_USE_KEY_LONG_PRESS_REPEAT来打开 *
* 长按键重复触发功能。 *
* 8、宏_USE_KEY_LONG_KEY_FASTEST_SPEED_LEVEL可 *
* 以用来设定长按键时重复触发的最小时间间隔等 *
* 级。取值范围是0至4,数值越大,时间间隔越小 *
* 默认情况下为2,即一秒钟重复4次。 *
***********************************************************/
/********************
* 头 文 件 配 置 区 *
********************/
# include "RD_MacroAndConst.h"
# include "LIB_Config.h"
# include "RD_UseKey.h"
/********************
* 系 统 宏 定 义 *
********************/
/*------------------*
* 常 数 宏 定 义 *
*------------------*/
#ifndef KEY_BUFF_SIZE
# define KEY_BUFF_SIZE 8
#endif
#ifndef KEY_NULL
# define KEY_NULL 0xff
#endif
#ifndef KEY_PRESS_DELAY
# define KEY_PRESS_DELAY 50
#endif
#ifndef _USE_KEY_LONG_PRESS_DELAY_TIME
# define _USE_KEY_LONG_PRESS_DELAY_TIME 1000
#endif
#ifndef _USE_KEY_LONG_KEY_FASTEST_SPEED_LEVEL
# define _USE_KEY_LONG_KEY_FASTEST_SPEED_LEVEL 2
#endif
#if _USE_KEY_LONG_KEY_FASTEST_SPEED_LEVEL == 0
# define _USE_KEY_LONG_PRESS_FASTEST_SPEED 0x03ff
#elif _USE_KEY_LONG_KEY_FASTEST_SPEED_LEVEL == 1
# define _USE_KEY_LONG_PRESS_FASTEST_SPEED 0x01ff
#elif _USE_KEY_LONG_KEY_FASTEST_SPEED_LEVEL == 2
# define _USE_KEY_LONG_PRESS_FASTEST_SPEED 0x00ff
#elif _USE_KEY_LONG_KEY_FASTEST_SPEED_LEVEL == 3
# define _USE_KEY_LONG_PRESS_FASTEST_SPEED 0x007f
#elif _USE_KEY_LONG_KEY_FASTEST_SPEED_LEVEL == 4
# define _USE_KEY_LONG_PRESS_FASTEST_SPEED 0x003f
#else
# define _USE_KEY_LONG_PRESS_FASTEST_SPEED 0x00ff
#endif
/********************
* 函 数 声 明 区 *
********************/
static void _Key_Scan(void);
/********************
* 函 数 声 明 区 *
********************/
void Add_Key_Code(void);
unsigned char Get_Key_Code(void);
/********************
* 函 数 引 用 区 *
********************/
#ifndef _USE_KEY_PRESS_SCAN_FUNC_INTERFACE
# error Need for _USE_KEY_PRESS_SCAN_FUNC_INTERFACE
#else
extern unsigned char _USE_KEY_PRESS_SCAN_FUNC_INTERFACE(void);
#endif
/********************
* 全局变量声明区 *
********************/
unsigned char g_cReturnKeyNum = KEY_NULL;
unsigned char g_cReturnLongPressKeyNum = KEY_NULL;
unsigned int g_wKeyPressTimeCounter = 0;
unsigned int g_wKeyPressDelayCounter = 0;
/********************
* 模块变量声明区 *
********************/
static unsigned char s_cKeyBUFF[KEY_BUFF_SIZE][2];
static unsigned char s_cKeyBUFFCounter = 0;
static unsigned char s_cKeyBUFFHeadPoint = 0;
static unsigned char s_cKeyBUFFTailPoint = 0;
static unsigned char s_cLongKeyPressNum = KEY_NULL;
static unsigned char s_cKeyNum = KEY_NULL;
/***********************************************************
* 函数说明:按键扫描码处理函数 *
* 输入: 无 *
* 输出: 无 *
* 调用函数:_USE_KEY_PRESS_SCAN_FUNC_INTERFACE() *
* -------------------------------------------------------- *
* [说 明] *
* 按下一个键以后,1s以内松开返回短按键键值 *
* 1s以上返回长按键键值。键值只保存一个周期 *
***********************************************************/
static void _Key_Scan(void)
{
static unsigned char OldKeyCode = KEY_NULL;
static unsigned char IfLongKeyPress = FALSE;
static unsigned int LongPressAcceleration = 0;
unsigned char NowKeyCode = _USE_KEY_PRESS_SCAN_FUNC_INTERFACE();
s_cKeyNum = KEY_NULL;
if ((OldKeyCode != NowKeyCode) && (g_wKeyPressDelayCounter == 0))
{
g_wKeyPressTimeCounter = 0;
LongPressAcceleration = 0x01ff;
if ((NowKeyCode == KEY_NULL) && (IfLongKeyPress == FALSE))
{
s_cKeyNum = OldKeyCode;
}
g_wKeyPressDelayCounter = KEY_PRESS_DELAY;
OldKeyCode = NowKeyCode;
IfLongKeyPress = FALSE;
}
else
{
s_cKeyNum = KEY_NULL;
if ((g_wKeyPressTimeCounter > _USE_KEY_LONG_PRESS_DELAY_TIME) && (IfLongKeyPress == FALSE))
{
#ifdef _USE_KEY_LONG_PRESS_REPEAT
if (LongPressAcceleration > _USE_KEY_LONG_PRESS_FASTEST_SPEED)
{
LongPressAcceleration >>= 1;
}
#endif
s_cLongKeyPressNum = NowKeyCode;
IfLongKeyPress = TRUE;
}
else
{
#ifdef _USE_KEY_LONG_PRESS_REPEAT
if (!(g_wKeyPressTimeCounter & LongPressAcceleration))
{
IfLongKeyPress = FALSE;
}
else
{
s_cLongKeyPressNum = KEY_NULL;
}
#else
s_cLongKeyPressNum = KEY_NULL;
#endif
}
}
}
/***********************************************************
* 函数说明:键盘缓冲处理函数 *
* 输入: 无 *
* 输出: 无 *
* 调用函数:_Key_Scan() *
***********************************************************/
void Add_Key_Code(void)
{
_Key_Scan();
if ((s_cKeyNum == KEY_NULL) && (s_cLongKeyPressNum == KEY_NULL))
{
return ;
}
if ((s_cKeyBUFFHeadPoint == s_cKeyBUFFTailPoint) && (s_cKeyBUFFCounter != NULL))
{
return ;
}
s_cKeyBUFF[s_cKeyBUFFTailPoint][0] = s_cKeyNum;
s_cKeyBUFF[s_cKeyBUFFTailPoint][1] = s_cLongKeyPressNum;
s_cKeyBUFFTailPoint ++;
if (s_cKeyBUFFTailPoint == KEY_BUFF_SIZE)
{
s_cKeyBUFFTailPoint = 0;
}
s_cKeyBUFFCounter ++;
}
/***********************************************************
* 函数说明:从键盘缓冲区中获得一个按键扫描码 *
* 输出: 返回操作是否成功TRUE / FALSE *
* 输入: 无 *
* 调用函数:Add_Key_Code() *
* -------------------------------------------------------- *
* [说 明] *
* 将按键扫描码放到专门的临时缓冲变量中 *
***********************************************************/
unsigned char Get_Key_Code(void)
{
g_cReturnKeyNum = KEY_NULL;
g_cReturnLongPressKeyNum = KEY_NULL;
#ifdef _USE_KEY_MANUL_REFRESH
Add_Key_Code();
#endif
if ((s_cKeyBUFFHeadPoint == s_cKeyBUFFTailPoint) && (s_cKeyBUFFCounter == NULL))
{
return FALSE;
}
g_cReturnKeyNum = s_cKeyBUFF[s_cKeyBUFFHeadPoint][0];
g_cReturnLongPressKeyNum = s_cKeyBUFF[s_cKeyBUFFHeadPoint][1];
s_cKeyBUFFCounter--;
s_cKeyBUFFHeadPoint++;
if (s_cKeyBUFFHeadPoint == KEY_BUFF_SIZE)
{
s_cKeyBUFFHeadPoint = 0;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -