9.矩陣鍵盤的使用

實現原理:令其中某一行或某一列爲0(等同於獨立鍵盤的接地),判斷對應的位置的列或行是否爲0,從而確定是哪一個按鍵被按下。(注意跳線帽位置的更改)
學習時使用的平臺爲CT107S,原理圖如下:
在這裏插入圖片描述
其與競賽用的官方平臺CT107D不同在於WR、RD對應的引腳不同,CT107D原理圖如下:(CT107D電路是爲52單片機所設計,需使用IAP15F2K60S轉接板,經轉接板後WR,RD也爲P42,P44,也即程序仍使用的P42,P44,而並非如下圖的直接使用P36,P37,本人在此曾有迷惑)
在這裏插入圖片描述
轉接板原理圖參考如下:
在這裏插入圖片描述
矩陣鍵盤第一列按鍵控制L1~L4點亮

#include<STC15F2K60S2.H>
void KEY_Scan(void);
void Delayms(int ms);

void main(void)
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;   //初始化程序
	while(1)
	{
		KEY_Scan();
	}
}

void KEY_Scan(void)
{
	P44=0;
	if(P30==0)					//S7
	{	
		Delayms(5);
		if(P30==0)
		{
			P00=0;				//L1亮
		}
		while(!P30);
	}
	else if(P31==0)				//S6
	{
		Delayms(5);
		if(P31==0)
		{
			P01=0;				//L2亮
		}
		while(!P31);
	}
	else if(P32==0)				//S5
	{	
		Delayms(5);
		if(P32==0)
		{
			P02=0;				//L3亮
		}
		while(!P32);
	}
	else if(P33==0)				//S4
	{
		Delayms(5);
		if(P33==0)
		{
			P03=0;				//L4亮
		}
		while(!P33);
	}
}

void Delayms(int ms)
{
	int i,j;
	for(i=0;i<ms;i++)
		for(j=845;j>0;j--);
}

矩陣鍵盤第一列按鍵控制L1-L4點亮,第二列控制L5~L8點亮

#include<STC15F2K60S2.H>
void Delayms(int ms);
void KEY_Scan(void);

void main(void)
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;   //初始化程序
	while(1)
	{
		KEY_Scan();
	}
}

void Delayms(int ms)
{
	int i,j;
	for(i=0;i<ms;i++)
		for(j=845;j>0;j--);
}

void KEY_Scan(void)
{
	P44=0;P42=1;						//第一列
	if((P30==0)&&(P44==0))				//S7
	{
		Delayms(5);
		if(P30==0)
		{
			P00=0;						//L1亮
		}
		while(!P30);
	}
	else if((P31==0)&&(P44==0))			//S6
	{
		Delayms(5);
		if(P31==0)
		{
			P01=0;						//L2亮
		}
		while(!P31);
	}
	else if((P32==0)&&(P44==0))			//S5
	{
		Delayms(5);
		if(P32==0)
		{
			P02=0;						//L3亮
		}
		while(!P32);
	}
	else if((P33==0)&&(P44==0))			//S4
	{
		Delayms(5);
		if(P33==0)
		{
			P03=0;						//L4亮
		}
		while(!P33);
	}
	P42=0;P44=1;						//第二列
	if((P30==0)&&(P42==0))				//S11
	{
		Delayms(5);
		if(P30==0)
		{
			P04=0;						//L5亮
		}
		while(!P30);
	}
	else if((P31==0)&&(P42==0))			//S10
	{
		Delayms(5);
		if(P31==0)
		{
			P05=0;						//L6亮
		}
		while(!P31);
	}
	else if((P32==0)&&(P42==0))			//S9
	{
		Delayms(5);
		if(P32==0)
		{
			P06=0;						//L7亮
		}
		while(!P32);
	}
	else if((P33==0)&&(P42==0))			//S8
	{
		Delayms(5);
		if(P33==0)
		{
			P07=0;						//L8亮
		}
		while(!P33);
	}
}

矩陣鍵盤16按鍵控制數碼管顯示,按列掃描程序:

#include<STC15F2K60S2.H>
unsigned char tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0X88,0X83,0XC6,0XA1,0X86,0X8E};
//定義一個數組,保存數碼管顯示所需的P0值,0~F

void Delayms(int ms);
void KEY_Scan16(void);					//爲了與獨立按鍵函數相區別

void main(void)
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;   //初始化程序
	P2=0XC0;P0=0X01;P2=0XFF;P0=0XFF;   //數碼管初始化程序,打開第一個數碼管
	while(1)
	{
		KEY_Scan16();
	}
}

void Delayms(int ms)
{
	int i,j;
	for(i=0;i<ms;i++)
		for(j=845;j>0;j--);
}

void KEY_Scan16(void)
{
	unsigned char temp;
	
	//第一列	0111 1111
	P44=0;P42=1;P3=0X7F;					//此步驟個人認爲相當於初始化矩陣鍵盤
	//注意官方原理圖上,P37,P38和P42,P44的關係,程序使用引腳爲P44,P42,請參考轉接板原理圖
	temp=P3;
	temp=temp&0X0F;							//如果不進行與運算,由於無法得知高四位的值,無法編寫if程序
	if(temp!=0X0F)							//如果此時有按鍵被按下,temp將不再是0X0F
	{
		Delayms(5);							//消抖
		temp=P3;
		temp=temp&0X0F;			//與之前消抖所用不同,temp爲變量,如果不進行重新掃描賦值,temp將不會發生變化,消抖不起作用
		if(temp!=0X0F)
		{
			temp=P3;
			switch(temp)
			{
				case 0X7E:P0=tab[1];break;//S7,1
				case 0X7D:P0=tab[2];break;//S6,2
				case 0X7B:P0=tab[3];break;//S5,3
				case 0X77:P0=tab[4];break;//S4,4
			}
		}
		while(temp!=0X0F)
		{
			temp=P3;
			temp=temp&0X0F;			//重新掃描判斷按鍵狀態,若賦值步驟,上一步進行完後恰好滿足循環條件將一直死循環下去
		}
	}
	//第二列	1011 1111
	P44=1;P42=0;P3=0XBF;
	temp=P3;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
		Delayms(5);
		temp=P3;
		temp=temp&0X0F;
		if(temp!=0X0F)
		{
			temp=P3;
			switch(temp)
			{
				case 0XBE:P0=tab[5];break;//S11,5
				case 0XBD:P0=tab[6];break;//S10,6
				case 0XBB:P0=tab[7];break;//S9,7
				case 0XB7:P0=tab[8];break;//S8,8
			}
		}
		while(temp!=0X0F)
		{
			temp=P3;
			temp=temp&0X0F;
		}
	}
	//第三列	1101 1111
	P44=1;P42=1;P3=0XDF;
	temp=P3;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
		Delayms(5);
		temp=P3;
		temp=temp&0X0F;
		if(temp!=0X0F)
		{
			temp=P3;
			switch(temp)
			{
				case 0XDE:P0=tab[9];break;//S15,9
				case 0XDD:P0=tab[10];break;//S14,A
				case 0XDB:P0=tab[11];break;//S13,b
				case 0XD7:P0=tab[12];break;//S12,C
			}
		}
		while(temp!=0X0F)
		{
			temp=P3;
			temp=temp&0X0F;
		}
	}
	//第四列	1110 1111
	P44=1;P42=1;P3=0XEF;
	temp=P3;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
		Delayms(5);
		temp=P3;
		temp=temp&0X0F;
		if(temp!=0X0F)
		{
			temp=P3;
			switch(temp)
			{
				case 0XEE:P0=tab[13];break;//S19,d
				case 0XED:P0=tab[14];break;//S18,E
				case 0XEB:P0=tab[15];break;//S17,F
				case 0XE7:P0=tab[0];break;//S16,0
			}
		}
		while(temp!=0X0F)
		{
			temp=P3;
			temp=temp&0X0F;
		}
	}
}

注:如果switch前沒有temp=P3的重新賦值,所有的case裏面高4位均爲一致的0,可能出現此時P3按鍵值已發生變化但是用於判斷的變量仍爲原來的,從而造成誤判
另一種簡化寫法:

#include<STC15F2K60S2.H>
unsigned char tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0X88,0X83,0XC6,0XA1,0X86,0X8E};
unsigned char num;

void KEY_Scan16(void);

void Delayms(int ms);

void main(void)
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;   //初始化程序
	P2=0XC0;P0=0X01;P2=0XFF;P0=0XFF;   //數碼管初始化程序,打開第一個數碼管
	while(1)
	{
		KEY_Scan16();
		P0=tab[num];
	}
}

void Delayms(int ms)
{
	int i,j;
	for(i=0;i<ms;i++)
		for(j=845;j>0;j--);
}

void KEY_Scan16(void)
{
	unsigned char temp;
	
	P44=0;P42=1;P3=0X7F;		//第一列
	temp=P3;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
		Delayms(5);
		temp=P3;
		temp=temp&0X0F;
		if(temp!=0X0F)
		{
			temp=P3;
			switch(temp)
			{
				case 0X7E:num=1;break;//S7,1
				case 0X7D:num=2;break;//S6,2
				case 0X7B:num=3;break;//S5,3
				case 0X77:num=4;break;//S4,4
			}
		}
		while(temp!=0X0F)
		{
			temp=P3;
			temp=temp&0X0F;
		}
	}
	
	P44=1;P42=0;P3=0XBF;		//第二列
	temp=P3;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
		Delayms(5);
		temp=P3;
		temp=temp&0X0F;
		if(temp!=0X0F)
		{
			temp=P3;
			switch(temp)
			{
				case 0XBE:num=5;break;//S11,5
				case 0XBD:num=6;break;//S10,6
				case 0XBB:num=7;break;//S9,7
				case 0XB7:num=8;break;//S8,8
			}
		}
		while(temp!=0X0F)
		{
			temp=P3;
			temp=temp&0X0F;
		}
	}
	
	P44=1;P42=1;P3=0XDF;		//第三列
	temp=P3;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
		Delayms(5);
		temp=P3;
		temp=temp&0X0F;
		if(temp!=0X0F)
		{
			temp=P3;
			switch(temp)
			{
				case 0XDE:num=9;break;//S13,9
				case 0XDD:num=10;break;//S14,A
				case 0XDB:num=11;break;//S13,b
				case 0XD7:num=12;break;//S12,C
			}
		}
		while(temp!=0X0F)
		{
			temp=P3;
			temp=temp&0X0F;
		}
	}
	
	P44=1;P42=1;P3=0XEF;		//第四列
	temp=P3;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
		Delayms(5);
		temp=P3;
		temp=temp&0X0F;
		if(temp!=0X0F)
		{
			temp=P3;
			switch(temp)
			{
				case 0XEE:num=13;break;//S19,d
				case 0XED:num=14;break;//S18,E
				case 0XEB:num=15;break;//S17,F
				case 0XE7:num=0;break;//S16,0
			}
		}
		while(temp!=0X0F)
		{
			temp=P3;
			temp=temp&0X0F;
		}
	}
}

注:此程序運行後一個現象是數碼管初始即顯示0,因爲定義num默認爲0
如果CT107D使用的是STC8的轉接板,則需將P42改爲P43(STC8的WR引腳在P43),如果是CT107S使用STC8轉接板,則無需更改。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章