51单片机(AT89C52)矩阵键盘检测程序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhoukouguren/article/details/7772186

矩阵键盘检测思路:行线设为输出、列线设为输入获得列码,行线设为输入、列线设为输出获得行码,由行列码确定键值。

本程序可改进的地方:按键状态机中,将等待按键释放语句移到第三个状态中,可进一步提高按键扫描程序效率。

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit dula=P3^0;
sbit wela=P3^1;
#define keyport (P1)
#define keystate0 0		//按键确认状态
#define keystate1 1		//按键无动作状态
char keystate=1;	//按键状态初始化为按键无动作状态
uchar keynum=0;
void delayms(uint x)	//1ms
{
	uint y,z;
	for(y=x;y>0;y--)
		for(z=111;z>0;z--);
}
uchar code table[]={	//共阳数码管
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e};
void smg()
{
	dula=0;
	wela=0;
	P2=0x01;
	wela=1;
	wela=0;
	P2=table[keynum];
	dula=1;
	dula=0;
	delayms(1);

	P2=0x02;
	wela=1;
	wela=0;
	P2=table[keynum];
	dula=1;
	dula=0;
	delayms(1);

	P2=0x04;
	wela=1;
	wela=0;
	P2=table[keynum];
	dula=1;
	dula=0;
	delayms(1);

	P2=0x08;
	wela=1;
	wela=0;
	P2=table[keynum];
	dula=1;
	dula=0;	
	delayms(1);

	P2=0x10;
	wela=1;
	wela=0;
	P2=table[keynum];
	dula=1;
	dula=0;
	delayms(1);

	P2=0x20;
	wela=1;
	wela=0;
	P2=table[keynum];
	dula=1;
	dula=0;
	delayms(1);

	P2=0x40;
	wela=1;
	wela=0;
	P2=table[keynum];
	dula=1;
	dula=0;
	delayms(1);

	P2=0x80;
	wela=1;
	wela=0;
	P2=table[keynum];
	dula=1;
	dula=0;
	delayms(1);
}
void keyscan()
{
	uchar temp1,temp2,column,row;
	switch(keystate)		
	{
		case keystate0:	//keystate0,按键按下确认状态,下一状态为keystate1(按键无动作状态)
			keyport=0x0f;
			temp1=keyport;
			keyport=0xf0;
			temp2=keyport;			
			if((temp1|temp2)!=0xff)
			{
				temp1|=temp2;
				if(!(temp1&0x80))
					row=3;
				else 
					if(!(temp1&0x40))
						row=2;	
					else
						if(!(temp1&0x20))
							row=1;
						else
							if(!(temp1&0x10))
								row=0;
				if(!(temp1&0x08))
					column=3;
				else 
					if(!(temp1&0x04))
						column=2;	
					else
						if(!(temp1&0x02))
							column=1;
						else
							if(!(temp1&0x01))
								column=0;
				keynum=column*4+row;
				while(!(keyport==0x0f|keyport==0xf0));
				keystate=keystate1;
				break;				
				
			}
			else
				keystate=keystate1;
			break;
		case keystate1:	//keystate1,按键无动作状态,下一状态为keystate0(按键无动作状态)
			keyport=0x0f;
			temp1=keyport;
			keyport=0xf0;
			temp2=keyport;			
			if((temp1|temp2)!=0xff)
			{
				keystate=keystate0;
			}
			else
				keystate=keystate1;
			break;
	}
}
void main()
{
	while(1)
	{
		keyscan();
		smg();
	}
}


 

展开阅读全文

没有更多推荐了,返回首页