蓝桥杯之单片机设计与开发(6)——矩阵按键下的扫描流水灯与数码管

#include <reg52.h>  //一般51单片机的头文件声明

上面是我们一般写51单片机程序的头文件,但是在蓝桥杯开发板上注意到其中需要用到P4口,而此头文件并没有声明P4口。
蓝桥杯之单片机设计与开发(6)——矩阵按键下的扫描流水灯与数码管_第1张图片蓝桥杯之单片机设计与开发(6)——矩阵按键下的扫描流水灯与数码管_第2张图片因此在使用的时候我们需要提前声明好P4口才能使用。
声明格式如下:

sfr P4    = 0xC0;        //端口声明,此版本reg52没有P4口

在需要使用P4口的函数前声明即可

矩阵键盘的扫描思想

与独立按键不同的是,按键的两个引脚都分别连接的单片机的I/O端口,一个作为行信号,另外一个作为列信号。我们以4X4的矩阵键盘为例,试着探讨其工作方式和扫描思路。

蓝桥杯之单片机设计与开发(6)——矩阵按键下的扫描流水灯与数码管_第3张图片
在上面的矩阵键盘中,要识别出黄色按键的按下状态,应该怎么做呢?

对与矩阵键盘,我们只能逐行扫描,然后读取列的状态信号。如果R3行输出低电平,那么黄色按键如果有按下动作的话,那读取C2列信号也应该为低电平,而该行上其他没有按下动作的按键的列信号则为高电平。因此,我们可以得到矩阵键盘的基本扫描步骤:

<1> R1输出点电平,R2、R3、R4输出高电平,逐个读取判断列信号,如果都为高电平则R1行上没有按键按下。
<2> R2输出点电平,R1、R3、R4输出高电平,逐个读取判断列信号。
<3> R3输出点电平,R1、R2、R4输出高电平,发现C2列信号为低电平,那么可以判断得R3行的C2列的按键有按下动作。
<4> R4输出点电平,R1、R3、R4输出高电平,逐个读取判断列信号。

如此循环往复,扫描的按键的状态。
/**********************************************************
@功能模块:主函数
@作    者:朱明
@时    间:202026/

#include <reg52.h>
#include "mode.h"
#include "delay.h"
#include "test.h"

/**********************************************************
说明:"",<>,两种引用方式的区别:
	<>是指从当前安装目录处引用,如果找不到则报错。
   “”,是先从当前工程文件夹寻找如果找不到则到安装目录中去找,找不到则报错。
**********************************************************/


		
void main()
{

				while(1)
				{
					test();
				}
}


/********************************************************
@功能模块:工程函数
@作    者:朱明
@时    间:202026*********************************************************/

#include "test.h"
#include "testa.h"


sfr P4    = 0xC0;        //端口声明,此版本reg52没有P4口

sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;

sbit C4 = P3^4;
sbit C3 = P3^5;
sbit C2 = P4^2;
sbit C1 = P4^4;

unsigned char code SMG_duanma[18]=
		{	/*0*/ 0xc0 ,/*1*/ 0xf9 ,/*2*/ 0xa4 ,
			/*3*/ 0xb0 ,/*4*/ 0x99 ,/*5*/ 0x92 ,
			/*6*/ 0x82 ,/*7*/ 0xf8 ,/*8*/ 0x80 ,
			/*9*/ 0x90 ,/*a*/ 0x88 ,/*b*/ 0x80 ,
			/*c*/ 0xc6 ,/*d*/ 0xc0 ,/*e*/ 0x86 ,
			/*f*/ 0x8e ,/*g*/ 0xbf ,/*h*/ 0x7f };

unsigned char key_num;          //按键对应的数码管值

void test()  //单片机使用核心工程文件

/************************************************************
//按键S7和S6为选择键,确定控制键控制那组LED指示灯。
//简单来说就是S7按下后,S6/S5/S4无效,再按下S7后按键S6方才有效。
//只有当S6按键有效的时候(S7无效)S5/S4按键的控制才有效
***********************************************************/

{
		R1 = 0;									//扫描第一排按键
		R2 = R3 = R4 = 1;
		C1 = C2 = C3 = C4 =1;
		if(C1 == 0)
		{
			while(C1 == 0);
			key_num = 0;
			testa(SMG_duanma[key_num]);
		}
		else if(C2 == 0)
		{
			while(C2 == 0);
			key_num = 1;
			testa(SMG_duanma[key_num]);
		}
		else if(C3 == 0)
		{
			while(C3 == 0);
			key_num = 2;
			testa(SMG_duanma[key_num]);
		}
		else if(C4 == 0)
		{
			while(C4 == 0);
			key_num = 3;
			testa(SMG_duanma[key_num]);
		}
	
				R2 = 0;							//扫描第二排按键
				R1 = R3 = R4 = 1;
				C1 = C2 = C3 = C4 =1;
				if(C1 == 0)
				{
					while(C1 == 0);
					key_num = 4;
					testa(SMG_duanma[key_num]);
				}
				else if(C2 == 0)
				{
					while(C2 == 0);
					key_num = 5;
					testa(SMG_duanma[key_num]);
				}
				else if(C3 == 0)
				{
					while(C3 == 0);
					key_num = 6;
					testa(SMG_duanma[key_num]);
				}
				else if(C4 == 0)
				{
					while(C4 == 0);
					key_num = 7;
					testa(SMG_duanma[key_num]);
				}
	
						R3 = 0;						//扫描第三排按键
						R2 = R1 = R4 = 1;
						C1 = C2 = C3 = C4 =1;
						if(C1 == 0)
						{
							while(C1 == 0);
							key_num = 8;
							testa(SMG_duanma[key_num]);
						}
						else if(C2 == 0)
						{
							while(C2 == 0);
							key_num = 9;
							testa(SMG_duanma[key_num]);
						}
						else if(C3 == 0)
						{
							while(C3 == 0);
							key_num = 10;
							testa(SMG_duanma[key_num]);
						}
						else if(C4 == 0)
						{
							while(C4 == 0);
							key_num = 11;
							testa(SMG_duanma[key_num]);
						}
	
								R4 = 0;				//扫描第四排按键
								R2 = R3 = R1 = 1;
								C1 = C2 = C3 = C4 =1;
								if(C1 == 0)
								{
									while(C1 == 0);
									key_num = 12;
									testa(SMG_duanma[key_num]);
								}
								else if(C2 == 0)
								{
									while(C2 == 0);
									key_num = 13;
									testa(SMG_duanma[key_num]);
								}
								else if(C3 == 0)
								{
									while(C3 == 0);
									key_num = 14;
									testa(SMG_duanma[key_num]);
								}
								else if(C4 == 0)
								{
									while(C4 == 0);
									key_num = 15;
									testa(SMG_duanma[key_num]);
								}
}

/********************************************************
@功能模块:模式函数
@作    者:朱明
@时    间:202026**********************************************************/

#include "mode.h"


void mode(unsigned char channel)  //单片机使用前清零以及模式选择
{
	switch(channel)
	{
		case 4:
			P2 = (P2 & 0x1f) | 0x80;
		break;
		case 5:
			P2 = (P2 & 0x1f) | 0xa0;
		break;
		case 6:
			P2 = (P2 & 0x1f) | 0xc0;
		break;
		case 7:
			P2 = (P2 & 0x1f) | 0xe0;
		break;
	}
}

/*********************************************************
@功能模块:工程函数
@作    者:朱明
@时    间:202026***********************************************************/

#include "testa.h"
#include "mode.h"

extern unsigned char key_num;		
void testa(unsigned char value)  //单片机使用核心工程文件
{		

	mode(6);
	P0 = 0x01;
	mode(7);
	P0 = value;
	mode(4);
	P0 = 0xff << (key_num+1);       //数码管显示对应的按键数
	if (key_num > 7)
	{
	 P0 = 0xff00 >> (key_num+1);    //先从左到右扫描再从右到左扫描
	}
}

你可能感兴趣的:(蓝桥杯,单片机)