📄 4x4keyboardscan.c
字号:
/*单片机典型矩阵键盘扫描程序
进行键盘扫描及键处理时,在程序中直接调用函数KeyProcess()即可。键处理函数原型声明在头文件Key.h中,键处理函数可放在程序的任何地方,一个按键对应一个处理函数。
该键盘扫描程序去抖动为什么不需软件延时?因为从无按键到键被按下,要进行两次扫描,此间相当于延时去抖动。
该键盘扫描程序还有一特色:用二维数组进行按键功能处理,使程序更简单。
/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
矩阵键盘键值扫描,功能处理函数
本程序处理4*4的矩阵键盘,直接用于8051系列单片机,也可移植到其它机型.
行输出在P1口高四位 列输入在P1口低四位,如果不同,则需修改键值读取函数
即:GetKeyCode(); 有10个数字键0--9,1个小数点,1个负号键。
第二功能键和回车键共用一个,如果连续按下该键2秒钟,则键盘进入第二功能。
在键盘初始化程序InitKeyboard中把ucKey1和ucKey2赋值0xff
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
#include "Key.h"
static uchar GetKeyStatus();
////$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
bit KeyProcess() // 为程序方便而设的返回值
{
uchar i,j;
void (*pFunction)(); // 定义函数指针
void (*code Tab[mHorizontalNumber][mVerticalNumber])()= // 定义函数表
{ { ZeroKey, OneKey, FourKey, SevenKey },
{ DotKey, TwoKey, FiveKey, EightKey },
{ NegativeKey, ThreeKey, SixKey, NineKey },
{ EnterOrShiftKey, CancelKey, OptionKey, PauseKey }
}; // 二维数组,对对应16个按键
NOP(); NOP();
if(!bScanKey)
return 0; // 扫描时间未到,返回(时间值在定时器中设定)
bScanKey=0;
NOP(); NOP();
j=GetKeyStatus(); // 取键值,0xff为无效键,即无按键
NOP(); NOP();
if(bKeyDown||bKeyPress||bKeyUp)
{
i=j>>4; j=j&0x0f; // 高半字节为行,低半字节为列
if((i<mHorizontalNumber)&&(j<mVerticalNumber))
{
pFunction=Tab[i][j]; // 指向函数入口地址
(*pFunction)(); // 调用函数
}
}
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
// 判断按键状态:KeyFree,KeyDown,KeyPress,KeyUp,并返回键值
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
static uchar ucKey1,ucKey2,ucKeyBak;
static uchar GetKeyCode();
static uchar GetKeyStatus()
{
uchar c;
NOP(); NOP();
mHorizontalAllLow; // 行输入全为0
mJugeVertical(c); // 判断是否有按键
NOP(); NOP();
if((ucKey1==0xff)&&(ucKey2==0xff)&&(c==0xff))
{ // 三个值均为0xff,无按键
bKeyDown=bKeyPress=bKeyUp=0;
bKeyFree=TRUE; return 0xff; // 没按键
}
else
{
bKeyFree=0;
if(c!=0xff)
c=GetKeyCode(); // 扫描键值
if((ucKey1==0xff)&&(ucKey2==c))
{
ucKey1=ucKey2; ucKey2=c;
bKeyDown=TRUE; return c; // 键被按下
}
if((ucKey1==ucKey2)&&(ucKey2==c))
{
NOP();
if(bKeyDown)
{
bKeyPress=TRUE; // 键被按住
bKeyDown=0;
}
return c;
}
if((ucKey1!=0xff)&&(ucKey2==0xff)&&(c==0xff))
{
ucKeyBak=ucKey1; ucKey1=ucKey2; ucKey2=c;
if(bKeyPress)
{
bKeyUp=TRUE; // 键弹起
bKeyPress=0;
}
return ucKeyBak;
}
ucKey1=ucKey2; ucKey2=c;
}
return 0xff;
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
// 本程序读按键的行列号值,将行列号组合成一个字节后返回, //
// 若读键错误,或没按键均返回0xff。// 低半字节为行,高半字节为列
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
static uchar GetKeyCode()
{
uchar i,j,ucTemp,ucH_Value;
NOP(); NOP();
ucH_Value=mH_InitValue;
for(i=0;i<mHorizontalNumber;i++)
{
j=ucH_Value;
mReadVertical(j); // 输出一行低电平后,读列值
NOP();
if(j<mKeyOff)
{
j=(~j)&mKeyOff;
ucTemp=0xff; // 列初值,加0x01为0x00,即第0列
do
{ ucTemp=ucTemp+0x01; }
while ((j=j>>1)>0);
i<<=4; // 把行值移到高四位
return(i|ucTemp); // 返回高四位行值,低四位列值
}
ucH_Value<<=1; ucH_Value|=0x01; // 下一行输出低电平
}
return 0xff;
}
/* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
/* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
void InitKeyboard()
{
ucKey1=ucKey2=0xff;
}
以下是键盘专用头文件。文件名 Key.h
/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
矩阵键盘键值扫描,功能处理函数
本程序处理4*4的矩阵键盘,适用于8051系列单片机。行输出在P1口高四位,
列输入在P1口低四位,如果不同,则需修改键值读取函数即:GetKeyCode();
在键盘初始化程序InitKeyboard中把ucKey1和ucKey2赋值0xff
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
#include "head.h"
#define mHorizontalNumber 4 // 总行数
#define mVerticalNumber 4 // 总列数
#define mKeyOff 0x0f
#define mH_InitValue 0xef
// P14-P17 行 // P10-P13 列
#define mJugeVertical(c) { c=P1&0x0f; c|=0xf0; }
// 判断列值是否全为高电平,即是否有按键
#define mHorizontalAllLow { P1&=0x0f; NOP(); NOP(); NOP();}
// 高四位行线输出全零
#define mReadVertical(c) { P1=c; NOP(); NOP(); NOP(); \
NOP(); NOP(); c=P1&0x0f; }
// 某一行为低电平,读键值
uchar bdata bucKeyStatus; // 键的一般属性标志位
sbit bKeyDown=bucKeyStatus^0; // KeyDown
sbit bKeyPress=bucKeyStatus^1; // KeyPress
sbit bKeyUp=bucKeyStatus^2; // KeyUp
sbit bKeyFree=bucKeyStatus^3; // KeyFree
sbit bScanKey=bucKeyStatus^4; // 定时扫描标志位
void ZeroKey();
void OneKey();
void TwoKey();
void ThreeKey();
void FourKey();
void FiveKey();
void SixKey();
void SevenKey();
void EightKey();
void NineKey();
void DotKey();
void NegativeKey();
void PauseKey();
void PrintKey();
void OptionKey();
void CancelKey();
void EnterOrShiftKey();
ulong FloatBcdToHex(uchar *);
uint DecToHex(uchar,uchar,uchar,uchar);
uchar HexToDec(uint,uchar);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -