基于51单片机的电子密码锁设计

1、设计需求

基于单片机的电子密码锁,通过密码输入来控制芯片工作,完成开锁、闭锁、修改密码等任务的电子产品。它具有保密性高、成本低、功耗低、操作简单,使用灵活性好等特点。

2、 设计思路及方案

本设计采用了AT89C51单片机电子锁系统,进行初始化设置,启动密码锁功能,密码输入显示屏幕采用了LCD液晶显示屏。该系统控制指令通过单片机进行实现,单片机根据实际操作情况分配部件工作内容,程序操作性强、方便简洁。在用户输入密码过程中,单片机将会采用矩阵按键布局模式记录当前输入密码,并将该密码与系统设置密码进行比对,若密码匹配则开启密码锁,若密码错误则需要用户按下删除键重新输入密码。当用户输入密码错误次数超过3次,电子密码锁将会自动锁定,需要用户切换管理员模式输入管理员密码才可解锁当前状态,并重新输入解锁密码。硬件原理图如图所示。

3、程序主函数

#include<reg52.h>
#define uint unsigned int
#define	uchar unsigned char
sbit l1=P1^0;	//LED指示
sbit bump=P2^2;	//蜂鸣器控制
sbit relay=P2^3;//继电器输出
sbit lcden=P2^7;//LCD1602液晶控制端
sbit lcdrs=P2^6;
sbit sda=P2^0;	//AT24C02数据端口
sbit scl=P2^1;	//时钟端口
/**********显示内容**************************/
uchar code xianshi0[]="input  password:";
uchar code xianshi1[]="please come in!";
uchar code xianshi2[]="*";
uchar code xianshi3[]=" you are thief!";
uchar code xianshi4[]=" new  password:";
uchar code xianshi5[]=" alter succeed!";
uchar code xianshi6[]="  first error!";
uchar code xianshi7[]="  second error!";
uchar code xianshi8[]="  third error!";
uchar code xianshi9[]="  alter fail!!";
uchar table[8];			 //给按键输入留取存储空间
uchar table1[8];		 //给密码修改留取存储空间
uchar mima[8];			 //给从存储中读取密码留取存储空间
uchar num,num1,num2,num3,etimes,fanhui,kai;
bit alterflog,cpflog,suoflog;//定义各种标志位 修改密码键按下标志   密码比较正确标志  上锁标志
void keyscan();						  //声明键盘扫描函数
void init();
void keydeal15();
void keydeal16();						  //声明初始化函数
/********************延时一毫秒函数**************/	
void delay_xs(uint x)
{  	uint i,j;
	for(i=x;i>0;i--) 	for(j=110;j>0;j--);}
void writecom(uchar com)	//写命令
{
	lcdrs=0; 	P0=com;	 	delay_xs(5);
	lcden=1;  	delay_xs(5);	 	lcden=0;
}
/*********************液晶写命令数据函数******************/
void writedate(uchar date)	//写命令
{
	lcdrs=1; 	P0=date;	delay_xs(5);
	lcden=1; 	delay_xs(5);	lcden=0;
}
/***************24c02读取写入数据初始化****************/
void delay()  //微妙级延时函数
{ ;; }
void start()  //开始信号
{	
	sda=1; 	delay(); scl=1;	delay(); sda=0;	delay();
}

void stop()   //停止
{
	sda=0;delay();scl=1;delay();sda=1;delay();
}
void respons()  //应答
{
	uchar i;
	scl=1;	delay();
	while((sda==1)&&(i<250)) i++;
	scl=0; 	delay();
}
void write_byte(uchar date)		//写一位数据
{
	uchar i,temp;
	temp=date;


	for(i=0;i<8;i++)
	{
		temp=temp<<1;
		scl=0; delay();	sda=CY;	delay();
		scl=1; delay();
	}
	scl=0; 	delay();
	sda=1; 	delay();
}

uchar read_byte()			   //读一位数据
{
	uchar i,k;
	scl=0; 	delay();
	sda=1;	delay();
	for(i=0;i<8;i++)
	{
		scl=1;	delay();	
		k=(k<<1)|sda;
		scl=0;	delay();	
	}
	return k;
}
void write24c02(uchar address,uchar date) //写一字节函数
{
	start();
	write_byte(0xa0);
	respons();
	write_byte(address);
	respons();
	write_byte(date);
	respons();
	stop();
}

uchar read24c02(uchar address)		//读一字节函数
{
	uchar date;
	start();
	write_byte(0xa0);
	respons();
	write_byte(address);
	respons();
	start();
	write_byte(0xa1);
	respons();
	date=read_byte();
	stop();
	return date;
}
/************各按键对应处理函数***************/
/*************各按键功能********************
1-2-3-4-5-6-7-8-9-0-确认-重新输入-未定义-上锁-密码修改
-密码修改确认-未定义*************************/
void keydeal1()		                 //按键1
{
	table[num]=1;
	num++;
	if(alterflog==1){table1[num1]=1;num1++;	}
}
void keydeal2()		                //按键2
{
	table[num]=2;
	num++;
	if(alterflog==1){table1[num1]=2;num1++;	}
}
void keydeal3()		               //按键3
{
	table[num]=3;
	num++;
	if(alterflog==1){table1[num1]=3;num1++;	}
}
void keydeal4()		               //按键4
{
	table[num]=4;
	num++;
	if(alterflog==1){table1[num1]=4;num1++;	}
}
void keydeal5()		               //按键5
{
	table[num]=5;
	num++;
	if(alterflog==1) {table1[num1]=5;num1++;}
}
void keydeal6()					//按键6
{
	table[num]=6;
	num++;
	if(alterflog==1){table1[num1]=6;num1++;	}
}
void keydeal7()					//按键7
{
	table[num]=7;
	num++;
	if(alterflog==1){table1[num1]=7;num1++;	}
}
void keydeal8()					  //按键8
{
	table[num]=8;
	num++;
	if(alterflog==1){table1[num1]=8;num1++;	}
}
void keydeal9()					   //按键9
{
	table[num]=9;
	num++;
	if(alterflog==1){table1[num1]=9; num1++;	}
}
void keydeal10()				   //按键10
{
	table[num]=0;  	num++;
	if(alterflog==1){table1[num1]=0;num1++;	}
}
void compare()			 //比较密码正确与否函数
{
	uchar j;
		for(j=0;j<8;j++)
		{
			if(table[j]==mima[j]){cpflog=1;l1=0;}
			else	cpflog=0;
			l1=1;
		} 	
}
void keydeal11()				  //确认键
{
	uchar j;
	if(alterflog==1)
	goto n;					//如果密码修改键按下再按此键无效
	if(num==8)			         //判断是否输入八个数字
	{
		num=0;			         //将输入数字个数清零
		compare();		         //进行密码比较
		for(j=0;j<8;j++)		 //用FFFFFFFF将输入的数据清空
		{
			table[j]=0x0f;
		}
	}
	if(cpflog==1)				 //如果密码正确,标志位为1
	{
		l1=0;					 //点亮开锁灯
		cpflog=0;				 //使比较密码标志位归零
		etimes=0;				 //使记错次数归零
		kai=1;					 //使打开锁标志位置1
		writecom(0x01);			 //液晶屏清空显示
		writecom(0x80);			 //让液晶显示“please come in!”
		for(j=0;j<15;j++)
		{
			writedate(xianshi1[j]);		delay_xs(3);
		}
		for(j=0;j<2;j++)		  //蜂鸣器响两声提示开锁成功
		{
			bump=0;	delay_xs(200);
			bump=1;	delay_xs(200);
			bump=0;	delay_xs(200);
			bump=1;	delay_xs(200);
		}
         /*********等待按下上锁键或者密码修改键**********/
		while((suoflog!=1)&(alterflog!=1)) 
		{
			P3=0xf7;
			if(P3==0xe7)  suoflog=1;  //上锁键按下上锁标志位置1				
			if(P3==0xd7) alterflog=1;  //密码修改键按下标志位置1		
			if(suoflog==1)	  //上锁后进行初始化
			{
				init();
			}
		n:	if(alterflog==1) //密码修改键按下显示new passsword
			{
				writecom(0x01);		writecom(0x38);
				for(j=0;j<15;j++){writedate(xianshi4[j]); }
			}
		}
		suoflog=0; 	  //上锁标志位清零
	}
	else			//否则密码错误,执行密码错误指令
	{
		num=0;		//将输入数据个数清零
		num1=0;		//将修改密码输入数字个数清零
		etimes++;	//记录错误次数加1 
		bump=0;		              //报警一声
		delay_xs(500);	bump=1;
		for(j=0;j<8;j++)		  //清空修改密码输入数据
		{ table1[j]=0x0f;		}
		if(etimes==1)			  //如果输错一次
		{
			writecom(0x01);		   //清屏
			writecom(0x80);
			for(j=0;j<14;j++)	   //显示first error
			{ writedate(xianshi6[j]);	}
			delay_xs(2000);		   //延时两秒
			writecom(0xc);
			writecom(0x80);
			for(j=0;j<16;j++)	   //第一行显示input passsword
			{
				writedate(xianshi0[j]);		delay_xs(5);
			}					   
			writecom(0x80+0x40+4);	 //第二行显示--------
			for(j=0;j<8;j++) {writedate('-'); 			}
		}
		if(etimes==2)			   //如果输错两次
		{
			writecom(0x01);	writecom(0x80);
			for(j=0;j<15;j++)	   //显示second error
			{
				writedate(xianshi7[j]);
			}
			delay_xs(2000);		   //延时两秒
			writecom(0xc);
			writecom(0x80);
			for(j=0;j<16;j++)		//第一行显示input passsword
			{
				writedate(xianshi0[j]);	delay_xs(5);
			}
			writecom(0x80+0x40+4);
			for(j=0;j<8;j++)		//第二行显示--------
			{
				writedate('-');
			}
		}
		if(etimes==3)				//如果输错三次
		{
			writecom(0x01);
			writecom(0x80);
			for(j=0;j<15;j++)		//显示you are thief!
			{
				writedate(xianshi3[j]);
			}
			for(j=0;j<10;j++)		//报警十秒钟
			{
				bump=0;		delay_xs(500);
				bump=1;		delay_xs(500);
			}
			init();					//初始化
		}
	}
}
void keydeal12()					//重新输入键
{
	uint i;
	if(kai==0)					//如果所没被打开
	{							//初始化回到输入密码状态
		init();
	}
	else				//如果锁被打开,则显示new password:
	{
		if(alterflog==1)
		{
			num=0; 	num1=0;
			writecom(0x01);		writecom(0x80);//清屏
			for(i=0;i<15;i++){writedate(xianshi4[i]);	}
		}
	}
}
void keydeal15()		   //确认密码修改键
{
	uchar i;
	alterflog=0;			//修改标志位归零
	num=0;					//数据输入个数清零
	for(i=0;i<8;i++)		//输入数据清空
	{
		table[i]=0x0f;	
	}
	if(num1==8)				//如果输入修改数字够八个进入
	{
		num1=0;				//将输入修改数字个数清零
		for(i=0;i<8;i++)	//将修改后八个数字写入存储器中
		{
			write24c02(i+1,table1[i]); 	delay_xs(5);
		}
		writecom(0x01);		  //清屏
		writecom(0x80);
		for(i=0;i<15;i++)	   //显示alter succeed!!
		{
			writedate(xianshi5[i]);
		}
		delay_xs(2000);
	}
	else					  //如果输入数字不够八个进入
	{
		num1=0;				  //将输入修改数字个数清零
		writecom(0x01);		 //清屏
		writecom(0x80);
		for(i=0;i<14;i++)	  //显示alter error!
		{
			writedate(xianshi9[i]);
		}
	}
	/**************修改后将键入返回程序************/
	if(kai==1)			 //如果锁被打开
	{
		num=0;			 //输入数字个数清零
		delay_xs(2000);	   //延时两秒钟
		writecom(0x01);		//清屏
		writecom(0x80);
		for(i=0;i<15;i++)	        //显示please come in!
		{
			writedate(xianshi1[i]);
			delay_xs(3);
		}						//继续等待上锁或修改密码
		while((suoflog!=1)&(alterflog!=1))
		{
			P3=0xf7;
			if(P3==0xe7)	suoflog=1;
			if(P3==0xd7)	alterflog=1;
			if(suoflog==1)	{ 	init();		}
			if(alterflog==1)
			{
				writecom(0x01);	writecom(0x80);//清屏
				for(i=0;i<15;i++){ writedate(xianshi4[i]);	}
			}
		 }
	}
	else	         //如果所没被打开,显示alter error两秒后
	{				 //进行初始化
		delay_xs(2000); 	init();
	}
}
void keydeal16()	   //键16未定义
{
	
}
/******************键盘扫描函数**************************/
void keyscan()
{
	uchar temp;
/**************第一行扫描********************/
	P3=0xfe;
	temp=P3&0xf0;
	if(temp!=0xf0)
	{
		delay_xs(10);
		if(temp!=0xf0)	temp=P3;
		switch(temp)
		{
			case 0xee:	keydeal1();	break;
			case 0xde:	keydeal2();	break;
			case 0xbe:	keydeal3();	break;
			case 0x7e: 	keydeal4();	break;

		}
		while((P3&0xf0)!=0xf0);	//松手检测

	}
/******************第二行扫描**********************/
	P3=0xfd;
	temp=P3&0xf0;
	if(temp!=0xf0)
	{
		delay_xs(10);
		if(temp!=0xf0) 	temp=P3;
		switch(temp)
		{
			case 0xed:	keydeal5();		break;
			case 0xdd: 	keydeal6();		break;
			case 0xbd:	keydeal7();		break;
			case 0x7d:	keydeal8();		break;

		}
		while((P3&0xf0)!=0xf0);	   //松手检测

	}
/*****************第三行扫描*********************/
	P3=0xfb; 
	temp=P3&0xf0;
	if(temp!=0xf0)
	{
		delay_xs(10);
		if(temp!=0xf0)	temp=P3;
		switch(temp)
		{
			case 0xeb: 	keydeal9();		break;
			case 0xdb:	keydeal10();	break;
			case 0xbb:	keydeal11();	break;
			case 0x7b:	keydeal12(); 	break;

		}
		while((P3&0xf0)!=0xf0);

	}
/********************第四行扫描********************/
	P3=0xf7;
	temp=P3&0xf0;
	if(temp!=0xf0)
	{
		delay_xs(10);
		if(temp!=0xf0)	temp=P3;
		switch(temp)
		{
			case 0xe7: 		//	keydeal13();
					break;
			case 0xd7:		//	keydeal14();
					break;
			case 0xb7: 	keydeal15(); break;
			case 0x77:	keydeal16(); break;
		}
		while((P3&0xf0)!=0xf0);

	}
}
/****************显示函数*************/
void display()
{
	uint c;
	writecom(0x80+0x40+4);
	if(alterflog==0)	//如果不处于修改密码状态,显示num个*
	{
		for(c=0;c<num;c++){	writedate('*');	delay_xs(5);	}
	}
	else		  //如果处于密码修改显示num1个*
	{
		for(c=0;c<num1;c++){ writedate('*'); delay_xs(5);}
	}

}
/*******************初始化函数***********/
void init()
{
	uint i,a,b;
	num=0;		  //输入数据个数清零
	num1=0;
	kai=0;		   //开锁标志位清零
	l1=1;		   //关闭开锁灯
	alterflog=0;   //修改密码标志位清零
	sda=1;		   //24c02进行释放总线
	delay();	scl=1; 	delay();
	writecom(0x38);	   //液晶初始化
	writecom(0x0c);
	writecom(0x06);
	writecom(0x01);
	for(i=0;i<8;i++)	//读取存储器中密码,并存放于mima[]中
	{
		mima[i]=read24c02(i+1);
	}
	writecom(0x01);		//清屏
	writecom(0x80);
	for(a=0;a<16;a++)		//显示input password:
	{
		writedate(xianshi0[a]);		delay_xs(5);
	}
	writecom(0x80+0x40+4);	//第二行显示--------
	for(b=0;b<8;b++){	writedate('-');	} 
}
/*****************主函数******************/
void main()
{
	init();  	//初始化
	while(1)	//不停地对键盘和显示进行扫描
	{
		keyscan(); //键盘扫描和密码输入处理
		display(); //LCD显示
	}
}

完整资料:

https://market.m.taobao.com/app/idleFish-F2e/widle-taobao-rax/page-detail?wh_weex=true&wx_navbar_transparent=true&id=614516242692&ut_sk=1.WUpxx7gpwUoDAMmnnrBIzAno_12431167_1585208034475.Copy.detail.614516242692.1828622527&forceFlush=1

发布了23 篇原创文章 · 获赞 7 · 访问量 332

猜你喜欢

转载自blog.csdn.net/weixin_41017942/article/details/105119750