笔者通过第十一届蓝桥杯单片机模拟I智能门锁和第十五届蓝桥杯单片机模拟I的题目,发现关于矩阵键盘输入和数码管实现输出的部分方法。

笔者能力有限,部分逻辑可能存在问题,欢迎各位大佬指出错误,谢谢!

第十一届模拟I

第十五届模拟I

一、矩阵键盘

键盘引脚

使用矩阵键盘需要在J5把按键帽连接KBD

矩阵键盘的使用我们基本上是扫描按键引脚,可以按行扫描,也可以按列扫描

笔者这里以按行扫描为例子

我们知道,判断按键按下,我们需要识别出某一行是相同电平,在这个图中,当K1按下后,与GND相连,电平由高电平,变为低电平,我们就可以知道,KeyIn1被接通,由此可以知道,我们矩阵键盘有8个引脚,所以,我们只需要把引脚配置成相同电平,再每一行独立检测,就可以知道哪一个按键按下了。

二、数码管

数码管位选

数码管段选

数码管的位选和段选

位选74HC573锁存器需要打开Y6C口

段选74HC573锁存器需要打开Y7C口

锁存器通道选择代码

void hc(unsigned char n)//锁存器通道选择
{
	switch(n)
	{
		case 0:
			P2 = P2 & 0x1f;
			break;
		case 4:
			P2 = (P2 & 0x1f) | 0x80;//LED
			break;
		case 5:
			P2 = (P2 & 0x1f) | 0xa0;//蜂鸣器,继电器
			break;
		case 6:
			P2 = (P2 & 0x1f) | 0xc0;//数码管位选
			break;
		case 7:
			P2 = (P2 & 0x1f) | 0xe0;//数码管段选
			break;
	}
}

三、结合

方法一:

定义一个按键数组,记录按键输入的数字,再通过不断替换数组的数字,显示在数码管上面

sbit K1 = P3^0;
sbit K2 = P3^1;
sbit K3 = P3^2;
sbit K4 = P3^3;
sbit K5 = P3^4;
sbit K6 = P3^5;
sbit K7 = P4^2;
sbit K8 = P4^4;

code unsigned char Seg_Table[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};//数码管段选数组

unsigned char Key_pass[4]={0};//键盘输入的数字(以四个数字为例)
unsigned char Key_count;//键盘输入的数字的位数

void Nixie_pos_num(unsigned char pos,num)//数码管位置,显示的数字
{
	hc(6);
	P0 = 0x01 << (pos-1);
	hc(7);
	P0 = num;
	delay(100);
	P0 = 0xff;
	hc(0);
}

void Nixie_Show()//数码管显示内容
{
        Nixie_pos_num(1,Seg_Table[12]);//C
		Nixie_pos_num(2,Seg_Table[16]);//16是数码管熄灭,赋值0xff防止数码管频闪
		Nixie_pos_num(3,Seg_Table[16]);
		Nixie_pos_num(4,Seg_Table[16]);
		//这里数码管显示需要判断输入是数字多少位
		if(Key_count == 1)//输入一位
		{
			Nixie_pos_num(8,Seg_Table[Key_pass[0]]);//数字从数组中获取
		}
		else if(Key_count == 2)//输入两位
		{
			Nixie_pos_num(7,Seg_Table[Key_pass[0]]);
			Nixie_pos_num(8,Seg_Table[Key_pass[1]]);
		}
		else if(Key_count == 3)//输入三位
		{
			Nixie_pos_num(6,Seg_Table[Key_pass[0]]);
			Nixie_pos_num(7,Seg_Table[Key_pass[1]]);
			Nixie_pos_num(8,Seg_Table[Key_pass[2]]);
		}
		else if(Key_count == 4)//输入四位
		{
			Nixie_pos_num(5,Seg_Table[Key_pass[0]]);
			Nixie_pos_num(6,Seg_Table[Key_pass[1]]);
			Nixie_pos_num(7,Seg_Table[Key_pass[2]]);
			Nixie_pos_num(8,Seg_Table[Key_pass[3]]);
		}
}


void Key_Num()
{
		K1 = K2 = K3 = K5 = K6 = K7 = K8 = 1;K4 = 0;//最下面一行扫描
		if(K7 == 0 || K6 == 0 || K5 == 0)
		{
			delay(100);
			if(K7 == 0)//s8按下
			{
				if(Key_count < 4)//判断按键是否超过4个数字
				{
					Key_pass[Key_count] = 7;
					Key_count++;
				}
				while(K7 == 0)
				{
					Nixie_Show();
				}
			}
			if(K6 == 0)//s12按下
			{
				if(Key_count < 4)//判断按键是否超过4个数字
				{
					Key_pass[Key_count] = 8;
					Key_count++;
				}
				while(K6 == 0)
				{
					Nixie_Show();
				}
			}
			if(K5 == 0)//s16按下
			{
				if(Key_count < 4)//判断按键是否超过4个数字
				{
					Key_pass[Key_count] = 9;
					Key_count++;
				}
				while(K5 == 0)
				{
					Nixie_Show();
				}
			}
		}
		
		K1 = K2 = K4 = K5 = K6 = K7 = K8 = 1;K3 = 0;//最倒数第二行扫描
		if(K8 == 0 || K7 == 0 || K6 == 0 || K5 == 0)
		{
			delay(100);
			//清零按键
			if(K8 == 0)//s5按下
			{
				Key_count = 0;//按键次数清零
				Key_pass[0]=Key_pass[1]=Key_pass[2]=Key_pass[3]=0;//数码管全部熄灭状态
				while(K8 == 0)
				{
					Nixie_Show();
				}
			}
			if(K7 == 0)//s9按下
			{
				if(Key_count < 4)//判断按键是否超过4个数字
				{
					Key_pass[Key_count] = 4;
					Key_count++;
				}
				while(K7 == 0)
				{
					Nixie_Show();
				}
			}
			if(K6 == 0)//s13按下
			{
				if(Key_count < 4)//判断按键是否超过4个数字
				{
					Key_pass[Key_count] = 5;
					Key_count++;
				}
				while(K6 == 0)
				{
					Nixie_Show();
				}
			}
			if(K5 == 0)//s17按下
			{
				if(Key_count < 4)//判断按键是否超过4个数字
				{
					Key_pass[Key_count] = 6;
					Key_count++;
				}
				while(K5 == 0)
				{
					Nixie_Show();
				}
			}
		}
		
		K1 = K3 = K4 = K5 = K6 = K7 = K8 = 1;K2 = 0;//第三行扫描
		if(K8 == 0 || K7 == 0 || K6 == 0 || K5 == 0)
		{
			delay(100);
			if(K8 == 0)//s6按下
			{
				if(Key_count < 4)//判断按键是否超过4个数字
				{
					Key_pass[Key_count] = 0;
					Key_count++;
				}
				while(K8 == 0)
				{
					Nixie_Show();
				}
			}
			if(K7 == 0)//s9按下
			{
				if(Key_count < 4)//判断按键是否超过4个数字
				{
					Key_pass[Key_count] = 1;
					Key_count++;
				}
				while(K7 == 0)
				{
					Nixie_Show();
				}
			}
			if(K6 == 0)//s13按下
			{
				if(Key_count < 4)//判断按键是否超过4个数字
				{
					Key_pass[Key_count] = 2;
					Key_count++;
				}
				while(K6 == 0)
				{
					Nixie_Show();
				}
			}
			if(K5 == 0)//s17按下
			{
				if(Key_count < 4)//判断按键是否超过4个数字
				{
					Key_pass[Key_count] = 3;
					Key_count++;
				}
				while(K5 == 0)
				{
					Nixie_Show();
				}
			}
		}
}

方法二:

定义一个变量Keynumber,不同按键按下,返回的变量Keynumber不同,在通过数码管显示出来

sbit K1 = P3^0;
sbit K2 = P3^1;
sbit K3 = P3^2;
sbit K4 = P3^3;
sbit K5 = P3^4;
sbit K6 = P3^5;
sbit K7 = P4^2;
sbit K8 = P4^4;

unsigned int Password,Count;
unsigned char KeyNum;

unsigned char Key()
{
	unsigned char KeyNumber=0;
	
	K4 = K2 = K3 = K5 = K6 = K7 = K8 = 1;K1 = 0;
	if(K8==0){Delay(20);while(K8==0);Delay(20);KeyNumber=1;}
	if(K7==0){Delay(20);while(K7==0);Delay(20);KeyNumber=5;}
	if(K6==0){Delay(20);while(K6==0);Delay(20);KeyNumber=9;}
	if(K5==0){Delay(20);while(K5==0);Delay(20);KeyNumber=13;}
	
	K1 = K4 = K3 = K5 = K6 = K7 = K8 = 1;K2 = 0;
	if(K8==0){Delay(20);while(K8==0);Delay(20);KeyNumber=2;}
	if(K7==0){Delay(20);while(K7==0);Delay(20);KeyNumber=6;}
	if(K6==0){Delay(20);while(K6==0);Delay(20);KeyNumber=10;}
	if(K5==0){Delay(20);while(K5==0);Delay(20);KeyNumber=14;}
	
	K1 = K2 = K4 = K5 = K6 = K7 = K8 = 1;K3 = 0;
	if(K8==0){Delay(20);while(K8==0);Delay(20);KeyNumber=3;}
	if(K7==0){Delay(20);while(K7==0);Delay(20);KeyNumber=7;}
	if(K6==0){Delay(20);while(K6==0);Delay(20);KeyNumber=11;}
	if(K5==0){Delay(20);while(K5==0);Delay(20);KeyNumber=15;}
	
	K1 = K2 = K3 = K5 = K6 = K7 = K8 = 1;K4 = 0;
	if(K8==0){Delay(20);while(K8==0);Delay(20);KeyNumber=4;}
	if(K7==0){Delay(20);while(K7==0);Delay(20);KeyNumber=8;}
	if(K6==0){Delay(20);while(K6==0);Delay(20);KeyNumber=12;}
	if(K5==0){Delay(20);while(K5==0);Delay(20);KeyNumber=16;}
	
	return KeyNumber;
}

void Key_Num()
{
    KeyNum=Key();
		if(KeyNum)
		{
			if(KeyNum<=10)	//如果S1~S10按键按下
			{
				if(Count<4) //如果输入次数小于4
				{
					Password*=10;         //左移一位
					Password+=KeyNum%10;  //获取一位密码
					Count++;   //计次加一
				}
			}
}

四、演示

五、总结

注意:以上代码这是一个参考,并不是所有题目都可以这样做,需要读者感觉题目要求配置。同时这是笔者的一个方法,代码是不完整的,目的是提供读者一个参考方向。

以上是笔者自己总结的一些方法,能力有限,可能复杂化了很多东西。本文是基于读者已经熟练掌握了矩阵键盘,数码管的单独模块后的代码显示,如果出现看不懂的代码,需要读者先学习关于数码管,矩阵键盘的基础知识哈。

更多推荐