📄 keyscan.c
字号:
/***************************************************************************************************
**
** 按键查询扫描软件子程序
** 该程序采用在定时器中每间隔10ms扫描一次按键状态,并且通过特定在按键“年份”计数器把每次的次数记录
** 下来,然后在GetKey_Value中进行相应的处理,进而得到相应的键值。
** 内存占用:2个字节的按键状态KeyDownF_Flag、KeyDownM_Flag
n个按键的字节个“年份”计数器KeyYearCnt[KeyMaxNum]
** 适用范围:该子程序使用于按键接在同一个端口上,并且是连续的情况
** 返回键值:返回的按键的键值和按键连接的端口相对应
**----------------------------------------------------------------------------------------------------
** 作 者 : 严俊生
** 日 期 : 2007-07-06
** 版本号 :V1.0
**----------------------------------------------------------------------------------------------------
** 修改人 :
** 日 期 :
** 版本号 :
**
****************************************************************************************************/
#include "KeyScan.H"
#define Key_Scan_EN 1
#define KeyDown_Value_EN 1
static _KeyScanStatus KeyScanStatus;
/*******************************************************************************************************
** 名 称:Key_Scan
** 功 能:本程序是采用查询的方式来扫描按键的,此处是假定KEY键全部接在P0口上的,在使用的时候要根据
实际的情况更改。由于此程序是在定时器0#中断中被调用,所以此处把它定义为可重入函数
** 入口参数:PinValue 按键实际连接的物理端口
** 出口参数:无
** 注 意:该程序执行时间的长短与所需要扫描的按键数目有关系;
如果在强实时系统上,可以把该定时器0#中断设为最低优先级;需要强实时的处理在更高的优先级
中断中进行。
**----------------------------------------------------------------------------------------------------
** 作 者 : 严俊生
** 日 期 : 2007-07-06
**----------------------------------------------------------------------------------------------------
** 修改人 :
** 日 期 :
*******************************************************************************************************/
#if Key_Scan_EN
void Key_Scan(unsigned char PinValue) reentrant
{ unsigned char i,keycurval;
// 暂定为P0口接按键
keycurval = PinValue;
/*============================= 按键扫描处理程序 ==============================*/
for(i=0;i<KeyMaxNum;i++)
{
if(keycurval&0x01)
{
KeyScanStatus.KeyYearCnt[i] = 0; // 按键“年份”计数器清0
KeyScanStatus.KeyDownF_Flag &= ( ~(1<<i) ); // 清零单次按键状态
KeyScanStatus.KeyDownM_Flag &= ( ~(1<<i) ); // 清零多次按键状态
}
else KeyScanStatus.KeyYearCnt[i]++; // 按键“年份”计数器加1
keycurval = keycurval>>1;
}
}
#endif
/*******************************************************************************************************
** 名 称:GetKey_Value
** 功 能:本程序根据扫描的结果来判断按键的状态,是第一次按键,还是连击
** 入口参数:无
** 出口参数:返回按键的键号,支持多个按键同时按下
**----------------------------------------------------------------------------------------------------
** 作 者 : 严俊生
** 日 期 : 2007-07-06
**----------------------------------------------------------------------------------------------------
** 修改人 :
** 日 期 :
*******************************************************************************************************/
#if KeyDown_Value_EN
unsigned char GetKey_Value(void)
{ unsigned char i, mm, nn=0, keydownstatus = 0;
for(i=0;i<KeyMaxNum;i++)
{
if( ( (KeyScanStatus.KeyYearCnt[i] > KeyDelayTime)&&((KeyScanStatus.KeyDownF_Flag&(1<<i))==0) ) ||
( (KeyScanStatus.KeyYearCnt[i] > KeyMaxTime) && ((KeyScanStatus.KeyDownM_Flag&(1<<i))==0) ) ||
( (KeyScanStatus.KeyYearCnt[i] > KeyMinTime) &&(KeyScanStatus.KeyDownM_Flag&(1<<i)) ) )
{
keydownstatus |= (1<<i);
// 第一次进入按键按下的状态
if( (KeyScanStatus.KeyYearCnt[i]>KeyDelayTime)&&((KeyScanStatus.KeyDownF_Flag&(1<<i))==0) )
{
KeyScanStatus.KeyYearCnt[i] = 0;
KeyScanStatus.KeyDownF_Flag |= (1<<i);
continue; // 退出本次循环
}
// 多次进入按键按下的状态
if( (KeyScanStatus.KeyYearCnt[i]>KeyMaxTime)&&((KeyScanStatus.KeyDownM_Flag&(1<<i))==0) )
{
KeyScanStatus.KeyYearCnt[i] = 0;
KeyScanStatus.KeyDownM_Flag |= (1<<i);
continue; // 退出本次循环
}
// 已经连击时候的处理
KeyScanStatus.KeyYearCnt[i] = 0;
}
}
// 进行多个按键的判断,如果已经有多个按键处于按下状态,则返回多个按键的键号
mm = KeyScanStatus.KeyDownF_Flag;
for(i=0;i<KeyMaxNum;i++)
{
if(mm&0x01) nn++;
mm = (mm>>1);
}
if(nn>1) return KeyScanStatus.KeyDownF_Flag;
else return keydownstatus;
}
#endif
/********************************* End *************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -