本文通过在proteus上搭建51单片机的矩阵键盘电路并联合keil编程软件编写的源程序进行8*8矩阵键盘仿真,进而熟悉proteus软件的仿真操作。
(一)4×4矩阵键盘原理
1.逐行扫描
通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下;然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。
2.行列扫描
通过高四位同时输出低电平,低四位输出高电平。当低四位接收到的数据不全为高电平时,说明有按键按下;然后通过接收的数据值,判断是哪一列有按键按下。然后再反过来,高四位同时输出高电平,低四位输出低电平,然后根据高四位接收到的值判断是哪一行有按键按下,这样就能够确定是哪一个按键被按下。
(二)8×8矩阵键盘设计
1.proteus电路图设计
2.程序设计
- 按键检测部分
这里编写的8×8矩阵键盘检测程序是通过51单片机的P2和P3口以行列检测原理的方式进行按键的检测。
/********键盘检测函数************/
void Key_Down(void)
{
char a=0;
P2=0xff; //P2口为高电平
P3=0x00; //P3口为低电平
if(P2!=0xff)//读取按键是否按下
{
delay();//延时进行消抖
if(P2!=0xff)//再次检测键盘是否按下
{
flags=1;
//测试列上哪一个键按下
P2=0x00; //P2口为低电平
P3=0xff; //P3口为高电平
switch(P3)
{
case(0Xfe): KeyValue=1;break;
case(0Xfd): KeyValue=2;break;
case(0Xfb): KeyValue=3;break;
case(0Xf7): KeyValue=4;break;
case(0Xef): KeyValue=5;break;
case(0Xdf): KeyValue=6;break;
case(0Xbf): KeyValue=7;break;
case(0X7f): KeyValue=8;break;
}
//测试行上哪一个键按下
P2=0xff; //P2口为高电平
P3=0x00; //P3口为低电平
switch(P2)
{
case(0Xfe): KeyValue=KeyValue;break;
case(0Xfd): KeyValue=KeyValue+8;break;
case(0Xfb): KeyValue=KeyValue+16;break;
case(0Xf7): KeyValue=KeyValue+24;break;
case(0Xef): KeyValue=KeyValue+32;break;
case(0Xdf): KeyValue=KeyValue+40;break;
case(0Xbf): KeyValue=KeyValue+48;break;
case(0X7f): KeyValue=KeyValue+56;break;
}
}
}
while((a<20)&&(P2!=0xff)) //检测按键是否松开检测(P2!=0xff表示按键仍然处于按下的状态)
{
delay();
a++;
}
flags=0;
}
- 数码管显示部分
/*****数码管段选数码******/
void Seg_Choose()
{
unsigned int key=KeyValue;
if(key<10) //个位数时直接显示
{
k1=0;
k2=key;
key=0;
}
else //两位数时分别显示
{
while(key/10!=0)
{
k2=key%10;
key/=10;
k1=key;
}
}
}
- 完整程序如下
#include<reg51.h>
unsigned int KeyValue=0;
unsigned int flags=0; //按键状态标志位,按下为1,没按下为0
unsigned int k1,k2;
unsigned char code KB[10]={0xBF,0xB0,0xED,0xF9,0xF2,0xDB,0xDF,0xB1,0xFF,0xFB}; /*存储0~9的数码管1段选数码*/
/*******延时函数*********/
void Delay()
{
unsigned int i;
for(i=0;i<200;i++);
}
/********键盘检测函数************
//以下按键检测函数为逐行扫描的程序
unsigned int kbscan()
{
unsigned int linecode,rowcode;
unsigned int kcode[2];
P2=0x00; //P2.0~P2.7置为0
P3=0xff; //P3.0~P3.7置为1
//P1=0xff;
if((P3 & 0xff) != 0xff) //P3口八位不全为1,说明有按键按下
{
delay(); //去除按键抖动
if((P3 & 0xff) != 0xff)
{
linecode=0xfe;
rowcode=P3;
while((linecode & 0x80) != 0 || (linecode & 0x80) == 0xff) //逐行扫描
{
P2=linecode; //P2口输出扫描码逐行扫描
if((P2 & 0xff)!=0xff) //如果P2.0~P2.7不全为1,该行有按键按下
{
kcode[0]=linecode; //把行编码存入数组中去
kcode[1]=rowcode; //把列编码存入数组中去
//P1=0xb1;
return kcode; //返回该数组
}
else
{
linecode=(linecode<<1) | 0x01; //如果该行没有按键按下,查找下一行,行扫描值左移一位
}
}
}
}
return 0; //无键按下返回0
}
*/
/********键盘检测函数************/
void Key_Down(void)
{
char a=0;
P2=0xff; //P2口为高电平
P3=0x00; //P3口为低电平
if(P2!=0xff)//读取按键是否按下
{
delay();//延时进行消抖
if(P2!=0xff)//再次检测键盘是否按下
{
flags=1;
//测试列上哪一个键按下
P2=0x00; //P2口为低电平
P3=0xff; //P3口为高电平
switch(P3)
{
case(0Xfe): KeyValue=1;break;
case(0Xfd): KeyValue=2;break;
case(0Xfb): KeyValue=3;break;
case(0Xf7): KeyValue=4;break;
case(0Xef): KeyValue=5;break;
case(0Xdf): KeyValue=6;break;
case(0Xbf): KeyValue=7;break;
case(0X7f): KeyValue=8;break;
}
//测试行上哪一个键按下
P2=0xff; //P2口为高电平
P3=0x00; //P3口为低电平
switch(P2)
{
case(0Xfe): KeyValue=KeyValue;break;
case(0Xfd): KeyValue=KeyValue+8;break;
case(0Xfb): KeyValue=KeyValue+16;break;
case(0Xf7): KeyValue=KeyValue+24;break;
case(0Xef): KeyValue=KeyValue+32;break;
case(0Xdf): KeyValue=KeyValue+40;break;
case(0Xbf): KeyValue=KeyValue+48;break;
case(0X7f): KeyValue=KeyValue+56;break;
}
}
}
while((a<20)&&(P2!=0xff)) //检测按键是否松开检测(P2!=0xff表示按键仍然处于按下的状态)
{
delay();
a++;
}
flags=0;
}
/*****数码管段选数码******/
void Seg_Choose()
{
unsigned int key=KeyValue;
if(key<10) //个位数时直接显示
{
k1=0;
k2=key;
key=0;
}
else //两位数时分别显示
{
while(key/10!=0)
{
k2=key%10;
key/=10;
k1=key;
}
}
}
int main()
{
while(1)
{
Key_Down();
Seg_Choose();
P1=KB[k2];
P0=KB[k1];
Delay();
}
return 0;
}
3.矩阵键盘仿真效果
按下某个按键后,会显示相对应的按键值(按键值1~64)。
(三)总结
在4×4矩阵键盘的基础上,我使用51单片机的P2口和P3口将其扩展为8×8的矩阵键盘,并编写对应的控制程序。通过proteus的仿真功能进行矩阵键盘的仿真,当有按键按下时,数码管将会显示被按下的按键的值。