📄 key.c
字号:
/*
********************************************************************************
*
* LCD控制程序
*
* 这是一个按键处理模块
*
* 文件名 : KEY.C
* 设计者 : Terry
********************************************************************************
* 功 能 描 述
*
* 该键盘模块驱动一个简单的I/O键盘,在这里是能够处理6个输入按键,按键的输入
* 数量可以被很方便的扩展。键盘的扫描由一个定时中断来驱动,在固定的间隔里对键盘
* 进行扫描,一旦有按键按下,该按键的扫描码被放入一个键盘缓冲区,应用程序从缓冲
* 区中读取扫描码并进行相应的动作。键盘缓冲区是一个良好的特性,可以防止按键动作
* 的丢失。
* 该模块带有按键锁定的功能,由标志Flg_KeyLock来控制,如果Flg_KeyLock = 1,
* 那么按键将不会被扫描,这可以使用在不需要按键输入干扰的情况下。
* 关于该按键模块的配置,公共变量,对外接口函数均放在头文件: KEY.H中,如要
* 使用按键模块就要包含该头文件
********************************************************************************
*/
#include "global.h"
/*
********************************************************************************
* 定义键盘状态机的状态
********************************************************************************
*/
#define KEY_STATE_UP 1 /* Key scanning states used in KeyScan() */
#define KEY_STATE_DEBOUNCE 2
#define KEY_STATE_RPT_START_DLY 3
#define KEY_STATE_RPT_DLY 4
/*
********************************************************************************
* 键盘模块所使用的静态变量
********************************************************************************
*/
static uint8 xdata KeyBuf[KEY_BUF_SIZE];
static uint16 xdata KeyDownTmr;
static uint8 xdata KeyBufInLx;
static uint8 xdata KeyBufOutLx;
static uint8 xdata KeyScanState;
static uint8 xdata KeyRptStartDlyCtr;
static uint8 xdata KeyRptDlyCtr;
/*
********************************************************************************
* 键盘模块所使用的静态功能函数定义
********************************************************************************
*/
static void KeyBufIn(uint8 key);
static uint8 KeyGetKeyCode(void);
static uint8 KeyIsDown(void);
/*
********************************************************************************
* 键盘模块的全局变量定义
********************************************************************************
*/
bit Flg_KeyOnePress = 0;
/*
********************************************************************************
* 函 数 名: KeyBufIn
* 功能描述: 按键代码放入到键盘缓冲区中
* 输 入: key :按键的代码
* 返 回: 无
********************************************************************************
*/
static void KeyBufIn(uint8 key)
{
uint8 tmp;
tmp = KeyBufInLx + 1;
if (tmp == KEY_BUF_SIZE) tmp = 0;
if (tmp == KeyBufOutLx) return; //如果尾指针加1以后等于头指针,则表示命令队列已满
KeyBufInLx = tmp;
KeyBuf[KeyBufInLx] = key;
}
/*
********************************************************************************
* 函 数 名: KeyIsDown
* 功能描述: 判断有没有按键按下去
* 输 入: 无
* 返 回: 0 : 没有按键按下
* 1 : 有按键按下
********************************************************************************
*/
static uint8 KeyIsDown(void)
{
if (KeyGetKeyCode() == KEYCODE_NOPRESS) {
Flg_KeyOnePress = 0;
return 0;
}
else {
if (KeyDownTmr < 0xFFFF) KeyDownTmr++;
return 1;
}
}
/*
********************************************************************************
* 函 数 名: KeyGetKey
* 功能描述: 从键盘缓冲区中读按键代码,如果缓冲区是空则返回0xff
* 输 入: 无
* 返 回: 按键的代码
********************************************************************************
*/
uint8 KeyGetKey(void)
{
if (KeyBufOutLx == KeyBufInLx ) return 0xFF;
KeyBufOutLx++;
if (KeyBufOutLx == KEY_BUF_SIZE) KeyBufOutLx = 0;
return KeyBuf[KeyBufOutLx];
}
/*
********************************************************************************
* 函 数 名: KeyInit
* 功能描述: 键盘模块初始化,要正确使用键盘模块的功能,要首先调用初始化
* 输 入: 无
* 返 回: 0 : 键盘缓冲区中没有按键
* 1 : 键盘缓冲区中有按键
********************************************************************************
*/
void KeyInit(void)
{
uint8 i;
KeyBufInLx = KEY_BUF_SIZE - 1;
KeyBufOutLx = KEY_BUF_SIZE - 1;
KeyScanState = KEY_STATE_UP;
KeyDownTmr = 0;
for (i=0; i< KEY_BUF_SIZE; i++) KeyBuf[i] = 0xFF;
}
/*
********************************************************************************
* 函 数 名: KeyHit
* 功能描述: 应用程序调用该函数判断键盘缓冲区有无按键
* 输 入: 无
* 返 回: 无
********************************************************************************
*/
bit KeyHit(void)
{
if (KeyBufOutLx == KeyBufInLx ) return 0;
else return 1;
}
/*
********************************************************************************
* 函 数 名: KeyGetKeyDownTime
* 功能描述: 返回按键按下去的时间,这个时间是扫描时间间隔的计数值
* 输 入: 无
* 返 回: 按键按下去的时间
********************************************************************************
*/
uint16 KeyGetKeyDownTime(void)
{
return KeyDownTmr;
}
/*
********************************************************************************
* 函 数 名: KeyScan
* 功能描述: 这是整个键盘模块的核心,完成整个键盘状态机的处理
* 输 入: 无
* 返 回: 按键按下去的时间
********************************************************************************
*/
void KeyScan(void)
{
switch (KeyScanState) {
case KEY_STATE_UP: // 按键没有按下,要查看有没有按键
if (KeyIsDown()) { // 检查是否有按键按下
KeyScanState = KEY_STATE_DEBOUNCE; // 有按键按下,改变按键扫描的状态
}
KeyDownTmr = 0; // 按键按下的时间清零
break;
case KEY_STATE_DEBOUNCE: // 按键已按下,获取扫描码,放入缓冲区
if (KeyIsDown()) { // 检查是否有按键按下
KeyBufIn(KeyGetKeyCode()); // 获取扫描码,并放入缓冲区
KeyRptStartDlyCtr = KEY_RPT_START_DLY; // 启动自动重复功能
KeyScanState = KEY_STATE_RPT_START_DLY; // 转换按键扫描状态
}
else KeyScanState = KEY_STATE_UP; // 没有键按下,改变按键扫描状态
break;
case KEY_STATE_RPT_START_DLY: // 等待启动自动重复
if (KeyIsDown()) { // 检查按键是否一直按着
if (KeyRptStartDlyCtr) { // 检查是否需要延时
KeyRptStartDlyCtr--;
if (KeyRptStartDlyCtr == 0) { // 检查延时时间到了没有
KeyBufIn(KeyGetKeyCode());
KeyRptDlyCtr = KEY_RPT_DLY; // 设置下一次重复的延时间隔
KeyScanState = KEY_STATE_RPT_DLY;
}
}
}
else KeyScanState = KEY_STATE_DEBOUNCE; // 键没有按下,改变扫描状态
break;
case KEY_STATE_RPT_DLY: // 等待下一次重复
if (KeyIsDown()) { // 检查按键是否一直按着
if (KeyRptDlyCtr) { // 检查是否需要延时
KeyRptDlyCtr--;
if (KeyRptDlyCtr == 0) { // 检查延时时间到了没有
KeyBufIn(KeyGetKeyCode());
KeyRptDlyCtr = KEY_RPT_DLY; // 设置下一次重复的延时间隔
}
}
}
else KeyScanState = KEY_STATE_DEBOUNCE; // 键没有按下,改变扫描状态
break;
}
}
/*
********************************************************************************
* 文 件 结 束 *
********************************************************************************
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -