4x4矩阵键盘程序
P1外接4x4键盘的反转法扫描
2009-11-07 10:53
;------------------------------------------------------------------------------------P1口外接4×4按键, 常用的读出键值的方法有“查表法”和“反转法”。
查表法的程序最为简短,但是稍多占用一点存储空间;反转法的程序执行速度最快,只是要求接口向的。
下面分别给出了使用查表法和反转法读取键值的程序。
;------------------------------------------------------------------------------------#include
#include
#define uint unsigned int
#define uchar unsigned char
/**************************************************************
* 名称:Key_Tab()
* 功能:P1外接4×4按键, 按照查表法读出键值
* 返回:按键值0~15/如无键按下, 返回16
***************************************************************/
uchar Key_Tab(void)
{
uchar code K_Tab[4][4] = {
0xee, 0xde, 0xbe, 0x7e, 0xed, 0xdd, 0xbd, 0x7d,
0xeb, 0xdb, 0xbb, 0x7b, 0xe7, 0xd7, 0xb7, 0x77};
uchar temp1 = 0xfe, temp2, i, j;
for(i = 0; i
P1 = temp1; //输出一行0
temp2 = P1; //马上就读入
if((temp2 & 0xf0) != 0xf0) { //如果有键按下
for(j = 0; j
if(temp2 == K_Tab[i][j]) //查表
return i * 4 + j; //查到了就返回按键的数值
}
else temp1 = _crol_(temp1, 1);
}
return 16; //没有查到,返回按键松开的代码
} //呵呵,实质性的语句不过9行,就是这么简练!
;------------------------------------------------------------------------------------/**************************************************************
* 名称:KeyRvs()
* 功能:P1外接4×4按键, 按照反转法读出键值
* 输出:按键值0~15/如无键按下, 返回16
***************************************************************/
uchar KeyRvs(void)
{
uchar temH, temL, key;
P1 = 0xf0; temH = P1;//低四位先输出0;读入,高四位含有按键信息 P1 = 0x0f; temL = P1;//然后反转输出0;读入,低四位含有按键信息 //-----------------------------------------------------
//两次读入的时间间隔,必须尽量的小,以尽量避免按键状态发生变化
//有些人给出的程序,就没有注重这些,有些程序甚至还有间隔几个毫秒的! //要知道,按键是会抖动的,夜长梦多,真不知道读出些什么!
//呵呵,做而论道给出的这个程序,读键的准确性最高。
//-----------------------------------------------------
switch(temH) {
case 0xe0: key = 0; break;
case 0xd0: key = 1; break;
case 0xb0: key = 2; break;
case 0x70: key = 3; break;
default: return 16;//按下的不是上述按键,就当是没有按键
}
switch(temL) {
case 0x0e: return key;
case 0x0d: return key + 4;
case 0x0b: return key + 8;
case 0x07: return key + 12;
default: return 16;//按下的不是上述按键,就当是没有按键
}
}//本程序虽然稍多几行,但是没有循环,还可以提前返回,所以执行的速度最快 欢迎大家积极讨论:
/* 名称:数码管显示 4X4矩阵
键盘按键号
说明:按下任意键时,数码
管都会显示其键的序号,扫描程
序首先判断按键发生在哪一列,
然后根据所发生的行附加不同的
值,从而得到按键的序号。
*/
#include
#define uchar unsigned char
#define uint unsigned int
//段码
uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xa1,0x86,0x8e,0x00};
sbit BEEP=P3^7;
//上次按键和当前按键的序号,该矩阵中序号范围 0~15,16表示无按键
uchar Pre_KeyNo=16,KeyNo=16;
//延时
void DelayMS(uint x)
{
uchar i;
while(x--) for(i=0;i
}
//矩阵键盘扫描
void Keys_Scan()
{
uchar Tmp;
P1=0x0f; //高4 位置0,放入 4 行
DelayMS(1);
Tmp=P1^0x0f;//按键后0f 变成 0000XXXX,X 中一个为 0,3 个仍为 1,通过异或把 3 个1 变为0,唯 一的 0 变为1
switch(Tmp) //判断按键发生于 0~3 列的哪一列
{
case 1: KeyNo=0;break;
case 2: KeyNo=1;break;
case 4: KeyNo=2;break;
case 8: KeyNo=3;break;
default:KeyNo=16; //无键按下
}
P1=0xf0; //低 4 位置0,放入 4 列
DelayMS(1);
Tmp=P1>>4^0x0f;//按键后 f0 变成 XXXX0000,X 中有 1 个为 0,三个仍为 1;高4 位转移到低 4位并 异或得到改变的值
switch(Tmp) //对0~3 行分别附加起始值 0,4,8,12
{
case 1: KeyNo+=0;break;
case 2: KeyNo+=4;break;
case 4: KeyNo+=8;break;
case 8: KeyNo+=12;
}
}
//蜂鸣器
void Beep()
{
uchar i;
for(i=0;i
{
DelayMS(1);
BEEP=~BEEP;
}
BEEP=0;
}
//主程序
void main()
{
P0=0x00;
BEEP=0;
while(1)
{
P1=0xf0;
if(P1!=0xf0) Keys_Scan(); //获取键序号 if(Pre_KeyNo!=KeyNo)
{
P0=~DSY_CODE[KeyNo];
Beep();
Pre_KeyNo=KeyNo;
}
DelayMS(100);
}
}
proteus 仿真图: