课程设计:89C51单片机实现六位密码锁

全部内容为本人原创!
其中代码程序仅为该课程设计中的一种方法,对有兴趣修改、完善的同学表示欢迎!
注:由于各模块代码在编写时相互交融,因此将各模块代码独立显示出来较为困难且观赏性差,因此代码展示仅有最后的总代码展示

本程序功能:
1.设置6位密码,密码通过键盘输入,若密码正确,则指示灯亮。
2.密码可以由用户自己修改设定,锁打开后才能修改密码。修改密码之前必须再次输入密码,在输入新密码时需要二次确认,以防止误操作。
3.报警、锁定键盘功能。密码输入错误显示器会出现错误提示,若密码输入错误次数超过三次,蜂鸣器报警、指示灯闪烁、锁定键盘,约8s后解除锁定和数码管、蜂鸣器报警。

编写程序前构思完成总体流程图:在这里插入图片描述
之后在仿真软件上完成单片机原理图:
在这里插入图片描述
本作品的主要构成部分主要包括80C51单片机、矩阵按键、LED灯、蜂鸣器、八位数码管显示器。
其中,矩阵按键与八位数码管显示器为重点。

首先介绍矩阵按键模块:
密码的输入用矩阵键盘实现,包括数字键和功能键。
如图一所示,矩阵键盘的每一条水平线与垂直线的交叉处不相通,二十通过一个按键来连接,利用这种行列式矩阵只需要N条行线和M条列线即可组成由N×M个按键的键盘。
在这里插入图片描述
在这里插入图片描述
本次设计需要0-9九个数字键、清零键、确认键和一个重置密码键,所以选用4×4的矩阵按键。
在这种行列式矩阵键盘编码的单片机系统中,键盘处理程序首先执行等待按键并确认有无按键按下的程序段,还要对按键进行消抖处理。
本程序中,当六位密码全部输入完成后,按下任意键即可进行密码正误判断,并进行消抖处理。
当数字键被按下后,就要识别是哪一个按键被按下。本次设计使用的是线反转法。给行线置为0x0f,给列线置为0xf0,。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位值判断是哪一行有按键按下,这样就能够确定是哪一个按键按下了。

显示模块(包含八位数码管、LED灯):
密码显示电路由单片机、电排阻和数码管组成。。P2控制位选,P0控制段选。为了防止手动错误,数码管显示数字。
数码管显示原理:
本设计采用数码管动态显示,在极短的时间内轮流显示各个字符。利用人眼视觉暂留的特点,循环顺序变更位码,同时数据线上发送相应的显示内容,即可表现出多位数字同时显示的特点。

报警模块(包含八位数码管,LED灯与蜂鸣器)
本报警电路由三个部分组成,让密码错误次数为3次时,触发报警电路,数码管滚动显示8,蜂鸣器持续间断发出声响,矩阵键盘锁死,D1灯亮,8秒后解除报警。

本代码特点:
①在进行八位数码管动态多位的同时显示时,采用了break语句,以正在输入的位数为判断标准,如正在输入 第三位密码时,将会使1至3位密码动态循环显示,利用视觉暂留形成多位密码同时显示的效果。
②修改密码共有四道程序,标志位分别位mark01,mark02,mark03,mark04。
第一遍为输入一遍正确密码,若密码正确mark01置1,并按密码重置键进行修改密码程序。
第二遍为重复输入原密码,若正确mark02置1同时使mark01归零。
第三遍为输入新密码,输入完六位密码后临时保存此密码,并使mark03置1,mark02归零。
第四遍为重复输入新密码,输入完成后mark04置1,mark03归零。
最后为密码判断,若新密码两次输入一致,则修改密码成功,标志位mark04归零。

注意,在进行按键程序的编写时,注意按键延时消抖与弹起!
其余基本都在代码的注释中

程序总代码:

#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define GPIO P1
#define count 50000			   //计数值,约为0.05s
#define TH	(65536-count)/256  //定时器初始化设置
#define TL	(65536-count)%256
sbit LSA=P2^2;				   //数码管位选设置
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit bee=P1^5;
sbit LED=P2^0;
int key=0;					   //矩阵键盘按键标志
int password[6];			   //输入数字数组
int right[6]={6,6,6,6,6,6};	   //正确密码数组
int temporary[6];			   //零时密码数组
uchar code DSY[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};	 //数码管显示数字数组

void delay(int n)			   //延时函数
{	int t;
	while(n--)
	{	for(t=0;t<12;t++);
	}
}
void main()
{	int flag=1;
    int sign=0;				   //重置密码位数
	int mark01=0;			   //重置密码第一遍(原密码)标志
	int mark02=0;			   //重置密码第二遍(原密码重复)标志
	int mark03=0;			   //重置密码第三遍(新密码)标志
	int mark04=0;			   //重置密码第四遍(新密码重复)标志
	int mistake=0;			   //错误次数
	int temp=0;				   //正确位数
	int N=0;				   //输入位数
	int i=0;				   //计数
	int a=0;				   //计数
	bee=0;
	TMOD&=0X0F;				   //定时器初始化设置
	TMOD|=0X01;
	P2=0X03;
	while(1)
	{	
	while(1)				   //进入循环
		{   GPIO=0x0f;
			if(GPIO!=0x0f)		   //判断按下
			{	delay(100);
				if(GPIO!=0x0f)	   //重新判断按下
				{	switch(N)      //位选   
		            {
		                case(0):
		                        LSA=1;LSB=1;LSC=1; break;
		                case(1):
		                        LSA=0;LSB=1;LSC=1; break;
		                case(2):
		                        LSA=1;LSB=0;LSC=1; break;
		                case(3):
		                        LSA=0;LSB=0;LSC=1; break;
		                case(4):
		                        LSA=1;LSB=1;LSC=0; break;
		                case(5):
		                        LSA=0;LSB=1;LSC=0; break;
					}
					GPIO=0X0F;						//测试列
						switch(GPIO)
						{
							case(0x07):key=0;break;
							case(0x0b):key=1;break;
							case(0x0d):key=2;break;
							case(0x0e):key=3;break;
						}						   //测试行
					GPIO=0XF0;
					switch(GPIO)
						{
							case(0x70):key=key;break;
							case(0xb0):key=key+4;break;
							case(0xd0):key=key+8;break;
							case(0xe0):key=key+12;break;
						}
					
					P0=DSY[key];				  //矩阵键盘按键输出至数码管并显示
					password[N]=key;			  //保存按键输入
					if(mark04==1)				  //第四遍密码标志开启时,将第三遍输入密码与第四遍输入密码比对
					{if(key==temporary[N])
					 sign++;
					}
					if(mark03==1)				  //第三遍密码标志开启时,将输入新密码保存到临时密码数组中
					{temporary[N]=key;
					}
					if(key==right[N])			  //判断这一位密码是否正确并计数
					   temp++;
					if(key==15)					  //重新输入密码功能
					  {N=0;
					   if(mark01==1)			  //输入正确密码后按S16,可输入第二遍密码
					   {mark02=1;				  //第二遍密码标志开启
					    mark01=0;
					}
					   break;
					  }
					while((GPIO!=0xf0)&&(i<500))  //按键弹起
					{	delay(100);
						i++;
					}
					i=0; 
					while(1)					  //进入显示循环
						{	while(1)
							{LSA=1;LSB=1;LSC=1;	  //显示第一位
							 key=password[0];
							 P0=DSY[key];
							 delay(15); 
							 if(N==0)			  
							 break;
							 LSA=0;LSB=1;LSC=1;	  //显示第二位
							 key=password[1];
							 P0=DSY[key];
							 delay(15);
							 if(N==1)
							 break;
							 LSA=1;LSB=0;LSC=1;	 //显示第三位
							 key=password[2];
							 P0=DSY[key];
							 delay(15);
							 if(N==2)
							 break;
							 LSA=0;LSB=0;LSC=1;	 //显示第四位
							 key=password[3];
							 P0=DSY[key];
							 delay(15);
							 if(N==3)
							 break;
							 LSA=1;LSB=1;LSC=0;	 //显示第五位
							 key=password[4];
							 P0=DSY[key];
							 delay(15);
							 if(N==4)
				             break;
							 LSA=0;LSB=1;LSC=0;	 //显示第六位
						 	 key=password[5];
							 P0=DSY[key];
							 delay(15);
							 if(N==5)
				             break;
							}
							if(GPIO!=0xf0)		 //按键再次按下退出循环
							{	delay(100);
								if(GPIO!=0xf0)
								break;
							}
						}
					 
				N++;	 
				}
		        
			}
			if(N==6)							//六位密码输入完成
			{	if(mark03==1)					//第三遍密码标志开启并输入完六位新密码后,可进行第四遍密码输入
				{mark04=1;
				 mark03=0;
				}
				if(temp!=6)						//输入错误,计数加一
				mistake++;
				while((GPIO!=0xf0)&&(i<500))	//按键弹起
					{	delay(100);
						i++;
					}
					i=0; 
				if(sign==6)						//第三遍密码与第四遍密码相同时,将此密码设置为新密码
				{   delay(15);
				    right[0]=temporary[0];
					right[1]=temporary[1];
					right[2]=temporary[2];
					right[3]=temporary[3];
					right[4]=temporary[4];
					right[5]=temporary[5];
					sign=0;
					mark04=0;
					mistake=0;
					for(flag=1;flag<100;flag++)	//密码修改正确蜂鸣器响
					{ bee=~bee;
					  delay(15);
					}
				}
				while(1)						//进入显示循环
				{	while(1)
					{	LSA=1;LSB=1;LSC=1;		//第一位显示
				    	if(temp==6)				//密码正确显示1
						{mistake=0;
						 P0=DSY[1];
						 mark01=1;				//密码输入正确时,第一遍密码标志开启
						 if(mark02==1)			//第二遍密码标志开启并第二遍输入密码正确时,第三遍密码标志开启
						 {mark03=1;
						  mark02=0;
						 }
						} 
						 else					//密码错误显示0
						{P0=DSY[0];
						 if(mistake==3)			//错误次数为3时
						 {LED=0;
						  for(a=0;a<100;a++)
						 	{	TH0=TH;
								TL0=TL;
								TR0=1;
								bee=~bee;			//蜂鸣器响
								LSA=1;LSB=1;LSC=1;	//数码管循环显示
								P0=DSY[8];
								delay(50); 
								LSA=0;LSB=1;LSC=1;
								P0=DSY[8];
								delay(50);
								LSA=1;LSB=0;LSC=1;
								P0=DSY[8];
								delay(50);
								LSA=0;LSB=0;LSC=1;
								P0=DSY[8];
								delay(50);
								LSA=1;LSB=1;LSC=0;
								P0=DSY[8];
								delay(50);
								LSA=0;LSB=1;LSC=0;
							 	P0=DSY[8];
								delay(50);
								LSA=1;LSB=0;LSC=0;
							 	P0=DSY[8];
								delay(50);
								LSA=0;LSB=0;LSC=0;
							 	P0=DSY[8];
								delay(50);
							}
						 mistake=0; 			//错误次数重置
						 LED=1;
						 }
						 
						}
						break;
					}
					if(GPIO!=0xf0)			 //按键再次按下退出循环
					{	delay(100);
						if(GPIO!=0xf0)
						break;
					}
				}
				N=0;					   //密码位数重置
				temp=0;
			}	
		}
	
	}
}
发布了1 篇原创文章 · 获赞 0 · 访问量 112

猜你喜欢

转载自blog.csdn.net/Schofiled/article/details/104324916