(51单片机)第四章-键盘检测原理及应用实现-矩阵键盘检测

目录

4.2 矩阵键盘检测

  书上例程:实验板上电时,数码管不显示,顺序按下矩阵键盘后没再数码管上依此显示0~F,6个数码管同时静态显示即可

         一个用JX-TX-1C实验板制作的24小时以内的时间显示或者倒数计数模式的闹钟(相较以前有所更新)示例

参考资料: 


4.2 矩阵键盘检测

        独立键盘与单片机相连时每一个案件都需要单片机的一个I/O口,若单片机系统需要较多按键则独立按键会占用过多的I/O口资源。为节省I/O口,因纳入矩阵键盘。以4×4矩阵键盘为例讨论起工作原理和检测方法——16个按键排成4行4列,4行4列一共8根线,连接到单片机的8个I/O口上。

   TX-1C上的连接图原理如下:

        矩阵键盘检测是否按下原理同独立键盘——检测该键对应的I/O口是否为低电平,矩阵键盘两端都与I/O口相连,因此检测时需认为通过单片机I/O口送出低电平。检测时,送一列为低电平,其余几列为高电平(确定了列),再检测哪一行为低电平即可确定按下键的行列号,如此轮流检测各列各行,即可检测完所有的按键,反之先检测行线同理可行。 

        其中,TX-1C上的4行S6~S21的8条线分别与单片机的P3口相连——4行分别连P3.0~P3.3,4列分别于单片机的P3.4~P3.7(注意这里与独立按键占用的I/O口重复了,为防止发生51单片机独立键盘和矩阵键盘引脚定义相同IO口导致的问题(串口干扰):在扫描独立按键程序的开头加一句,P3=0xff;)。

        当无按键闭合时,P3.0~P3.3与P3.4~P3.7之间开路。当有键闭合时,与闭合键相连的两条I/O口线之间短路。判断有无按键按下的方法是:

(1)置列线P3.4~P3.7为输入状态,从行线P3.0~P3.3输出低电平,读入列线数据,若某一列线为低电平,则该列线上有键闭合。

(2)行线轮流输出低电平,从列线P3.4~P3.7读入数据,若有某一列为低电平,则对应行线上有键按下。综合一二两步的结果,可确定按键编号。但是键闭合一次只能进行一次键功能操作,因此须等到按键释放后,再进行键功能操作,否则按一次键,有可能会连续多次进行同样的键操作。

        检测矩阵键盘语句说明:(以扫描第一行按键为例)

         注:关于位运算可以参考文章:http://t.csdnimg.cn/dAUY9

        为方便编程和查找,在下面的例程中进行了如下的优化:

(1)将矩阵键盘行线存入code数组中便于表示和查找

uchar code matrixkeyboard_row_table[]={	//矩阵键盘行线
	0xfe, //第一行线
	0xfd, //第二行线
	0xfb, //第三行线
	0xf7  //第四行线	
};

(2)将矩阵键盘键位编码存入code数组中便于表示和查找 

uchar code matrixkeyboard_table[]={ //矩阵键盘按钮编号
	0xee,0xde,0xbe,0x7e, //第一行key1~4
	0xed,0xdd,0xbd,0x7d, //第二行key5~8
	0xeb,0xdb,0xbb,0x7b, //第三行key9~12
	0xe7,0xd7,0xb7,0x77  //第四行key13~16
};

(3) 由于(1)无法采用switch case语句(由于case后必须跟的是常数),因此判断temp具体值部分修改为(具体的情况请代入下面的例程):

temp=P3;

if(temp == matrixkeyboard_table[4*i-4]) key_num=4*i-3;
if(temp == matrixkeyboard_table[4*i-3]) key_num=4*i-2;
if(temp == matrixkeyboard_table[4*i-2]) key_num=4*i-1;
if(temp == matrixkeyboard_table[4*i-1]) key_num=4*i;

  书上例程:实验板上电时,数码管不显示,顺序按下矩阵键盘后没再数码管上依此显示0~F,6个数码管同时静态显示即可

        (和原书所附程序有所不同,原理一致,相比之下更便捷更简短)

#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char 

sbit dula=P2^6; //声明U1锁存器的锁存端
sbit wela=P2^7;	//声明U2锁存器的锁存端

uchar code dula_table[]={ //段选数码库
	0x3f,0x06,0x5b,0x4f, // 0,1,2,3
	0x66,0x6d,0x7d,0x07, //4,5,6,7
	0x7f,0x6f,0x77,0x7c, //8,9,10,11
	0x39,0x5e,0x79,0x71  //12,13,14,15
};

uchar code matrixkeyboard_row_table[]={	//矩阵键盘行线
	0xfe, //第一行线
	0xfd, //第二行线
	0xfb, //第三行线
	0xf7  //第四行线	
};

uchar code matrixkeyboard_table[]={ //矩阵键盘按钮编号
	0xee,0xde,0xbe,0x7e, //第一行key1~4
	0xed,0xdd,0xbd,0x7d, //第二行key5~8
	0xeb,0xdb,0xbb,0x7b, //第三行key9~12
	0xe7,0xd7,0xb7,0x77  //第四行key13~16
};
 
void main()
{
	void delayxms(uint xms); //延时函数 ms为单位
	void matrixkeyscan(); //矩阵键盘输入函数
	void display(uchar key_num); //数码管显示函数 
	dula=1;
	P0=0; //关闭所有数码管段选
	dula=0;
	wela=1; 
	P0=0xc0; //打开所有数码管的位选
	wela=0;
	
	while(1)
	{
		matrixkeyscan(); //不停调用键盘输入扫描函数
	}
}
void display(uchar key_num) //数码管显示函数 
{
	dula=1;
	P0=dula_table[key_num-1]; //由于是6个数码管同时静态显示,所以只需要变化段选数据
	dula=0;		
}
void matrixkeyscan() //矩阵键盘输入函数
{
	uchar key_num,temp;
	int i;
	for(i=1;i<=4;i++)
	{
		P3=matrixkeyboard_row_table[i-1];
		temp=P3;
		temp=temp&0xf0;
		while(temp!=0xf0)
		{
			delayxms(5);
			temp=P3;
			temp=temp&0xf0;
			while(temp!=0xf0)
			{
				temp=P3;

				if(temp == matrixkeyboard_table[4*i-4]) key_num=4*i-3;
				if(temp == matrixkeyboard_table[4*i-3]) key_num=4*i-2;
				if(temp == matrixkeyboard_table[4*i-2]) key_num=4*i-1;
				if(temp == matrixkeyboard_table[4*i-1]) key_num=4*i;

				while(temp!=0xf0)
				{
					temp=P3;
					temp=temp&0xf0;
				}
				display(key_num);	
			}
		}	
	}
}

void delayxms(uint xms) //延时函数 ms为单位
{
	uint x,y;
	for(x=xms;x>0;x--)
		for(y=124;y>0;y--);	
} 

         一个用JX-TX-1C实验板制作的24小时以内的时间显示或者倒数计数模式的闹钟(相较以前有所更新)示例

       注:同时按下4个独立按键可以解除闹钟

#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
#define ul unsigned long

sbit dula=P2^6; //声明U1锁存器的锁存端
sbit wela=P2^7; //声明U2锁存器的锁存端
sbit led1=P1^0; //声明第1号发光二极管(0亮1灭)
sbit beep=P2^3;	//声明蜂鸣器引脚(0响1灭)
sbit key1=P3^4; //声明独立按键1(S2)
sbit key2=P3^5; //声明独立按键2(S3)
sbit key3=P3^6; //声明独立按键3(S4)
sbit key4=P3^7; //声明独立按键4(S5)

uchar code dula_table[]={ //段选数码库
	0x3f,0x06,0x5b,0x4f, // 0,1,2,3
	0x66,0x6d,0x7d,0x07, //4,5,6,7
	0x7f,0x6f,0x77,0x7c, //8,9,10,11
	0x39,0x5e,0x79,0x71  //12,13,14,15
};

uchar code wela_table[]=  //片选数码库
{
	  0xdf/*最低位*/,0xef,0xf7,0xfb,0xfd,0xfe/*最高位*/	//从右向左数第一到六位
};

uchar code matrixkeyboard_row_table[]={	//矩阵键盘行线
	0xfe, //第一行线
	0xfd, //第二行线
	0xfb, //第三行线
	0xf7  //第四行线	
};

uchar code matrixkeyboard_table[]={ //矩阵键盘按钮编号
	0xee,0xde,0xbe,0x7e, //第一行key1~4
	0xed,0xdd,0xbd,0x7d, //第二行key5~8
	0xeb,0xdb,0xbb,0x7b, //第三行key9~12
	0xe7,0xd7,0xb7,0x77  //第四行key13~16
};

uint hour10_b,hour_b,min10_b,min_b,s10_b,s_b; //倒计时功能相关参数
uint hour10_f,hour_f,min10_f,min_f,s10_f,s_f; //时间显示功能相关参数
uint num_timer1; //定时器1计数
uint wei; //位选数字
uchar judge; //倒计时结束判别字符
uchar modechoice; //模式选择指示字符
uchar time_forwardon,time_backon;//模式选择开始与否指示字符
uchar temp;

void main()
{
	void init_wedu(); //数码管位选段选初始化函数
	void init_timer1(); //定时器1初始化函数
	void init_timebackward(); //倒计时功能相关参数初始化函数
	void init_timeforward(); //时间显示功能相关参数初始化函数
	void start_or_stop(); //启动或停止控制函数
	void delayxms(uint xms); //延时函数
	void wedu(uchar dula_num,uchar wela_num); //数码管位选段选函数
	void modechange(); //模式转换函数
	void resetall(); //重置函数(归0或满值)
	void display(); //数码管显示函数
	void matrixkeyscan(); //矩阵键盘输入函数

	init_wedu(); //数码管位选段选初始化
	init_timer1(); //定时器1初始化
	init_timebackward(); //倒计时功能相关参数初始化
	init_timeforward(); //时间显示功能相关参数初始化
	modechoice=0; //模式选择初始化为时间显示
	time_forwardon=0; //时间显示模式开始时暂停
	time_backon=0; //倒计时模式开始时暂停
	led1=1;	//初始化,二极管灯灭
	beep=1;	//初始化,蜂鸣器不响

	while(1)//程序在此处不停地对数码管进行动态扫描等待中断发生数码管示数发生变化
	{
		modechange();
		start_or_stop();
		matrixkeyscan();
		display();
		resetall();
    	}
}

void init_wedu() //数码管位选段选初始化函数
{
	dula=0; //初始化,段选置0
	wela=0; //初始化,片选置0
}

void init_timer1() //定时器1初始化函数
{
	TMOD=0x10;//设置定时器1的工作方式为1(0001)
	TH1=(65536-4608)/256; //装初值 50ms一次中断(45872) 10ms一次中断(4608) 
	TL1=(65536-4608)%256; //装初值
	EA=1; //打开总中断
	ET1=1; //打开定时器1中断
	TR1=1; //初始化直接开启定时器1
	num_timer1=0; //定时器1的计数初值置为0	
}

void init_timebackward() //倒计时功能相关参数初始化函数
{
	hour10_b=2;
	hour_b=3;
	min10_b=5;
	min_b=9;
	s10_b=5;
	s_b=9;	
}

void init_timeforward() //时间显示功能相关参数初始化函数
{
	hour10_f=0;
	hour_f=0;
	min10_f=0;
	min_f=0;
	s10_f=0;
	s_f=0;	
}

void modechange() //模式转换函数
{
	P3=0xff; //P3口置高防止矩阵键盘误触
	if(key1==0)
	{
		delayxms(10);  //检测按下延迟
		if((key1==0))
		{
			led1=0;
			beep=0;
			modechoice=!modechoice; //模式指示字符改变
		}
		while(!key1);//松手检测,不松开key1=0,while始终循环
			     //松开key1=1,while退出,退出此次检测程序
		delayxms(5);
		while(!key1); //检测松手延迟
	}
	else
	{
		led1=1;
		beep=1;
	}	
}

void start_or_stop() //启动或停止控制函数
{
	if(modechoice==0)
	{
		P3=0xff; //P3口置高防止矩阵键盘误触
		if(key2==0)
		{
			delayxms(10);
			if((key2==0))
			{
				led1=0;
				beep=0;
				time_forwardon=!time_forwardon; //时间显示功能开启或停止
			}
			while(!key2);
			delayxms(5);
			while(!key2);
		}
		else
		{
			led1=1;
			beep=1;
		}	
	}
	if(modechoice==1)
	{
		P3=0xff; //P3口置高防止矩阵键盘误触
		if(key2==0)
		{
			delayxms(10);
			if((key2==0))
			{
				led1=0;
				beep=0;
				time_backon=!time_backon; //倒计时功能开启或停止
			}
			while(!key2);
			delayxms(5);
			while(!key2);
		}
		else
		{
			led1=1;
			beep=1;
		}
	}
	
}

void resetall()	 //重置函数(归0或满值)
{
	if(modechoice==0)
	{
		if(time_forwardon==0)
		{
			P3=0xff;
			if(key3==0)
			{
				delayxms(10);
				if(key3==0)
				{
				 	led1=0;
					beep=0;
					s_f=0;
					s10_f=0;
					min_f=0;
					min10_f=0;
					hour_f=0;
					hour10_f=0;
				}
				while(!key3);
				delayxms(5);
				while(!key3);
			}
			else
			{
				led1=1;
				beep=1;
			}
	
			P3=0xff;
			if(key4==0)
			{
				delayxms(10);
				if(key4==0)
				{
				 	led1=0;
					beep=0;
					s_f=9;
					s10_f=5;
					min_f=9;
					min10_f=5;
					hour_f=3;
					hour10_f=2;
				}
				while(!key4);
				delayxms(5);
				while(!key4);
			}
			else
			{
				led1=1;
				beep=1;
			}
		}
	}	

	if(modechoice==1)
	{
		if(time_backon==0)
		{
			P3=0xff;
			if(key3==0)
			{
				delayxms(10);
				if(key3==0)
				{
				 	led1=0;
					beep=0;
					s_b=0;
					s10_b=0;
					min_b=0;
					min10_b=0;
					hour_b=0;
					hour10_b=0;
				}
				while(!key3);
				delayxms(5);
				while(!key3);
			}
			else
			{
				led1=1;
				beep=1;
			}
	
			P3=0xff;
			if(key4==0)
			{
				delayxms(10);
				if(key4==0)
				{
				 	led1=0;
					beep=0;
					s_b=9;
					s10_b=5;
					min_b=9;
					min10_b=5;
					hour_b=3;
					hour10_b=2;
				}
				while(!key4);
				delayxms(5);
				while(!key4);
			}
			else
			{
				led1=1;
				beep=1;
			}
		}
	}
}

void delayxms(uint xms) //延时函数 ms为单位
{
	uint x,y;
	for(x=xms;x>0;x--)
		for(y=124;y>0;y--);	
} 

void display() //数码管显示函数
{
	if(modechoice==0)
	{
		for(wei=0;wei<6;wei++)
		{
			switch(wei)
			{
				case 0: wedu(s_f,wei);break;
				case 1: wedu(s10_f,wei);break;
				case 2: wedu(min_f,wei);break;
				case 3: wedu(min10_f,wei);break;
				case 4: wedu(hour_f,wei);break;
				case 5: wedu(hour10_f,wei);break;
			}
			dula=1; //打开U1锁存端
			P0=0x00; //防止最高位数码管过亮
			dula=0; //关闭U1锁存端	
		}	
	}

	if(modechoice==1)
	{
		for(wei=0;wei<6;wei++)
		{
			switch(wei)
			{
				case 0: wedu(s_b,wei);break;
				case 1: wedu(s10_b,wei);break;
				case 2: wedu(min_b,wei);break;
				case 3: wedu(min10_b,wei);break;
				case 4: wedu(hour_b,wei);break;
				case 5: wedu(hour10_b,wei);break;
			}
			dula=1; //打开U1锁存端
			P0=0x00; //防止最高位数码管过亮
			dula=0; //关闭U1锁存端		
		}	
	} 
}

void wedu(uchar dula_num,uchar wela_num) //数码管位选段选函数
{
	wela=1; //打开U2锁存端
	P0=wela_table[wela_num]; //送入U2锁存端
	wela=0; //关闭U2锁存端
	P0=0xc0; //消影,防止P0残留电位信号干扰段选
	dula=1; //打开U1锁存端
	P0=dula_table[dula_num]; //送入段选信号
	dula=0; //关闭U1锁存端
	P0=0xff; //消影,防止P0残留电位信号干扰片选
	delayxms(1);
}

void T1_time() interrupt 3 //中断程序
{
	void timeforward(); //时间显示功能函数
	void timebackward(); //倒计时功能函数

	TH0=(65536-45872)/256; //装初值 50ms一次中断(45872) 5ms一次中断(4608)
        TL0=(65536-45872)%256; //装初值 50ms一次中断(45872) 5ms一次中断(4608)
	num_timer1++;
	if(num_timer1==20)  //num_timer1==20等价于1s
	{
		num_timer1=0;	 
		beep=0;
		delayxms(5);
		beep=1;
		delayxms(5);
		 
		if(time_forwardon==1) timeforward(); //时间显示功能函数
		if(time_backon==1) timebackward(); //倒计时功能函数 
	}
}

void timeforward() //时间显示功能函数
{
	s_f++;
	if(s_f==10)
	{
		s_f=0;
		s10_f++;
	}
	if(s10_f==6)
	{
		s10_f=0;
		min_f++;
	}
	if(min_f==10)
	{
		min_f=0;
		min10_f++;
	}
	if(min10_f==6)
	{
		min10_f=0;
		hour_f++;
	}
	if(hour_f==10)
	{
		hour_f=0;
		hour10_f++;
	}
	if((hour10_f==2)&&(hour_f==4))
	{
		hour10_f=0;
		hour_f=0;
		min10_f=0;
		min_f=0;
		s10_f=0;
		s_f=0;	
	}		
}

void timebackward() //倒计时功能函数
{
	s_b--;
	if(s_b==-1)
	{
		s_b=9;
		s10_b--;
	}
	if(s10_b==-1)
	{
		s10_b=5;
		min_b--;
	}
	if(min_b==-1)
	{
		min_b=9;
		min10_b--;
	}
	if(min10_b==-1)
	{
		min10_b=5;
		hour_b--;
	}
	if(hour_b==-1)
	{
		hour_b=9;
		hour10_b--;
	}
	if(hour10_b==-1)
	{
		hour10_b=0;
		hour_b=0;
		min10_b=0;
		min_b=0;
		s10_b=0;
		s_b=0;	
		judge=1; //倒计时结束
		while(judge)
		{
			display();	
			beep=0;
			delayxms(5000);
			beep=1;
			delayxms(5000);
			if((key3==0)||(key4==0)||(key1==0)||(key2==0)) //同时按下4个独立按键可以解除闹钟
			{
				delayxms(10);
				if((key3==0)||(key4==0)||(key1==0)||(key2==0))
				{
					led1=0;
					beep=0;
					hour10_b=2;
					hour_b=3;
					min10_b=5;
					min_b=9;
					s10_b=5;
					s_b=9;
					judge=0; //倒计时结束标志置0跳出循环
				}
				while((!key3)||(!key4)||(!key1)||(!key2));
				delayxms(5);
				while((!key3)||(!key4)||(!key1)||(!key2));
			}
			else
			{
				led1=1;
				beep=1;
			}
		}
	}			
		 			
}

void matrixkeyscan() //矩阵键盘输入函数
{

	if(modechoice==0)
	{
		if(time_forwardon==0)
		{
			P3=matrixkeyboard_row_table[2];
			temp=P3;
			temp=temp&0xf0;
			if(temp!=0xf0)
			{
				delayxms(10);
				temp=P3;
				temp=temp&0xf0;
				if(temp!=0xf0)
				{
					temp=P3;
					if(temp==matrixkeyboard_table[8])
					{
									 				led1=0;
						beep=0;
						min_f++;
						if(min_f==10) 
						{
							min_f=0;
							min10_f++;
							if(min10_f==6) min10_f=0;
						}
					}
					if(temp==matrixkeyboard_table[9])
					{
				 		led1=0;
						beep=0;
						min_f--;
						if(min_f==-1) 
						{
							min_f=9;
							min10_f--;
							if(min10_f==-1) min10_f=5;
						}
					}
					if(temp==matrixkeyboard_table[10])
					{
				 		led1=0;
						beep=0;
						min_f=0;
						min10_f=0;
					 }
					if(temp==matrixkeyboard_table[11])
					{
				 		led1=0;
						beep=0;
						min_f=9;
						min10_f=5;
					}
					while(temp!=0xf0)
					{
						temp=P3;
						temp=temp&0xf0;
					}
				}
			}
		
			P3=matrixkeyboard_row_table[1];
			temp=P3;
			temp=temp&0xf0;
			if(temp!=0xf0)
			{
				delayxms(10);
				temp=P3;
				temp=temp&0xf0;
				if(temp!=0xf0)
				{
					temp=P3;
					if(temp==matrixkeyboard_table[4])
					{
				 		led1=0;
						beep=0;
						hour_f++;
						if(hour_f==10) 
						{
							hour_f=0;
							hour10_f++;
						}
						if((hour10_f==2)&&(hour_f==4)) 
						{
							hour10_f=0;
							hour_f=0;
						}
					}
					if(temp==matrixkeyboard_table[5])
					{
						led1=0;
						beep=0;
						hour_f--;	    
						if((hour10_f==0)&&(hour_f==-1)) 
						{
							hour10_f=2;
							hour_f=3;
						}
						else if((hour_f==-1)&&(hour10_f!=0)) 
						{
							hour_f=9;
							hour10_f--;
						}
					}
					if(temp==matrixkeyboard_table[6])
					{
				 		led1=0;
						beep=0;
						hour_f=0;
						hour10_f=0;
					}
					if(temp==matrixkeyboard_table[7])
					{
				 		led1=0;
						beep=0;
						hour_f=3;
						hour10_f=2;
					}
					while(temp!=0xf0)
					{
						temp=P3;
						temp=temp&0xf0;
					}
				}
		
			}
	
			P3=matrixkeyboard_row_table[3];
			temp=P3;
			temp=temp&0xf0;
			if(temp!=0xf0)
			{
				delayxms(10);
				temp=P3;
				temp=temp&0xf0;
				if(temp!=0xf0)
				{
					temp=P3;
					if(temp==matrixkeyboard_table[12])
					{
				 		led1=0;
						beep=0;
						s_f++;
						if(s_f==10) 
						{
							s_f=0;
							s10_f++; 	
							if(s10_f==6) s10_f=0;
						}	
					 }
					if(temp==matrixkeyboard_table[13])
					{
				 		led1=0;
						beep=0;
						s_f--;	    
						if(s_f==-1) 
						{
							s_f=9;
							s10_f--;
							if(s10_f==-1) s10_f=5;
						}
					}
					if(temp==matrixkeyboard_table[14])
					{
				 		led1=0;
						beep=0;
						s_f=0;
						s10_f=0;
					}
					if(temp==matrixkeyboard_table[15])
					{
				 		led1=0;
						beep=0;
						s_f=9;
						s10_f=5;
					}
					while(temp!=0xf0)
					{
						temp=P3;
						temp=temp&0xf0;
					}
				}
			}	
		}
	}
	if(modechoice==1)
	{
		if(time_backon==0)
		{
			P3=matrixkeyboard_row_table[2];
			temp=P3;
			temp=temp&0xf0;
			if(temp!=0xf0)
			{
				delayxms(10);
				temp=P3;
				temp=temp&0xf0;
				if(temp!=0xf0)
				{
					temp=P3;
					if(temp==matrixkeyboard_table[8])
					{
									 				led1=0;
						beep=0;
						min_b++;
						if(min_b==10) 
						{
							min_b=0;
							min10_b++;
							if(min10_b==6) min10_b=0;
						}
					}
					if(temp==matrixkeyboard_table[9])
					{
				 		led1=0;
						beep=0;
						min_b--;
						if(min_b==-1) 
						{
							min_b=9;
							min10_b--;
							if(min10_b==-1) min10_b=5;
						}
					}
					if(temp==matrixkeyboard_table[10])
					{
				 		led1=0;
						beep=0;
						min_b=0;
						min10_b=0;
					 }
					if(temp==matrixkeyboard_table[11])
					{
				 		led1=0;
						beep=0;
						min_b=9;
						min10_b=5;
					}
					while(temp!=0xf0)
					{
						temp=P3;
						temp=temp&0xf0;
					}
				}
			}
		
			P3=matrixkeyboard_row_table[1];
			temp=P3;
			temp=temp&0xf0;
			if(temp!=0xf0)
			{
				delayxms(10);
				temp=P3;
				temp=temp&0xf0;
				if(temp!=0xf0)
				{
					temp=P3;
					if(temp==matrixkeyboard_table[4])
					{
				 		led1=0;
						beep=0;
						hour_b++;
						if(hour_b==10) 
						{
							hour_b=0;
							hour10_b++;
						}
						if((hour10_b==2)&&(hour_f==4)) 
						{
							hour10_b=0;
							hour_b=0;
						}
					}
					if(temp==matrixkeyboard_table[5])
					{
						led1=0;
						beep=0;
						hour_b--;	    
						if((hour10_b==0)&&(hour_b==-1)) 
						{
							hour10_b=2;
							hour_b=3;
						}
						else if((hour_b==-1)&&(hour10_b!=0)) 
						{
							hour_b=9;
							hour10_b--;
						}
					}
					if(temp==matrixkeyboard_table[6])
					{
				 		led1=0;
						beep=0;
						hour_b=0;
						hour10_b=0;
					}
					if(temp==matrixkeyboard_table[7])
					{
				 		led1=0;
						beep=0;
						hour_b=3;
						hour10_b=2;
					}
					while(temp!=0xf0)
					{
						temp=P3;
						temp=temp&0xf0;
					}
				}
		
			}
	
			P3=matrixkeyboard_row_table[3];
			temp=P3;
			temp=temp&0xf0;
			if(temp!=0xf0)
			{
				delayxms(10);
				temp=P3;
				temp=temp&0xf0;
				if(temp!=0xf0)
				{
					temp=P3;
					if(temp==matrixkeyboard_table[12])
					{
				 		led1=0;
						beep=0;
						s_b++;
						if(s_b==10) 
						{
							s_b=0;
							s10_b++; 	
							if(s10_b==6) s10_b=0;
						}	
					 }
					if(temp==matrixkeyboard_table[13])
					{
				 		led1=0;
						beep=0;
						s_b--;	    
						if(s_b==-1) 
						{
							s_b=9;
							s10_b--;
							if(s10_b==-1) s10_b=5;
						}
					}
					if(temp==matrixkeyboard_table[14])
					{
				 		led1=0;
						beep=0;
						s_b=0;
						s10_b=0;
					}
					if(temp==matrixkeyboard_table[15])
					{
				 		led1=0;
						beep=0;
						s_b=9;
						s10_b=5;
					}
					while(temp!=0xf0)
					{
						temp=P3;
						temp=temp&0xf0;
					}
				}
		
			}
		}
	}
	P3=matrixkeyboard_row_table[0];
	temp=P3;
	temp=temp&0xf0;
	if(temp!=0xf0)
	{
		delayxms(10);
		temp=P3;
		temp=temp&0xf0;
		if(temp!=0xf0)
		{
			temp=P3;
			if(temp==matrixkeyboard_table[0]||temp==matrixkeyboard_table[1]||temp==matrixkeyboard_table[2]||temp==matrixkeyboard_table[3])
			{
				judge=1;
				while(judge)
				{
					hour10_b=0;
					hour_b=0;
					min10_b=0;
					min_b=0;
					s10_b=0;
					s_b=0;	
					beep=0;
					delayxms(5000);
					beep=1;
					delayxms(5000);
					if((key3==0)||(key4==0)||(key1==0)||(key2==0))
					{
						delayxms(10);
						if((key3==0)||(key4==0)||(key1==0)||(key2==0))
						{
							led1=0;
							beep=0;
							hour10_b=2;
							hour_b=3;
							min10_b=5;
							min_b=9;
							s10_b=5;
							s_b=9;
							judge=0;
						}
							while((!key3)||(!key4)||(!key1)||(!key2));
							delayxms(5);
							while((!key3)||(!key4)||(!key1)||(!key2));
					}
					else
					{
						led1=1;
						beep=1;
					}
				}
			}
			while(temp!=0xf0)
			{
				temp=P3;
				temp=temp&0xf0;
			}
		}
	}
}

参考资料: 

[1] 郭天祥. 新概念51单片机C语言教程:入门、提高、开发、拓展全攻略[M]. 北京: 电子工业出版社, 2009. 

  • 23
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C51单片机矩阵键盘4x4的实现方法如下: 1. 矩阵键盘原理是将按键按下后的电信号通过行列扫描方式转化为数字信号输入到单片机中。 2. 在C51单片机中,需要将矩阵键盘的行和列分别连接到单片机的GPIO口。 3. 程序中需要循环扫描矩阵键盘的每一行和每一列,检测是否有按键按下。 4. 如果检测到按键按下,就需要通过行列坐标计算出按键的编号,然后将该编号作为输入信号传输给单片机。 5. 单片机在接收到按键信号后,就可以根据程序中预先定义好的按键编号对应功能来执行相应操作。 下面是一个简单的C语言程序示例: ``` #include "reg52.h" sbit Row_1 = P1^0; // 矩阵键盘第1行 sbit Row_2 = P1^1; // 矩阵键盘第2行 sbit Row_3 = P1^2; // 矩阵键盘第3行 sbit Row_4 = P1^3; // 矩阵键盘第4行 sbit Col_1 = P1^4; // 矩阵键盘第1列 sbit Col_2 = P1^5; // 矩阵键盘第2列 sbit Col_3 = P1^6; // 矩阵键盘第3列 sbit Col_4 = P1^7; // 矩阵键盘第4列 unsigned char Key_Table[4][4] = // 键盘矩阵 { {'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', 'C'}, {'*', '0', '#', 'D'} }; void main() { unsigned char i, j, key_value; while(1) { for(i = 0; i < 4; i++) // 扫描行 { switch(i) { case 0: Row_1 = 0; Row_2 = 1; Row_3 = 1; Row_4 = 1; break; case 1: Row_1 = 1; Row_2 = 0; Row_3 = 1; Row_4 = 1; break; case 2: Row_1 = 1; Row_2 = 1; Row_3 = 0; Row_4 = 1; break; case 3: Row_1 = 1; Row_2 = 1; Row_3 = 1; Row_4 = 0; break; } for(j = 0; j < 4; j++) // 检测列 { if(Col_1 == 0 && j == 0) key_value = Key_Table[i][j]; if(Col_2 == 0 && j == 1) key_value = Key_Table[i][j]; if(Col_3 == 0 && j == 2) key_value = Key_Table[i][j]; if(Col_4 == 0 && j == 3) key_value = Key_Table[i][j]; } } if(key_value != 0) // 如果有按键按下,则输出按键值 { P2 = key_value; key_value = 0; } } } ``` 在上述程序中,将矩阵键盘的行和列分别连接到单片机的P1口,并定义了键盘矩阵和按键值等变量。然后使用嵌套循环扫描矩阵键盘的每一行和每一列,并根据行列坐标计算出按键的编号。最后将该编号作为输入信号传输给单片机,并根据预先定义的按键编号对应功能来执行相应操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值