【單片機】— {STC15}—{矩陣鍵盤&Proteus}

矩陣鍵盤

Proteus仿真

一、Proteus仿真STC15的問題

            > 據說P0口存在BUG,不會被正常拉低,而是產生短路。

二、原理圖

1、CPU

在這裏插入圖片描述

2、矩陣鍵盤

在這裏插入圖片描述

3、顯示部分

在這裏插入圖片描述

程序

一、矩陣鍵盤_單行掃描_普通寫法

#include<STC15.H>
#include<intrins.h>

#define uchar unsigned char
#define uint unsigned int
#define KeyBus P6    //定義矩陣鍵盤接口

uchar Key_res =0; 
uchar i=0;

void GPIO(void);    //IO口初始化函數
void Delay10ms();		//@12.000MHz
void Delay5ms();		//@12.000MHz
void Delay1ms();	  //@12.000MHz
uchar Key16_Scan(void);//矩陣鍵盤掃描函數子程序
void Key16_Function(void); //矩陣鍵盤服務(功能)子函數

void main(void)
{
    GPIO();

	while(1) 
	{
		Key_res =0; 
		i=Key16_Scan();   //矩陣鍵盤掃描函數子程序
        Key16_Function(); //矩陣鍵盤服務(功能)子函數
	}
}

//-----------------------------------IO口初始化函數-----------------------------//
void GPIO(void)
{
	P0M1=0;
	P0M0=0;
	P1M1=0;
	P1M0=0;
	P2M1=0;
	P2M0=0;
	P3M1=0;
	P3M0=0;
	P4M1=0;
	P4M0=0;
	P5M1=0;
	P5M0=0;
}

//------------------------------------軟件延時---------------------------------------//
void Delay10ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 117;
	j = 184;
	do
	{
		while (--j);
	} while (--i);
}

void Delay5ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 59;
	j = 90;
	do
	{
		while (--j);
	} while (--i);
}

void Delay1ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 12;
	j = 169;
	do
	{
		while (--j);
	} while (--i);
}



//---------------------------------------矩陣鍵盤掃描函數子程序-------------------------//

uchar Key16_Scan(void)
{
	uchar temp = 0;
	uchar Key_res = 0;
	
    KeyBus = 0XFF;	
	KeyBus = 0X7F;	 //0111 1111 掃描第一行
 	temp=KeyBus;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
	  Delay10ms();   //按鍵消抖
	  temp=KeyBus;
	  temp=temp&0X0F; 
	  if(temp!=0X0F)
		{
			temp=temp&0X0F;
			switch(temp)
			{
				case 0X0E: Key_res=16;break;
				case 0X0D: Key_res=15;break;
				case 0X0B: Key_res=14;break;
				case 0X07: Key_res=13;break;
				default: break;
			}
			while(temp!=0X0F)     //鬆手檢測
			{
				temp=KeyBus;
				temp=temp&0X0F;
			}	
		}
	}
	
	KeyBus = 0XFF;
	KeyBus = 0XBF;	 //1011 1111  掃描第二行
 	temp=KeyBus;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
	  Delay10ms();
	  temp=KeyBus;
	  temp=temp&0X0F;
	  if(temp!=0X0F)
		{
			temp=temp&0X0F;
			switch(temp)
			{
				case 0X0E: Key_res=12;break;
				case 0X0D: Key_res=11;break;
				case 0X0B: Key_res=10;break;
				case 0X07: Key_res=9;break;
				default: break;
			}
			while(temp!=0X0F)     //鬆手檢測
			{
				temp=KeyBus;
				temp=temp&0X0F;
			}	
		}
	}

	KeyBus = 0XFF;	
	KeyBus = 0XDF;	 //1101 1111  掃描第三行
 	temp=KeyBus;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
	  Delay10ms();
	  temp=KeyBus;
	  temp=temp&0X0F;
	  if(temp!=0X0F)
		{
			temp=temp&0X0F;
			switch(temp)
			{
				case 0X0E: Key_res=8;break;
				case 0X0D: Key_res=7;break;
				case 0X0B: Key_res=6;break;
				case 0X07: Key_res=5;break;
				default: break;
			}
			while(temp!=0X0F)    //鬆手檢測
			{
				temp=KeyBus;
				temp=temp&0X0F;
			}	
		}
	}

	KeyBus = 0XFF;	
	KeyBus = 0XEF;	 //1110 1111  掃描第四行
 	temp=KeyBus;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
	  Delay10ms();
	  temp=KeyBus;
	  temp=temp&0X0F;
	  if(temp!=0X0F)
		{
			temp=temp&0X0F;
			switch(temp)
			{
				case 0X0E: Key_res=4;break;
				case 0X0D: Key_res=3;break;
				case 0X0B: Key_res=2;break;
				case 0X07: Key_res=1;break;
				default: break;
			}
			while(temp!=0X0F)     //鬆手檢測
			{
				temp=KeyBus;
				temp=temp&0X0F;
			}	
		}
	}
	return Key_res;
}


//-----------------------------------矩陣鍵盤服務(功能)子函數-------------------//
void Key16_Function(void) 
{
	if(i != 0)
		{
			switch(i)
			{
			  case  1: P1=0XFE;P2=0XFF;break;
			  case  2: P1=0XFD;P2=0XFF;break;
		      case  3: P1=0XFB;P2=0XFF;break;
		      case  4: P1=0XF7;P2=0XFF;break;
			  case  5: P1=0XEF;P2=0XFF;break;
			  case  6: P1=0XDF;P2=0XFF;break;
			  case  7: P1=0XBF;P2=0XFF;break;
			  case  8: P1=0X7F;P2=0XFF;break;
			  case  9: P1=0XFF;P2=0XFE;break;
			  case 10: P1=0XFF;P2=0XFD;break;
			  case 11: P1=0XFF;P2=0XFB;break;
			  case 12: P1=0XFF;P2=0XF7;break;
			  case 13: P1=0XFF;P2=0XEF;break;
			  case 14: P1=0XFF;P2=0XDF;break;
			  case 15: P1=0XFF;P2=0XBF;break;
			  case 16: P1=0XFF;P2=0X7F;break;
			  default:P1=0X00;P2=0X00;break;
			}
	}
}

二、矩陣鍵盤_單行掃描_外部中斷

(代碼未能實現,改進ing)

#include<STC15.H>
#include<intrins.h>


#define uchar unsigned char
#define uint unsigned int
#define KeyBus P6    //定義矩陣鍵盤接口

uchar Key_res =0; 
uchar i=0;

void GPIO(void);    //IO口初始化函數
void Delay10ms();		//@12.000MHz
void Delay5ms();		//@12.000MHz
void Delay1ms();	  //@12.000MHz
void INT1_INIT(void);    //外部中斷1初始化函數
uchar Key16_Scan(void);//矩陣鍵盤掃描函數子程序
void Key16_Function(void); //矩陣鍵盤服務(功能)子函數

void main(void)
{
  GPIO();
  INT1_INIT();
	while(1) 
	{
	   KeyBus=0X0F;		
       Key16_Function(); //矩陣鍵盤服務(功能)子函數
	}
}

//-----------------------------------IO口初始化函數-----------------------------//
void GPIO(void)
{
	P0M1=0;
	P0M0=0;
	P1M1=0;
	P1M0=0;
	P2M1=0;
	P2M0=0;
	P3M1=0;
	P3M0=0;
	P4M1=0;
	P4M0=0;
	P5M1=0;
	P5M0=0;

}

//------------------------------------軟件延時---------------------------------------//
void Delay10ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 117;
	j = 184;
	do
	{
		while (--j);
	} while (--i);
}

void Delay5ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 59;
	j = 90;
	do
	{
		while (--j);
	} while (--i);
}

void Delay1ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 12;
	j = 169;
	do
	{
		while (--j);
	} while (--i);
}

//---------------------------------------外部中斷1初始化函數-----------------------------//
void INT1_INIT(void)
{
	IT1=1;
	EX1=1;
  EA=1;

}

//---------------------------------------矩陣鍵盤掃描函數子程序-------------------------//

uchar Key16_Scan(void)
{
	uchar temp = 0;
	uchar Key_res = 0;
	
    KeyBus = 0XFF;	
	KeyBus = 0X7F;	 //0111 1111
 	temp=KeyBus;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
	  Delay10ms();
	  temp=KeyBus;
	  temp=temp&0X0F;
	  if(temp!=0X0F)
		{
			temp=temp&0X0F;
			switch(temp)
			{
				case 0X0E: Key_res=16;break;
				case 0X0D: Key_res=15;break;
				case 0X0B: Key_res=14;break;
				case 0X07: Key_res=13;break;
				default: break;
			}
			while(temp!=0X0F)     //鬆手檢測
			{
				temp=KeyBus;
				temp=temp&0X0F;
			}	
		}
	}
	
	KeyBus = 0XFF;
	KeyBus = 0XBF;	 //1011 1111
 	temp=KeyBus;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
	  Delay10ms();
	  temp=KeyBus;
	  temp=temp&0X0F;
	  if(temp!=0X0F)
		{
			temp=temp&0X0F;
			switch(temp)
			{
				case 0X0E: Key_res=12;break;
				case 0X0D: Key_res=11;break;
				case 0X0B: Key_res=10;break;
				case 0X07: Key_res=9;break;
				default: break;
			}
			while(temp!=0X0F)     //鬆手檢測
			{
				temp=KeyBus;
				temp=temp&0X0F;
			}	
		}
	}

	KeyBus = 0XFF;	
	KeyBus = 0XDF;	 //1101 1111
 	temp=KeyBus;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
	  Delay10ms();
      temp=KeyBus;
	  temp=temp&0X0F;
	  if(temp!=0X0F)
		{
			temp=temp&0X0F;
			switch(temp)
			{
				case 0X0E: Key_res=8;break;
				case 0X0D: Key_res=7;break;
				case 0X0B: Key_res=6;break;
				case 0X07: Key_res=5;break;
				default: break;
			}
			while(temp!=0X0F)    //鬆手檢測
			{
				temp=KeyBus;
				temp=temp&0X0F;
			}	
		}
	}

	KeyBus = 0XFF;	
	KeyBus = 0XEF;	 //1110 1111
 	temp=KeyBus;
	temp=temp&0X0F;
	if(temp!=0X0F)
	{
      Delay10ms();
	  temp=KeyBus;
	  temp=temp&0X0F;
	  if(temp!=0X0F)
		{
			temp=temp&0X0F;
			switch(temp)
			{
				case 0X0E: Key_res=4;break;
				case 0X0D: Key_res=3;break;
				case 0X0B: Key_res=2;break;
				case 0X07: Key_res=1;break;
				default: break;
			}
			while(temp!=0X0F)     //鬆手檢測
			{
				temp=KeyBus;
				temp=temp&0X0F;
			}	
		}
	}
	return Key_res;
}

//--------------------------------------外部中斷1服務函數-----------------------------//
void INT1_ISR() interrupt 2
{
		i = Key16_Scan();   //矩陣鍵盤掃描函數子程序
}



//-----------------------------------矩陣鍵盤服務(功能)子函數-------------------//
void Key16_Function(void) 
{
	if(i != 0)
		{
			switch(i)
			{
			  case  1: P1=0XFE;P2=0XFF;break;
			  case  2: P1=0XFD;P2=0XFF;break;
		      case  3: P1=0XFB;P2=0XFF;break;
		      case  4: P1=0XF7;P2=0XFF;break;
			  case  5: P1=0XEF;P2=0XFF;break;
			  case  6: P1=0XDF;P2=0XFF;break;
			  case  7: P1=0XBF;P2=0XFF;break;
			  case  8: P1=0X7F;P2=0XFF;break;
			  case  9: P1=0XFF;P2=0XFE;break;
			  case 10: P1=0XFF;P2=0XFD;break;
			  case 11: P1=0XFF;P2=0XFB;break;
			  case 12: P1=0XFF;P2=0XF7;break;
			  case 13: P1=0XFF;P2=0XEF;break;
			  case 14: P1=0XFF;P2=0XDF;break;
			  case 15: P1=0XFF;P2=0XBF;break;
			  case 16: P1=0XFF;P2=0X7F;break;
			  default:P1=0X00;P2=0X00;break;
			}
	}
}


三、矩陣鍵盤_多行掃描_普通寫法

#include<STC15.H>
#include<intrins.h>

#define uchar unsigned char
#define uint unsigned int
#define KeyBus P6    //定義矩陣鍵盤接口

uchar Key_res =0; 
uchar i=0;

void GPIO(void);    //IO口初始化函數
void Delay10ms();		//@12.000MHz
void Delay5ms();		//@12.000MHz
void Delay1ms();	  //@12.000MHz
uchar Key16_Scan(void);//矩陣鍵盤掃描函數子程序
void Key16_Function(void); //矩陣鍵盤服務(功能)子函數

void main(void)
{
  GPIO();    //IO口初始化函數

	while(1) 
	{
		Key_res =0; 
		i=Key16_Scan();   //矩陣鍵盤掃描函數子程序
    Key16_Function(); //矩陣鍵盤服務(功能)子函數
	}
}

//-----------------------------------IO口初始化函數-----------------------------//
void GPIO(void)
{
	P0M1=0;
	P0M0=0;
	P1M1=0;
	P1M0=0;
	P2M1=0;
	P2M0=0;
	P3M1=0;
	P3M0=0;
	P4M1=0;
	P4M0=0;
	P5M1=0;
	P5M0=0;

}

//------------------------------------軟件延時---------------------------------------//
void Delay10ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 117;
	j = 184;
	do
	{
		while (--j);
	} while (--i);
}

void Delay5ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 59;
	j = 90;
	do
	{
		while (--j);
	} while (--i);
}

void Delay1ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 12;
	j = 169;
	do
	{
		while (--j);
	} while (--i);
}



//---------------------------------------矩陣鍵盤掃描函數子程序-------------------------//

uchar Key16_Scan(void)
{
	uchar X_temp = 0,Y_temp = 0;
	uchar Key_down = 0;
	
	KeyBus = 0XFF;	
	KeyBus = 0X0F;	//高4位置0,低4位置1,此時有按鍵按下時,低四位的某一位會被拉低,由此定位按下的按鍵在第幾列
	Y_temp = KeyBus&0X0F;
	
	if(Y_temp!=0X0F)	//如果檢測到某列有按鍵按下(有按鍵按下時,低四位會有一位被拉低)
	{
		Delay5ms();    //按鍵消抖(不知道有無必要)
		KeyBus = 0X0F; 	
	    Y_temp = KeyBus&0X0F;//將KeyBus低四位的按鍵信息賦值給Y_temp
		if(Y_temp!=0X0F)
		{
			KeyBus = 0X0F;
			Y_temp = KeyBus&0X0F;  //將KeyBus低四位的按鍵信息賦值給Y_temp,反應列信息
			KeyBus = 0XF0;
			X_temp = KeyBus&0XF0;  //將KeyBus高四位的按鍵信息賦值給X_temp,反應行信息
			if(Key_down == 0)      //按鍵擡起檢測,	
			{
			  switch(Y_temp)    //判斷列
			  {
				  case 0X07: Key_res=1; break;
				  case 0X0B: Key_res=2; break;
				  case 0X0D: Key_res=3; break;
				  case 0X0E: Key_res=4; break;
				  default: return 0;    //無按鍵按下,返回0
			  }
			 switch(X_temp)    //判斷行
			  {
				case 0X70: return Key_res+12;break;
		     	case 0XB0: return Key_res+ 8;break;
                case 0XD0: return Key_res+ 4;break;
                case 0XE0: return Key_res;   break;
                default: return 0;	 //無按鍵按下,返回0	
			 }
		 }
	 }
	}
	else
		Key_down = 0;	//按鍵被鬆開
	
	if(Key_res)
		Key_down = 1;	//標誌按鍵被按下,防止重入

	return Key_res;
}
    

//-----------------------------------矩陣鍵盤服務(功能)子函數-------------------//
void Key16_Function(void) 
{
	if(i != 0)    //按鍵按下
		{
			switch(i)
			{
			  case  1: P1=0XFE;P2=0XFF;break;
			  case  2: P1=0XFD;P2=0XFF;break;
		      case  3: P1=0XFB;P2=0XFF;break;
		      case  4: P1=0XF7;P2=0XFF;break;
			  case  5: P1=0XEF;P2=0XFF;break;
			  case  6: P1=0XDF;P2=0XFF;break;
			  case  7: P1=0XBF;P2=0XFF;break;
			  case  8: P1=0X7F;P2=0XFF;break;
			  case  9: P1=0XFF;P2=0XFE;break;
			  case 10: P1=0XFF;P2=0XFD;break;
			  case 11: P1=0XFF;P2=0XFB;break;
			  case 12: P1=0XFF;P2=0XF7;break;
			  case 13: P1=0XFF;P2=0XEF;break;
			  case 14: P1=0XFF;P2=0XDF;break;
			  case 15: P1=0XFF;P2=0XBF;break;
			  case 16: P1=0XFF;P2=0X7F;break;
			  default:P1=0X00;P2=0X00;break;
			}
	}
}

四、矩陣鍵盤_多行掃描_外部中斷

(僅能檢測到列,檢測不到行,改進ing)

#include<STC15.H>
#include<intrins.h>

#define uchar unsigned char
#define uint unsigned int
#define KeyBus P6    //定義矩陣鍵盤接口

uchar Key_res =0; 
uchar i=0;

void GPIO(void);    //IO口初始化函數
void Delay10ms();		//@12.000MHz
void Delay5ms();		//@12.000MHz
void Delay1ms();	  //@12.000MHz
void INT1_INIT(void); //外部中斷1初始化函數
uchar Key16_Scan(void);//矩陣鍵盤掃描函數子程序
void Key16_Function(void); //矩陣鍵盤服務(功能)子函數

void main(void)
{
   GPIO();    //IO口初始化函數
   INT1_INIT();
	while(1) 
	{
	  KeyBus = 0X0F;
      Key16_Function(); //矩陣鍵盤服務(功能)子函數
	}
}

//-----------------------------------IO口初始化函數-----------------------------//
void GPIO(void)
{
	P0M1=0;
	P0M0=0;
	P1M1=0;
	P1M0=0;
	P2M1=0;
	P2M0=0;
	P3M1=0;
	P3M0=0;
	P4M1=0;
	P4M0=0;
	P5M1=0;
	P5M0=0;

}

//------------------------------------軟件延時---------------------------------------//
void Delay10ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 117;
	j = 184;
	do
	{
		while (--j);
	} while (--i);
}

void Delay5ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 59;
	j = 90;
	do
	{
		while (--j);
	} while (--i);
}

void Delay1ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 12;
	j = 169;
	do
	{
		while (--j);
	} while (--i);
}

//---------------------------------------外部中斷1初始化函數-----------------------------//
void INT1_INIT(void)
{
	IT1=1;
	EX1=1;
    EA=1;

}

//---------------------------------------矩陣鍵盤掃描函數子程序-------------------------//

uchar Key16_Scan(void)
{

	uchar X_temp = 0,Y_temp = 0;
	uchar Key_down = 0;
	
	KeyBus = 0XFF;	
	KeyBus = 0X0F;	//高4位置0,低4位置1,此時有按鍵按下時,低四位的某一位會被拉低,由此定位按下的按鍵在第幾列
	Y_temp = KeyBus&0X0F;
	
	if(Y_temp!=0X0F)	//如果檢測到某列有按鍵按下(有按鍵按下時,低四位會有一位被拉低)
	{
		Delay1ms();    //按鍵消抖(不知道有無必要)
		KeyBus = 0X0F; 	
	    Y_temp = KeyBus&0X0F;//將KeyBus低四位的按鍵信息賦值給Y_temp
		if(Y_temp!=0X0F)
		{
			KeyBus = 0X0F;
			Y_temp = KeyBus&0X0F;  //將KeyBus低四位的按鍵信息賦值給Y_temp,反應列信息
			KeyBus = 0XF0;
			X_temp = KeyBus&0XF0;  //將KeyBus高四位的按鍵信息賦值給X_temp,反應行信息
			if(Key_down == 0)      //按鍵擡起檢測,	
			{
			  switch(Y_temp)    //判斷列
			  {
				  case 0X07: Key_res=1; break;
				  case 0X0B: Key_res=2; break;
				  case 0X0D: Key_res=3; break;
				  case 0X0E: Key_res=4; break;
				  default: return 0;    //無按鍵按下,返回0
			  }
			 switch(X_temp)    //判斷行
			  {
				case 0X70: return Key_res+12;break;
			   	case 0XB0: return Key_res+ 8;break;
                case 0XD0: return Key_res+ 4;break;
                case 0XE0: return Key_res;   break;
                default: return 0;	 //無按鍵按下,返回0	
			 }
		 }
	 }
	}
	else
		Key_down = 0;	//按鍵被鬆開
	
	if(Key_res)
		Key_down = 1;	//標誌按鍵被按下,防止重入

	return Key_res;
}
    
//--------------------------------------外部中斷1服務函數-----------------------------//
void INT1_ISR() interrupt 2
{
		i = Key16_Scan();   //矩陣鍵盤掃描函數子程序
}

//-----------------------------------矩陣鍵盤服務(功能)子函數-------------------//
void Key16_Function(void) 
{
	EX1=0;
	if(i != 0)    //按鍵按下
		{
			switch(i)
			{
			  case  1: P1=0XFE;P2=0XFF;break;
			  case  2: P1=0XFD;P2=0XFF;break;
		      case  3: P1=0XFB;P2=0XFF;break;
		      case  4: P1=0XF7;P2=0XFF;break;
			  case  5: P1=0XEF;P2=0XFF;break;                                     
			  case  6: P1=0XDF;P2=0XFF;break;
			  case  7: P1=0XBF;P2=0XFF;break;
			  case  8: P1=0X7F;P2=0XFF;break;
			  case  9: P1=0XFF;P2=0XFE;break;
			  case 10: P1=0XFF;P2=0XFD;break;
			  case 11: P1=0XFF;P2=0XFB;break;
			  case 12: P1=0XFF;P2=0XF7;break;
			  case 13: P1=0XFF;P2=0XEF;break;
			  case 14: P1=0XFF;P2=0XDF;break;
			  case 15: P1=0XFF;P2=0XBF;break;
			  case 16: P1=0XFF;P2=0X7F;break;
			  default:P1=0X00;P2=0X00;break;
			}
	}
	EX1=1;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章