【蓝桥杯单片机入门记录】矩阵键盘例程

一、目录

二、例程 

(1)例程1:以独立键盘程序为基础将]5跳线帽切换为矩阵键盘模式后先写出其中一列矩阵按键的程序。以S7、S6、S5、S4为例。

(2)例程2:根据例程1可以编写多列矩阵键盘程序。本例以写出第一列、第二列矩阵键盘程序按下S7、56、S5、S4、S11、510、59、S8按键,依次用第一位数码管依次显示1、2、3、4、5、6、7、8数值。

(3)例程3:根据例程1可以编写多列矩阵键盘程序。本例以写出第一列、第二列矩阵键盘程序按下57、56、S5、54、S11、S10、59、S8按键,依次用第一位数码管依次显示1、2、3、4、5、6、7、8数值。注:使用一个按键关键词来代替某一个按键被按下。

(4)矩阵键盘例程(列扫描法)。本例以按下依次按下S4-S16按键数码管依次显示1 9、-、5、灭、为例。本例题使用静态数码管。

(5)例程5:【选修】独立键盘→矩阵键盘 列扫描(四列)扫描端口整体操作法;

(6)【选修】独立键盘→矩阵键盘 线反转操作法;


二、例程 

(1)例程1:以独立键盘程序为基础将]5跳线帽切换为矩阵键盘模式后先写出其中一列矩阵按键的程序。以S7、S6、S5、S4为例。

  • 只在原来的KeyScan函数的第一行加上P44 = 0;即可实现在矩阵键盘中使用一列键盘;
//头文件声明区域
#include <STC15F2K60S2.H>
#include<intrins.h>

//变量声明区域

unsigned char S7_Flag = 0,S6_Flag = 0,S5_Flag = 0,S4_Flag = 0;

//函数声明区域

//毫秒级延时函数
void Delay(unsigned int ms);


//按键扫描函数
void KeyScan(void);

//程序主体
void main()
{
	P2 = 0XA0;P0 = 0X00;P2 = 0X80;P0 = 0XFF;//初始化程序
while(1)
{
	KeyScan();
	
	if(S7_Flag == 1) {S7_Flag = 0; P00 = 0;}
	if(S6_Flag == 1) {S6_Flag = 0; P00 = 1;}
	if(S5_Flag == 1) {S5_Flag = 0; P06 = 0;}
	if(S4_Flag == 1) {S4_Flag = 0; P06 = 1;}
}	
	
	
}
//毫秒级延时函数
void Delay(unsigned int ms)		//@11.0592MHz
{
	unsigned char i, j;
	while(ms--)
	{
	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
	}
	
}
//按键扫描函数
void KeyScan(void)
{
	P44 = 0;
	if(P30 == 0)
	{
		Delay(10);
		if(P30 == 0)
		{
			S7_Flag = 1;
			while(!P30);
		}
	}
		if(P31 == 0)
		{
			Delay(10);
			if(P31 == 0)
			{
				S6_Flag = 1;
				while(!P31);
			}
		}
		
		if(P32 == 0)
		{
			Delay(10);
			if(P32 == 0)
			{
				S5_Flag =1;
				while(!P32);
			}
		}
		
		if(P33 == 0)
		{
			Delay(10);
			if(P33 == 0)
			{
				S4_Flag = 1;
				while(!P33);
			}
		}
}

(2)例程2:根据例程1可以编写多列矩阵键盘程序。本例以写出第一列、第二列矩阵键盘程序按下S7、56、S5、S4、S11、510、59、S8按键,依次用第一位数码管依次显示1、2、3、4、5、6、7、8数值。

  • 假设只写出第一列,将P44置为0时候,按下按键后,只要判断P30 P31 P32 P33谁为0即可;只写第二列,将P42置为0,仍是只要判断P30 P31 P32 P33谁为即可;
  • 但是如果现在要同时写两列,应该如何写,思路:因为单片机程序执行的非常快,所以可以先讲P44置为0,然后对第一列进行扫描,如果有按键被按下,即可知道哪个按键被按下;如果没有按键被按下,那么将接下来P44置为1,将P42置为0,再对第二列进行扫描,不停地进行扫描,循环进行,即可知道哪个按键被按下。
//头文件声明区域
#include <STC15F2K60S2.H>
#include<intrins.h>

//变量声明区域

unsigned char S7_Flag = 0,S6_Flag = 0,S5_Flag = 0,S4_Flag = 0,S11_Flag = 0,S10_Flag = 0,S9_Flag = 0,S8_Flag = 0;
unsigned char code SEG[] = {0XF0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};

//函数声明区域

//毫秒级延时函数
void Delay(unsigned int ms);


//按键扫描函数
void KeyScan(void);

//程序主体
void main()
{
	P2 = 0XA0;P0 = 0X00;P2 = 0X80;P0 = 0XFF;//初始化程序
	P2 = 0XC0;P0 = 0X01;P2 = 0XFF;P0 = 0XFF;//打开第一个数码管程序
while(1)
{
	KeyScan();
	
	if(S7_Flag == 1)  {S7_Flag = 0;  P0 = SEG[1];}
	if(S6_Flag == 1)  {S6_Flag = 0;  P0 = SEG[2];}
	if(S5_Flag == 1)  {S5_Flag = 0;  P0 = SEG[3];}
	if(S4_Flag == 1)  {S4_Flag = 0;  P0 = SEG[4];}
	if(S11_Flag == 1) {S11_Flag = 0; P0 = SEG[5];}
	if(S10_Flag == 1) {S10_Flag = 0; P0 = SEG[6];}
	if(S9_Flag == 1)  {S9_Flag = 0;  P0 = SEG[7];}
	if(S8_Flag == 1)  {S8_Flag = 0;  P0 = SEG[8];}
}	
	
	
}
//毫秒级延时函数
void Delay(unsigned int ms)		//@11.0592MHz
{
	unsigned char i, j;
	while(ms--)
	{
	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
	}
	
}
//按键扫描函数
void KeyScan(void)
{
	P44 = 0;P42 = 1;
	if(P30 == 0)
	{
		Delay(10);
		if(P30 == 0)
		{
			S7_Flag = 1;
			while(!P30);
		}
	}
		if(P31 == 0)
		{
			Delay(10);
			if(P31 == 0)
			{
				S6_Flag = 1;
				while(!P31);
			}
		}
		
		if(P32 == 0)
		{
			Delay(10);
			if(P32 == 0)
			{
				S5_Flag =1;
				while(!P32);
			}
		}
		
		if(P33 == 0)
		{
			Delay(10);
			if(P33 == 0)
			{
				S4_Flag = 1;
				while(!P33);
			}
		}
		P44 = 1;P42 = 0;
	if(P30 == 0)
	{
		Delay(10);
		if(P30 == 0)
		{
			S11_Flag = 1;
			while(!P30);
		}
	}
		if(P31 == 0)
		{
			Delay(10);
			if(P31 == 0)
			{
				S10_Flag = 1;
				while(!P31);
			}
		}
		
		if(P32 == 0)
		{
			Delay(10);
			if(P32 == 0)
			{
				S9_Flag =1;
				while(!P32);
			}
		}
		
		if(P33 == 0)
		{
			Delay(10);
			if(P33 == 0)
			{
				S8_Flag = 1;
				while(!P33);
			}
		}
}
		

(3)例程3:根据例程1可以编写多列矩阵键盘程序。本例以写出第一列、第二列矩阵键盘程序按下57、56、S5、54、S11、S10、59、S8按键,依次用第一位数码管依次显示1、2、3、4、5、6、7、8数值。注:使用一个按键关键词来代替某一个按键被按下。

//头文件声明区域
#include <STC15F2K60S2.H>
#include<intrins.h>

//变量声明区域

unsigned char Key_Flag = 0;
unsigned char code SEG[] = {0XF0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};

//函数声明区域

//毫秒级延时函数
void Delay(unsigned int ms);


//按键扫描函数
void KeyScan(void);

//程序主体
void main()
{
	P2 = 0XA0;P0 = 0X00;P2 = 0X80;P0 = 0XFF;//初始化程序
	P2 = 0XC0;P0 = 0X01;P2 = 0XFF;P0 = 0XFF;//打开第一个数码管程序
while(1)
{
	KeyScan();
	
	switch(Key_Flag)
	{
		case 7:P0 = SEG[1];break;
		case 6:P0 = SEG[2];break;
		case 5:P0 = SEG[3];break;
		case 4:P0 = SEG[4];break;
		case 11:P0 = SEG[5];break;
		case 10:P0 = SEG[6];break;
		case 9:P0 = SEG[7];break;
		case 8:P0 = SEG[8];break;
		default:break;
	}
}	
	
	
}
//毫秒级延时函数
void Delay(unsigned int ms)		//@11.0592MHz
{
	unsigned char i, j;
	while(ms--)
	{
	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
	}
	
}
//按键扫描函数
void KeyScan(void)
{
	P44 = 0;P42 = 1;
	if(P30 == 0)
	{
		Delay(10);
		if(P30 == 0)
		{
			Key_Flag = 7;
			while(!P30);
		}
	}
		if(P31 == 0)
		{
			Delay(10);
			if(P31 == 0)
			{
				Key_Flag = 6;
				while(!P31);
			}
		}
		
		if(P32 == 0)
		{
			Delay(10);
			if(P32 == 0)
			{
				Key_Flag = 5;
				while(!P32);
			}
		}
		
		if(P33 == 0)
		{
			Delay(10);
			if(P33 == 0)
			{
				Key_Flag = 4 ;
				while(!P33);
			}
		}
		P44 = 1;P42 = 0;
	if(P30 == 0)
	{
		Delay(10);
		if(P30 == 0)
		{
			Key_Flag = 11;
			while(!P30);
		}
	}
		if(P31 == 0)
		{
			Delay(10);
			if(P31 == 0)
			{
				Key_Flag = 10;
				while(!P31);
			}
		}
		
		if(P32 == 0)
		{
			Delay(10);
			if(P32 == 0)
			{
				Key_Flag = 9;
				while(!P32);
			}
		}
		
		if(P33 == 0)
		{
			Delay(10);
			if(P33 == 0)
			{
				Key_Flag = 8;
				while(!P33);
			}
		}
}
		

(4)矩阵键盘例程(列扫描法)。本例以按下依次按下S4-S16按键数码管依次显示1 9、-、5、灭、为例。本例题使用静态数码管。

  • 为什么要写P3 = 0X7F; 在老版的蓝桥杯中,P42和P44 是 P36和P37,89C52中并没有P42和P44引脚,后来89C52被淘汰,为了兼容MM模式(总线操作模式),为了15能够代替C52的WR和RD引脚,就把P42和P44设为WR和RD。
//头文件声明区域
#include <STC15F2K60S2.H>
#include<intrins.h>

//变量声明区域

unsigned char Key_Flag = 0;
unsigned char code SEG[] = {0XF0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};

//函数声明区域

//毫秒级延时函数
void Delay(unsigned int ms);


//按键扫描函数
void ARRKeyScan(void);

//程序主体
void main()
{
	P2 = 0XA0;P0 = 0X00;P2 = 0X80;P0 = 0XFF;//初始化程序
	P2 = 0XC0;P0 = 0X01;P2 = 0XFF;P0 = 0XFF;//打开第一个数码管程序
while(1)
{
	ARRKeyScan();
	
	if(Key_Flag != 0)
	{
		P0 = SEG[Key_Flag];
		Key_Flag = 0;
	}
	
	
}

}
//毫秒级延时函数
void Delay(unsigned int ms)		//@11.0592MHz
{
	unsigned char i, j;
	while(ms--)
	{
	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
	}
	
}
//按键扫描函数
void ARRKeyScan(void)
{
	unsigned char temp;//定义局部变量用来存储从P3口读出的数值
	P44 = 0;P42 = 1;P3 = 0X7F;//0111 1111 扫描第一列
	temp = P3;				//将P3口读出的数字赋值给temp
	temp &= 0X0F;     //xxxx xxxx & 0000 1111 = 0000 xxxx temp高四位清零

	if(temp != 0X0F)  //如果低四位不全为1,则肯定有按键被按下
	{
		Delay(10);      //消抖
		temp = P3;
		temp &= 0X0F;
		
		if(temp != 0X0F) //真的有按键被按下
		{
			temp = P3;
			switch(temp) //
			{
				case 0X7E:Key_Flag = 4;break; // 0111 1110
				case 0X7D:Key_Flag = 3;break; // 0111 1101
				case 0X7B:Key_Flag = 2;break; // 0111 1011
				case 0X77:Key_Flag = 1;break; // 0111 0111
				default:break;				
			}
						
		}
		
		while(temp != 0X0F) //等待按键松手
		{
			temp = P3;
			temp &= 0X0F;
			
		}
	}
		
	P44 = 1;P42 = 0;P3 = 0XBF;//1011 1111 扫描第二列
	temp = P3;				//将P3口读出的数字赋值给temp
	temp &= 0X0F;     //xxxx xxxx & 0000 1111 = 0000 xxxx temp高四位清零

	if(temp != 0X0F)  //如果低四位不全为1,则肯定有按键被按下
	{
		Delay(10);      //消抖
		temp = P3;
		temp &= 0X0F;
		
		if(temp != 0X0F) //真的有按键被按下
		{
			temp = P3;
			switch(temp) //
			{
				case 0XBE:Key_Flag = 8;break; // 1011 1110
				case 0XBD:Key_Flag = 7;break; // 1011 1101
				case 0XBB:Key_Flag = 6;break; // 1011 1011
				case 0XB7:Key_Flag = 5;break; // 1011 0111
				default:break;				
			}
						
		}
		
		while(temp != 0X0F) //等待按键松手
		{
			temp = P3;
			temp &= 0X0F;
			
		}
		
		
	}
	
	P44 = 1;P42 = 1;P3 = 0XDF;//1101 1111 扫描第三列
	temp = P3;				//将P3口读出的数字赋值给temp
	temp &= 0X0F;     //xxxx xxxx & 0000 1111 = 0000 xxxx temp高四位清零

	if(temp != 0X0F)  //如果低四位不全为1,则肯定有按键被按下
	{
		Delay(10);      //消抖
		temp = P3;
		temp &= 0X0F;
		
		if(temp != 0X0F) //真的有按键被按下
		{
			temp = P3;
			switch(temp) //
			{
				case 0XDE:Key_Flag = 11;break; // 1101 1110
				case 0XDD:Key_Flag = 5;break; // 1101 1101
				case 0XDB:Key_Flag = 10;break; // 1011 1011
				case 0XD7:Key_Flag = 9;break; // 1011 0111
				default:break;				
			}
						
		}
		
		while(temp != 0X0F) //等待按键松手
		{
			temp = P3;
			temp &= 0X0F;
			
		}
	}
		
		P44 = 1;P42 = 1;P3 = 0XEF;//0111 1111 扫描第四列
	temp = P3;				//将P3口读出的数字赋值给temp
	temp &= 0X0F;     //xxxx xxxx & 0000 1111 = 0000 xxxx temp高四位清零

	if(temp != 0X0F)  //如果低四位不全为1,则肯定有按键被按下
	{
		Delay(10);      //消抖
		temp = P3;
		temp &= 0X0F;
		
		if(temp != 0X0F) //真的有按键被按下
		{
			temp = P3;
			switch(temp) //
			{
				case 0XEE:Key_Flag = 4;break; // 1110 1110
				case 0XED:Key_Flag = 3;break; // 1110 1101
				case 0XEB:Key_Flag = 2;break; // 1110 1011
				case 0XE7:Key_Flag = 1;break; // 1110 0111
				default:break;				
			}
						
		}
		
		while(temp != 0X0F) //等待按键松手
		{
			temp = P3;
			temp &= 0X0F;
			
		}
	}
	
}

(5)例程5:【选修】独立键盘→矩阵键盘 列扫描(四列)扫描端口整体操作法;

  • 注:矩阵键盘不设在一组1/0口上面,但又想像在一组1/0口一样操作。可想象例程4如果P44用P37代替,P42用P36代替的编程方法。
  • 注:此例程是为了下文学习矩阵键盘“高低电平翻转法(线与法)”而改进设计,正常情况设计电路使用4*4矩阵键盘一般都会放置在同一组1/0端口,也就不会使用本例程这种操作。
    #include <STC15F2K60S2.H>
    #include<intrins.h>
    
    
    #define uchar unsigned char
    #define uint unsigned int
    
    unsigned char tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
    //unsigned char code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
    
    unsigned char SEG1,SEG2,SEG3,SEG4,SEG5,SEG6,SEG7,SEG8;
    unsigned char KEY_Value = 0 ;
    
    void ArrKeyScan(void);
    void Delay_MS(unsigned int MS);
    void SEG_Display12(uchar yi,uchar er);
    void SEG_Display34(uchar san,uchar si);
    void SEG_Display56(unsigned char wu,unsigned char liu);
    void SEG_Display78(unsigned char qi,unsigned char ba);
    void Key_W(unsigned char Value);
    unsigned char Key_R();
    
    void main(void)
    {
    	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;		//初始化程序
    	
    	SEG1=10,SEG2=10,SEG3=10,SEG4=10,SEG5=10;
    	SEG6=10,SEG7=10,SEG8=10;
    	while(1)
    	{
    		ArrKeyScan();
    	
    		if(KEY_Value != 0)
    		{
    			SEG1 = KEY_Value/10 ;
    			SEG2 = KEY_Value%10 ;
    			KEY_Value = 0 ;
    		}
    		
    		SEG_Display12(SEG1,SEG2);
    		SEG_Display34(SEG3,SEG4);
    		SEG_Display56(SEG5,SEG6);
    		SEG_Display78(SEG7,SEG8);		
    	}
    }
    
    void ArrKeyScan(void)
    {
    	unsigned char temp;				//定义局部变量用来存储从P3口读出的数值? 
    	Key_W(0X7F);					// 0111 1111 扫描第一列
    	temp = Key_R(); 				//将P3口读出的数字赋值给temp 
    	temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
    	if(temp != 0X0F)
    	{
    		Delay_MS(5);
    		temp = Key_R(); 				//将P3口读出的数字赋值给temp 
    		temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
    		if(temp != 0X0F)
    		{
    			temp = Key_R(); 
    			switch(temp)  //1110  1101 1011 0111 
    			{
    				case 0X7E: KEY_Value = 7 ; break;
    				case 0X7D: KEY_Value = 6 ; break;
    				case 0X7B: KEY_Value = 5 ; break;
    				case 0X77: KEY_Value = 4 ; break;
    				default :  break;
    			}
    			while(temp != 0X0F)
    			{
    				temp = Key_R() ;				//将P3口读出的数字赋值给temp 
    				temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
    			}
    		}
    	}
    	
    	Key_W(0XBF); 		// //0111 1111 扫描第一列
    	temp = Key_R() ;				//将P3口读出的数字赋值给temp 
    	temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
    	if(temp != 0X0F)
    	{
    		Delay_MS(5);
    		temp = Key_R() ;				//将P3口读出的数字赋值给temp 
    		temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
    		if(temp != 0X0F)
    		{
    			temp = Key_R() ;
    			switch(temp)  //1110  1101 1011 0111 
    			{
    				case 0XBE: KEY_Value = 11 ; break;
    				case 0XBD: KEY_Value = 10 ; break;
    				case 0XBB: KEY_Value = 9 ; break;
    				case 0XB7: KEY_Value = 8 ; break;
    				default :  break;
    			}
    			while(temp != 0X0F)
    			{
    				temp = Key_R() ;				//将P3口读出的数字赋值给temp 
    				temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
    			}
    		}
    	}
    
    	Key_W(0XDF); 		// //1101 1111 扫描第一列
    	temp = Key_R() ;								//将P3口读出的数字赋值给temp 
    	temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
    	if(temp != 0X0F)
    	{
    		Delay_MS(5);
    		temp = Key_R() ;								//将P3口读出的数字赋值给temp 
    		temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
    		if(temp != 0X0F)
    		{
    			temp = Key_R() ;
    			switch(temp)  //1110  1101 1011 0111 
    			{
    				case 0XDE: KEY_Value = 15 ; break;
    				case 0XDD: KEY_Value = 14 ; break;
    				case 0XDB: KEY_Value = 13 ; break;
    				case 0XD7: KEY_Value = 12 ; break;
    				default :  break;
    			}
    			while(temp != 0X0F)
    			{
    				temp = Key_R() ;				//将P3口读出的数字赋值给temp 
    				temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
    			}
    		}
    	}
    	
    	Key_W(0XEF);		// //0111 1111 扫描第一列
    	temp = Key_R() ;								//将P3口读出的数字赋值给temp 
    	temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
    	if(temp != 0X0F)
    	{
    		Delay_MS(5);
    		temp = Key_R() ;				//将P3口读出的数字赋值给temp 
    		temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
    		if(temp != 0X0F)
    		{
    			temp = Key_R() ;
    			switch(temp)  //1110  1101 1011 0111 
    			{
    				case 0XEE: KEY_Value = 19 ; break;
    				case 0XED: KEY_Value = 18 ; break;
    				case 0XEB: KEY_Value = 17; break;
    				case 0XE7: KEY_Value = 16; break;
    				default :  break;
    			}
    			while(temp != 0X0F)
    			{
    				temp = Key_R() ;				//将P3口读出的数字赋值给temp 
    				temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
    			}
    		}
    	}
    }
    
    void Key_W(unsigned char Value)
    {
    	unsigned char Val = Value;
    	P3=Val;P44=Val>>7;P42=(Val&0x40)>>6;  	//	0111 1111   0100 0000
    }
    
    unsigned char Key_R()
    {
    	unsigned char Val = 0XFF,Val_P3=0,Val_P44=0,Val_P42=0;
    	Val_P3 = P3;  Val_P44 = P44;  Val_P42 = P42;
    	Val = ((Val_P3&0X3f)|(Val_P44<<7)|(Val_P42<<6)); //0011 1111 | 1000 0000 |  0100 000 
    	return Val;
    }
    
    void SEG_Display12(unsigned char yi,unsigned char er)
    {	
    	P2=0XC0;P0=0X01; 	//打开控制数码管位选的锁存器,然后选中第一个数码管
    	P2=0XFF;P0=tab[yi];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);
    	P0=0XFF;
    	
    	P2=0XC0;P0=0X02; 	//打开控制数码管位选的锁存器,然后选中第二个数码管
    	P2=0XFF;P0=tab[er];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);	
    	P0=0XFF;
    }
    
    void SEG_Display34(unsigned char san,unsigned char si)
    {
    	P2=0XC0;P0=0X04; 	//打开控制数码管位选的锁存器,然后选中第三个数码管
    	P2=0XFF;P0=tab[san];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);
    	P0=0XFF;
    	
    	P2=0XC0;P0=0X08; 	//打开控制数码管位选的锁存器,然后选中第四个数码管
    	P2=0XFF;P0=tab[si];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);	
    	P0=0XFF;
    }
    
    void SEG_Display56(unsigned char wu,unsigned char liu)
    {
    	P2=0XC0;P0=0X10; 	//打开控制数码管位选的锁存器,然后选中第五个数码管
    	P2=0XFF;P0=tab[wu];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);
    	P0=0XFF;
    	
    	P2=0XC0;P0=0X20; 	//打开控制数码管位选的锁存器,然后选中第六个数码管
    	P2=0XFF;P0=tab[liu];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);
    	P0=0XFF;
    }
    void SEG_Display78(unsigned char qi,unsigned char ba)
    {	
    	P2=0XC0;P0=0X40; 	//打开控制数码管位选的锁存器,然后选中第七个数码管
    	P2=0XFF;P0=tab[qi];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);
    	P0=0XFF;
    
    	P2=0XC0;P0=0X80; 	//打开控制数码管位选的锁存器,然后选中第八个数码管
    	P2=0XFF;P0=tab[ba];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);	
    	P0=0XFF;	
    }
    
    void Delay_MS(unsigned int MS)
    {
    	unsigned char i, j;
    	while(MS--)
    	{
    	_nop_();
    	_nop_();
    	_nop_();
    	i = 11;
    	j = 190;
    	do
    	{
    		while (--j);
    	} while (--i);
    	}
    	
    }
    
    

    (6)【选修】独立键盘→矩阵键盘 线反转操作法;

    #include <STC15F2K60S2.H>
    #include<intrins.h>
    
    #define uchar unsigned char
    #define uint unsigned int
    
    unsigned char tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
    //unsigned char code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
    
    unsigned char SEG1,SEG2,SEG3,SEG4,SEG5,SEG6,SEG7,SEG8;
    unsigned char KEY_Value = 0 ;
    
    void ArrKeyScan(void);
    void Delay_MS(unsigned int MS);
    void SEG_Display12(uchar yi,uchar er);
    void SEG_Display34(uchar san,uchar si);
    void SEG_Display56(unsigned char wu,unsigned char liu);
    void SEG_Display78(unsigned char qi,unsigned char ba);
    void Key_W(unsigned char Value);
    unsigned char Key_R();
    
    void main(void)
    {
    	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;		//初始化程序,后期详解;
    	
    	SEG1=10,SEG2=10,SEG3=10,SEG4=10,SEG5=10;
    	SEG6=10,SEG7=10,SEG8=10;
    	while(1)
    	{
    		ArrKeyScan();
    	
    		if(KEY_Value != 0)
    		{
    			SEG1 = KEY_Value/10 ;
    			SEG2 = KEY_Value%10 ;
    			KEY_Value = 0 ;
    		}
    		
    		SEG_Display12(SEG1,SEG2);
    		SEG_Display34(SEG3,SEG4);
    		SEG_Display56(SEG5,SEG6);
    		SEG_Display78(SEG7,SEG8);		
    	}
    }
    
    void ArrKeyScan(void)
    {
    	unsigned char key,key1,key2;
    	
    	Key_W(0X0F);	//P3=0XF0;		//所有列全部输出低电平
    	if((Key_R()&0X0F)!=0X0F)		//有按键被按下,能知道那一行,但不知道那一列
    	{
    		Delay_MS(5);									//消抖
    		if((Key_R()&0X0F)!=0X0F)	//消抖之后继续判断,是否按键依然被按下着,证明确实有按键被按下了
    		key1=Key_R()&0X0F;			//key1 存储按键的行值(即哪一行有按键被按下) 1110 1101 1011 0111
    		
    		Key_W(0XF0);			    //改变为所有行全部输出低电平
    		if((Key_R()&0XF0)!=0XF0)	//还是有按键被按下,能知道那一列,但不知道那一行
    		{
    				key2=Key_R()&0XF0;	//key2 存储按键的列值(即哪一行有按键被按下)  1110 1101 1011 0111
    				key=key1|key2;			//行值与列值相或,下面就可以得出那一列哪一行被按下了
    				if(key!=0xff)			//判断一下是都真的有按键被按下,其实这一句可以不写。
    				{
    					switch(key)						//分析出哪一个按键被按下了
    					{			
    						case 0x7e: KEY_Value = 7 ;break;   
    						case 0x7d: KEY_Value = 6 ;break;
    						case 0x7b: KEY_Value = 5 ;break;
    						case 0x77: KEY_Value = 4 ;break;
    						case 0xbe: KEY_Value = 11 ;break;
    						case 0xbd: KEY_Value = 10 ;break;
    						case 0xbb: KEY_Value = 9 ;break;
    						case 0xb7: KEY_Value = 8 ;break;
    						case 0xde: KEY_Value = 15 ;break;
    						case 0xdd: KEY_Value = 14 ;break;
    						case 0xdb: KEY_Value = 13 ;break;
    						case 0xd7: KEY_Value = 12 ;break;
    						case 0xee: KEY_Value = 19 ;break;
    						case 0xed: KEY_Value = 18 ;break;
    						case 0xeb: KEY_Value = 17 ;break;
    						case 0xe7: KEY_Value = 16 ;break;
    						default: break;
    					}
    				}
    		}
    	}
    }
    
    void Key_W(unsigned char Value)
    {
    	unsigned char Val = Value;
    	P3=Val;P44=Val>>7;P42=(Val&0x40)>>6;  	//	0111 1111   0100 0000
    }
    
    unsigned char Key_R()
    {
    	unsigned char Val = 0XFF,Val_P3=0,Val_P44=0,Val_P42=0;
    	Val_P3 = P3;  Val_P44 = P44;  Val_P42 = P42;
    	Val = ((Val_P3&0X3f)|(Val_P44<<7)|(Val_P42<<6)); //0011 1111 | 1000 0000 |  0100 000 
    	return Val;
    }
    
    void SEG_Display12(unsigned char yi,unsigned char er)
    {	
    	P2=0XC0;P0=0X01; 	//打开控制数码管位选的锁存器,然后选中第一个数码管
    	P2=0XFF;P0=tab[yi];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);
    	P0=0XFF;
    	
    	P2=0XC0;P0=0X02; 	//打开控制数码管位选的锁存器,然后选中第二个数码管
    	P2=0XFF;P0=tab[er];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);	
    	P0=0XFF;
    }
    
    void SEG_Display34(unsigned char san,unsigned char si)
    {
    	P2=0XC0;P0=0X04; 	//打开控制数码管位选的锁存器,然后选中第三个数码管
    	P2=0XFF;P0=tab[san];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);
    	P0=0XFF;
    	
    	P2=0XC0;P0=0X08; 	//打开控制数码管位选的锁存器,然后选中第四个数码管
    	P2=0XFF;P0=tab[si];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);	
    	P0=0XFF;
    }
    
    void SEG_Display56(unsigned char wu,unsigned char liu)
    {
    	P2=0XC0;P0=0X10; 	//打开控制数码管位选的锁存器,然后选中第五个数码管
    	P2=0XFF;P0=tab[wu];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);
    	P0=0XFF;
    	
    	P2=0XC0;P0=0X20; 	//打开控制数码管位选的锁存器,然后选中第六个数码管
    	P2=0XFF;P0=tab[liu];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);
    	P0=0XFF;
    }
    void SEG_Display78(unsigned char qi,unsigned char ba)
    {	
    	P2=0XC0;P0=0X40; 	//打开控制数码管位选的锁存器,然后选中第七个数码管
    	P2=0XFF;P0=tab[qi];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);
    	P0=0XFF;
    
    	P2=0XC0;P0=0X80; 	//打开控制数码管位选的锁存器,然后选中第八个数码管
    	P2=0XFF;P0=tab[ba];	//打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
    	Delay_MS(1);	
    	P0=0XFF;	
    }
    
    void Delay_MS(unsigned int MS)
    {
    	unsigned char i, j;
    	while(MS--)
    	{
    	_nop_();
    	_nop_();
    	_nop_();
    	i = 11;
    	j = 190;
    	do
    	{
    		while (--j);
    	} while (--i);
    	}
    	
    }
    

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值