proteus进行51单片机矩阵键盘仿真实验

本文通过在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的仿真功能进行矩阵键盘的仿真,当有按键按下时,数码管将会显示被按下的按键的值。

参考博文:
proteus pro 8.9 安装及汉化教程
矩阵键盘扫描原理(附单片机驱动程序)

猜你喜欢

转载自blog.csdn.net/qq_45237293/article/details/108955311