单片机系统中,若使用按键较多时如电子密码锁、电话机键盘等一般都至少有12到16个按键,通常采用矩阵键盘。
矩阵键盘又称行列键盘
,它是用四条I/O线作为行线,四条I/O线作为列线组成的键盘。在行线和列线的每个交叉点上设置一个按键。这样键盘上按键的个数就为4*4个。这种行列式键盘结构能有效地提高单片机系统中I/O口的利用率。最常见的键盘布局一般由16个按键组成,在单片机中正好可以用一个P口实现16个按键功能,这也是在单片机系统中最常用的形式,4*4矩阵键盘的内部电路如下图所示。
当无按键闭合时,P3.0~P3.3与P3.4~P3.7之间开路。当有键闭合时,与闭合键相连的两条I/O口线之间短路。
判断有无按键按下的方法是:第一步,置列线P3.4~P3.7为输入状态,从行线P3.0~P3.3输出低电平,读入列线数据,若某一列线为低电平,则该列线上有键闭合。第二步,行线轮流输出低电平,从列线P3.4~P3.7读入数据,若有某一列为低电平,则对应行线上有键按下。
综合上述两步的结果,可确定按键编号。但是键闭合一次只能进行一次键功能操作,因此须等到按键释放后,再进行键功能操作,否则按一次键,有可能会连续多次进行同样的键操作。识别按键的方法很多,其中最常见的方法是扫描法。当按键按下时,与此键相连的行线与列线导通,行线在无按键按下时处在高电平。如果所有的列线都处在高电平,则按键按下与否不会引起行线电平的变化,因此必须使所有列线处在低电平。这样,当有按键按下时,该键所在的行电平才会由高变低,才能判断相应的行有键按下。矩阵按键的位置由于行号和列号是唯一确定,因此可以分别对行号和列号进行二进制编码,然后两值合成一个字节,高4位是行号,低4位是列号。
代码如下:
#include<reg52.h>
void delay(int t)
{
int x, y;
for (x = t; x > 0; x--)
for (y = 10; y > 0; y--);
}
void main (void)
{
while (1)
{
P3 = 0xfe; //扫描第一行
temp = P3;
temp = temp & 0xf0; //保留列上的信息
if (temp != 0xf0) //四列有输入为低电平0的? 有按键?
{
delay(10); //过10ms,再观察。
if (temp != 0xf0) //还是四列有输入为低的情况?有按键?
{
temp = P3; //读一下信息。
switch (temp)
{
case 0xee: //如果是第一行第一列?
key = 0;
break;
case 0xde:
key = 1;
break;
case 0xbe:
key = 2;
break;
case 0x7e:
key = 3;
break;
}
while (temp != 0xf0)
{
temp = P3;
temp = temp & 0xf0;
}
disp(key);
}
}
P3 = 0xfd;
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delay(10);
if (temp != 0xf0)
{
temp = P3;
switch (temp)
{
case 0xed:
key = 4;
break;
case 0xdd:
key = 5;
break;
case 0xbd:
key = 6;
break;
case 0x7d:
key = 7;
break;
}
while (temp != 0xf0)
{
temp = P3;
temp = temp & 0xf0;
}
disp(key);
}
}
P3 = 0xfb;
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delay(10);
if (temp != 0xf0)
{
temp = P3;
switch (temp)
{
case 0xeb:
key = 8;
break;
case 0xdb:
key = 9;
break;
case 0xbb:
key = 10;
break;
case 0x7b:
key = 11;
break;
}
while (temp != 0xf0)
{
temp = P3;
temp = temp & 0xf0;
}
disp(key);
}
}
P3 = 0xf7;
temp = P3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delay(10);
if (temp != 0xf0)
{
temp = P3;
switch (temp)
{
case 0xe7:
key = 12;
break;
case 0xd7:
key = 13;
break;
case 0xb7:
key = 14;
break;
case 0x77:
key = 15;
break;
}
while (temp != 0xf0)
{
temp = P3;
temp = temp & 0xf0;
}
disp(key);
}
}
}
}