电子密码锁设计-单片机课程设计

密码锁

电子密码锁-AT89C51-储存AT24C02

本系统由STC89C52单片机系统(主要是STC89C52单片机最小系统)、4×4矩阵键盘、LCD1602显示和报警系统等组成,具有设置、修改六位用户密码、超次报警、超次锁定、密码错误报警等功能(本设计由P0口控制LCD显示,密码正确显示OPEN! 密码错误显示error!超过三次输入错误自动锁定。由P1口控制矩阵键盘含有0-9数字键和A-F功能键。)
2.本设计拟实现的性能指标如下:
(1)本设计为了防止密码被窃取要求在输入密码时在LCD屏幕上显示号。
(2)设计开锁密码位六位密码的电子密码锁。
(3)能够LCD显示在密码正确时显示OPEN,密码错误时显示ERROR。
(4)实现输入密码错误超过限定的三次电子密码锁定。
(5)4×4的矩阵键盘其中包括0-9的数字键和A-D的功能键和
、#按键。

(6)本产品具备报警功能,当输入密码错误时蜂鸣器响提示。
(7)密码可以由用户自己修改设定(只支持6位密码),修改密码之前必须再次输入密码,在输入新密码时候需要二次确认,以防止误操作 。
(8)输入正确的密码继电器闭合,可以随意驱动负载。
AT24C02
AT24C02是美国Atmel公司的低功耗CMOS型E2PROM,内含256×8位存储空间,具有工作电压宽(2.5~5.5 V)、擦写次数多(大于10000次)、写入速度快(小于10 ms)、抗干扰能力强、数据不易丢失、体积小等特点。而且他是采用了I2C总线式进行数据读写的串行器件,占用很少的资源和I/O线,并且支持在线编程,进行数据实时的存取十分方便。AT24C02中带有的片内地址寄存器。每写入或读出一个数据字节后,该地址寄存器自动加1,以实现对下一个存储单元的读写。所有字节均以单一操作方式读取。为降低总的写入时间,一次操作可写入多达8个字节的数据。I2C总线是一种用于IC器件之间连接的二线制总线。他通过SDA(串行数据线)及SCL(串行时钟线)两根线在连到总线上的器件之间传送信息,并根据地址识别每个器件。AT24C02正是运用了I2C规程,使用主/从机双向通信,主机(通常为单片机)和从机(AT24C02)均可工作于接收器和发送器状态。主机产生串行时钟信号(通过SCL引脚)并发出控制字,控制总线的传送方向,并产生开始和停止的条件。无论是主机还是从机,接收到一个字节后必须发出一个确认信号ACK。AT24C02的控制字由8位二进制数构成,在开始信号发出以后,主机便会发出控制字,以选择从机并控制总线传送的方向。
SOIC                 PDIP
SOIC/ PDIP - 24C02的两种引脚图
AT24C02的电路接线图
AT24C02的电路接线图
图中AT24C02的1、2、3脚是三条地址线,用于确定芯片的硬件地址。第8脚和第4脚分别为正、负电源。第5脚SDA为串行数据输入/输出,数据通过这条双向I2C总线串行传送,第6脚SCL为串行时钟输入线, SDA和SCL都需要和正电源间各接一个10 K的电阻上拉。第7脚需要接地。
24C02中带有片内地址寄存器。每写入或读出一个数据字节后,该地址寄存器自动加1,以实现对下一个存储单元的读写。所有字节均以单一操作方式读取。为降低总的写入时间,一次操作可写入多达8个字节的数据。
LCD显示模块
LCD1602A 是一种工业字符型液晶,能够同时显示16x02 即32个字符。(16列2行)。在日常生活中,我们对液晶显示器并不陌生。液晶显示模块已作为很多电子产品的通过器件,如在计算器、万用表、电子表及很多家用电子产品中都可以看到,显示的主要是数字、专用符号和图形。在单片机的人机交流界面中,一般的输出方式有以下几种:发光管、LED数码管、液晶显示器。发光管和LED数码管比较常用,软硬件都比较简单。
在单片机系统中应用晶液显示器作为输出器件有以下几个优点:
由于液晶显示器每一个点在收到信号后就一直保持那种色彩和亮度,恒定发光,而不像阴极射线管显示器(CRT)那样需要不断刷新新亮点。因此,液晶显示器画质高且不会闪烁。
液晶显示器都是数字式的,和单片机系统的接口更加简单可靠,操作更加方便。
液晶显示器通过显示屏上的电极控制液晶分子状态来达到显示的目的,在重量上比相同显示面积的传统显示器要轻得多。
相对而言,液晶显示器的功耗主要消耗在其内部的电极和驱动IC上,因而耗电量比其它显示器要少得多。
(1)引脚说明:
第1脚:VSS为地电源。
第2脚:VDD接5V正电源。
第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。
第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平
R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。
第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
第7~14脚:D0~D7为8位双向数据线。
第15脚:背光源正极。
第16脚:背光源负极。

源文件下载
链接: 源文件下载.

仿真图

电子密码锁-AT89C51-储存AT24C02

代码

//包含头文件
#include <REG51.h>
#include<intrins.h>
//宏定义
#define LCM_Data  P0		  //将P0口定义为LCM_Data
#define uchar unsigned char 
#define uint  unsigned int
//1602的控制脚
sbit lcd1602_rs=P2^5;
sbit lcd1602_rw=P2^6;
sbit lcd1602_en=P2^7;

sbit Scl=P3^4;			//24C02串行时钟
sbit Sda=P3^5;			//24C02串行数据

sbit ALAM = P2^1;		//报警	
sbit KEY = P3^6;		//开锁

bit  pass=0;			//密码正确标志
bit  ReInputEn=0;		//重置输入允许标志	
bit  s3_keydown=0;		//3秒按键标志位
bit  key_disable=0;		//锁定键盘标志

unsigned char countt0,second;	//t0中断计数器,秒计数器

void Delay5Ms(void);		//声明延时函数

unsigned char code a[]={0xFE,0xFD,0xFB,0xF7}; 				//控盘扫描控制表
//液晶显示数据数组
unsigned char code start_line[]	= {"password:       "};
unsigned char code name[] 	 	= {"===Coded Lock==="};	//显示名称
unsigned char code Correct[] 	= {"     correct    "};		//输入正确
unsigned char code Error[]   	= {"      error     "};  	//输入错误
unsigned char code codepass[]	= {"      pass      "}; 
unsigned char code LockOpen[]	= {"      open      "};		//OPEN
unsigned char code SetNew[] 	= {"SetNewWordEnable"};
unsigned char code Input[]   	= {"input:          "};		//INPUT
unsigned char code ResetOK[] 	= {"ResetPasswordOK "};
unsigned char code initword[]	= {"Init password..."};
unsigned char code Er_try[]		= {"error,try again!"};
unsigned char code again[]		= {"input again     "};

unsigned char InputData[6];									//输入密码暂存区
unsigned char CurrentPassword[6]={0,0,0,0,0,0}; 			//读取EEPROM密码暂存数组
unsigned char TempPassword[6];
unsigned char N=0;				//密码输入位数记数
unsigned char ErrorCont;			//错误次数计数
unsigned char CorrectCont;			//正确输入计数
unsigned char ReInputCont; 			//重新输入计数
unsigned char code initpassword[6]={0,0,0,0,0,0};			//输入管理员密码后将密码初始为000000
unsigned char code adminpassword[6]={1,3,1,4,2,0};			//输入管理员密码后将密码初始为000000


//=====================5ms延时==============================
void Delay5Ms(void)
{
	unsigned int TempCyc = 5552;
	while(TempCyc--);
}

//===================400ms延时==============================
void Delay400Ms(void)
{
 unsigned char TempCycA = 5;
 unsigned int TempCycB;
 while(TempCycA--)
 {
  TempCycB=7269;
  while(TempCycB--);
 }
}

//=============================================================================================
//================================24C02========================================================
//=============================================================================================

void mDelay(uint t) //延时
{ 
	uchar i;
   	while(t--)
   	{
   		for(i=0;i<125;i++)
   		{;}
   	}
}
   

void Nop(void)		  //空操作
{
 	_nop_();		  //仅作延时用一条语句大约1us
 	_nop_();
 	_nop_();
 	_nop_();
}

/*****24c02程序参照24c02时序图*****/
/*起始条件*/

void Start(void)
{
 	Sda=1;
 	Scl=1;
 	Nop();
 	Sda=0;
 	Nop();
}


 /*停止条件*/
void Stop(void)
{
 	Sda=0;
 	Scl=1;
 	Nop();
 	Sda=1;
 	Nop();
}

/*应答位*/
void Ack(void)
{
	Sda=0;
	Nop();
	Scl=1;
	Nop();
	Scl=0;
}

/*反向应答位*/
void NoAck(void)
{
 	Sda=1;
 	Nop();
 	Scl=1;
 	Nop();
 	Scl=0;
}

 /*发送数据子程序,Data为要求发送的数据*/
void Send(uchar Data)
{
   	uchar BitCounter=8;
   	uchar temp;
   	do
   	{
   		temp=Data;					   //将待发送数据暂存temp
   		Scl=0;
   		Nop();
   		if((temp&0x80)==0x80)		   //将读到的数据&0x80
   		Sda=1;
   		else 
   		Sda=0;
   		Scl=1;
   		temp=Data<<1;				   //数据左移
   		Data=temp;					   //数据左移后重新赋值Data
   		BitCounter--;				   //该变量减到0时,数据也就传送完成了
   	}
   	while(BitCounter);				   //判断是否传送完成
   	Scl=0;
}

/*读一字节的数据,并返回该字节值*/
uchar Read(void)
{
    uchar temp=0;
	uchar temp1=0;
	uchar BitCounter=8;
	Sda=1;
	do
	{
		Scl=0;
		Nop();
		Scl=1;
		Nop();
		if(Sda)				   //数据位是否为1
			temp=temp|0x01;	   //为1 temp的最低位为1(|0x01,就是将最低位变为1)
		else				   //如果为0
			temp=temp&0xfe;	   //temp最低位为0(&0xfe(11111110)最低位就是0)
		if(BitCounter-1)	   //BitCounter减1后是否为真
		{
			temp1=temp<<1;	   //temp左移
			temp=temp1;
		}
		BitCounter--;		   //BitCounter减到0时,数据就接收完了
	}
	while(BitCounter);		   //判断是否接收完成
	return(temp);
}

void WrToROM(uchar Data[],uchar Address,uchar Num)
{
  uchar i;
  uchar *PData;
  PData=Data;
  for(i=0;i<Num;i++)
  {
  Start();
  Send(0xa0);
  Ack();
  Send(Address+i);
  Ack();
  Send(*(PData+i));
  Ack();
  Stop();
  mDelay(20);
  }
}

void RdFromROM(uchar Data[],uchar Address,uchar Num)
{
  uchar i;
  uchar *PData;
  PData=Data;
  for(i=0;i<Num;i++)
  {
  Start();
  Send(0xa0);
  Ack();
  Send(Address+i);
  Ack();
  Start();
  Send(0xa1);
  Ack();
  *(PData+i)=Read();
  Scl=0;
  NoAck();
  Stop();
  }
}


//==================================================================================================
//=======================================LCD1602====================================================
//==================================================================================================

#define yi 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)
#define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)


//----------------延时函数,后面经常调用----------------------
void delay(uint xms)//延时函数,有参函数
{
	uint x,y;
	for(x=xms;x>0;x--)
	 for(y=110;y>0;y--);
}

//--------------------------写指令---------------------------
void write_1602com(uchar com)//****液晶写入指令函数****
{
	lcd1602_rs=0;//数据/指令选择置为指令
	lcd1602_rw=0; //读写选择置为写
	P0=com;//送入数据
	delay(1);
	lcd1602_en=1;//拉高使能端,为制造有效的下降沿做准备
	delay(1);
	lcd1602_en=0;//en由高变低,产生下降沿,液晶执行命令
}

//-------------------------写数据-----------------------------
void write_1602dat(uchar dat)//***液晶写入数据函数****
{
	lcd1602_rs=1;//数据/指令选择置为数据
	lcd1602_rw=0; //读写选择置为写
	P0=dat;//送入数据
	delay(1);
	lcd1602_en=1; //en置高电平,为制造下降沿做准备
	delay(1);
	lcd1602_en=0; //en由高变低,产生下降沿,液晶执行命令
}

//-------------------------初始化-------------------------
void lcd_init(void)
{
	write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据
	write_1602com(0x0c);//开显示不显示光标
	write_1602com(0x06);//整屏不移动,光标自动右移
	write_1602com(0x01);//清显示
}
//========================================================================================
//=========================================================================================
//==============将按键值编码为数值=========================
unsigned char coding(unsigned char m)	 
{
	unsigned char k;
	switch(m)
	{
		case (0x11): k=1;break;
		case (0x21): k=2;break;
		case (0x41): k=3;break;
		case (0x81): k='A';break;
		case (0x12): k=4;break;
		case (0x22): k=5;break;
		case (0x42): k=6;break;
		case (0x82): k='B';break;
		case (0x14): k=7;break;
		case (0x24): k=8;break;
		case (0x44): k=9;break;
		case (0x84): k='C';break;
		case (0x18): k='*';break;
		case (0x28): k=0;break;
		case (0x48): k='#';break;
		case (0x88): k='D';break;
	}
	return(k);
}
//=====================按键检测并返回按键值===============================
unsigned char keynum(void)
{
 	unsigned char row,col,i;
 	P1=0xf0;
 	if((P1&0xf0)!=0xf0)
 	{
	   	Delay5Ms();
        Delay5Ms();
   		if((P1&0xf0)!=0xf0)
		{
    		row=P1^0xf0;          //确定行线
			i=0;
			P1=a[i];	          //精确定位
			while(i<4)
			{
	 			if((P1&0xf0)!=0xf0)
	  			{
	   				col=~(P1&0xff);	  //确定列线
	   				break;            //已定位后提前退出   
	  			}
				else 
	  			{
	   				i++;
	   				P1=a[i];
	  			}
			}
		}
		else 
		{
			return 0;
		}
		while((P1&0xf0)!=0xf0);
		return (row|col);	 		//行线与列线组合后返回
 	}
 	else return 0;	         		//无键按下时返回0
}
//=======================一声提示音,表示有效输入========================
void OneAlam(void)
{
	ALAM=0;
	Delay5Ms();
    ALAM=1;
}
//========================二声提示音,表示操作成功========================
void TwoAlam(void)
{
	ALAM=0;
	Delay5Ms();
    ALAM=1;
    Delay5Ms();
	ALAM=0;
	Delay5Ms();
    ALAM=1;
}
//========================三声提示音,表示错误========================
void ThreeAlam(void)
{
	ALAM=0;
	Delay5Ms();
    ALAM=1;
    Delay5Ms();
	ALAM=0;
	Delay5Ms();
    ALAM=1;
    Delay5Ms();
	ALAM=0;
	Delay5Ms();
    ALAM=1;
}
//=======================显示提示输入=========================
void DisplayChar(void)
{
	unsigned char i;
	if(pass==1)
	{
		//DisplayListChar(0,1,LockOpen);
		write_1602com(er);				   //在二行开始显示
		for(i=0;i<16;i++)
		{
			write_1602dat(LockOpen[i]);	   //显示open 开锁成功
		}
	}
	else
	{
		if(N==0)
		{
			//DisplayListChar(0,1,Error);
			write_1602com(er);
			for(i=0;i<16;i++)
			{
				write_1602dat(Error[i]);	//显示错误
			}
		}
		else
		{
			//DisplayListChar(0,1,start_line);	
			write_1602com(er);
			for(i=0;i<16;i++)
			{
				write_1602dat(start_line[i]);//显示开始输入	
			}
		}
	}
}

//========================重置密码==================================================
//==================================================================================
void ResetPassword(void)
{
	unsigned char i;	
	unsigned char j;
	if(pass==0)
	{
		pass=0;			   
		DisplayChar();	   //显示错误
		ThreeAlam();	   //没开锁时按下重置密码报警3声
	}
	else				   //开锁状态下才能进行密码重置程序
	{
    	if(ReInputEn==1)   //开锁状态下,ReInputEn置1,重置密码允许
		{
			if(N==6)	   //输入6位密码
			{
				ReInputCont++;			//密码次数计数	
				if(ReInputCont==2)		//输入两次密码
				{
					for(i=0;i<6;)
					{
						if(TempPassword[i]==InputData[i])	//将两次输入的新密码作对比
							i++;
						else								//如果两次的密码不同
						{
							//DisplayListChar(0,1,Error);
							write_1602com(er);
							for(j=0;j<16;j++)
							{
								write_1602dat(Error[j]);	//显示错误Error
							}
							ThreeAlam();			//错误提示	
							pass=0;					//关锁
							ReInputEn=0;			//关闭重置功能,
							ReInputCont=0;
							DisplayChar();
							break;
						}
					} 
					if(i==6)
					{
						//DisplayListChar(0,1,ResetOK);
						write_1602com(er);
						for(j=0;j<16;j++)
						{
							write_1602dat(ResetOK[j]);	  //密码修改成功,显示
						}

						TwoAlam();				//操作成功提示
					 	WrToROM(TempPassword,0,6);		//将新密码写入24C02存储
						ReInputEn=0;
					}
					ReInputCont=0;
					CorrectCont=0;
				}
				else					  //输入一次密码时
				{
					OneAlam();
					//DisplayListChar(0, 1, again); 		//显示再次输入一次
					write_1602com(er);
					for(j=0;j<16;j++)
					{
						write_1602dat(again[j]);			//显示再输入一次
					}					
					for(i=0;i<6;i++)
					{
						TempPassword[i]=InputData[i];		//将第一次输入的数据暂存起来						
					}
				}

			N=0;						//输入数据位数计数器清零
		   }
	    }
	}
}
//=======================输入密码错误超过三过,报警并锁死键盘======================
void Alam_KeyUnable(void)
{
	P1=0x00;
	{
		ALAM=~ALAM;				 //蜂鸣器一直闪烁鸣响
		Delay5Ms();
	}
}
//=======================取消所有操作============================================
void Cancel(void)
{	
	unsigned char i;
	unsigned char j;
	//DisplayListChar(0, 1, start_line); 
	write_1602com(er);
	for(j=0;j<16;j++)
	{
		write_1602dat(start_line[j]);	  //显示开机输入密码界面
	}
	TwoAlam();				//提示音
	for(i=0;i<6;i++)
	{
		InputData[i]=0;		//将输入密码清零
	}
	KEY=1;					//关闭锁
	ALAM=1;					//报警关
	pass=0;					//密码正确标志清零
	ReInputEn=0;			//重置输入充许标志清零
	ErrorCont=0;			//密码错误输入次数清零
	CorrectCont=0;			//密码正确输入次数清零
	ReInputCont=0;			//重置密码输入次数清零 
	s3_keydown=0;
	key_disable=0;			//锁定键盘标志清零
	N=0;					//输入位数计数器清零
}

//==========================确认键,并通过相应标志位执行相应功能===============================
void Ensure(void)
{	
	unsigned char i,j;
	RdFromROM(CurrentPassword,0,6); 					//从24C02里读出存储密码
    if(N==6)
	{
	    if(ReInputEn==0)							//重置密码功能未开启
		{
			for(i=0;i<6;)
   			{					
				if(CurrentPassword[i]==InputData[i])	//判断输入密码和24c02中的密码是否相同
				{
					i++;								//相同一位 i就+1
				}
				else 									//如果有密码不同
				{										
					ErrorCont++;						//错误次数++
					if(ErrorCont==3)			//错误输入计数达三次时,报警并锁定键盘
					{
						write_1602com(er);
						for(i=0;i<16;i++)
						{
							write_1602dat(Error[i]);	
						}
						do
						Alam_KeyUnable();
						while(1);
					}
					else					 //错误次数小于3次时,锁死键盘3秒,然后重新可以输入
					{
						TR0=1;				//开启定时
						key_disable=1;			//锁定键盘
						pass=0;					//pass位清零
						break;					//跳出
					}
				}
			}

			if(i==6)					 //密码输入对时
			{
				if((InputData[0]==adminpassword[0])&&(InputData[1]==adminpassword[1])&&(InputData[2]==adminpassword[2])&&(InputData[3]==adminpassword[3])&&(InputData[4]==adminpassword[4])&&(InputData[5]==adminpassword[5]))
		  	 	{
					WrToROM(initpassword,0,6); 				//强制将初始密码写入24C02存储
					write_1602com(er);
					for(j=0;j<16;j++)
					{
						write_1602dat(initword[j]);				//显示初始化密码
					}
					TwoAlam();									//成功提示音
					Delay400Ms();								//延时400ms
					TwoAlam();									//成功提示音
					N=0;										//输入位数计数器清零
				}
				else 
				{
					CorrectCont++;					//输入正确变量++
					if(CorrectCont==1)				//正确输入计数,当只有一次正确输入时,开锁
					{
						//DisplayListChar(0,1,LockOpen);
						write_1602com(er);
						for(j=0;j<16;j++)
						{
							write_1602dat(LockOpen[j]);		  //显示open开锁画面
						}
						TwoAlam();			//操作成功提示音
						KEY=0;											//开锁
						pass=1;											//置正确标志位
						TR0=1;											//开启定时
						for(j=0;j<6;j++)								//将输入清除
						{
							InputData[i]=0;								//开锁后将输入位清零
						}
					}	
					else												//当两次正确输入时,开启重置密码功能
					{
						write_1602com(er);
						for(j=0;j<16;j++)
						{
							write_1602dat(SetNew[j]);					//显示重置密码界面
						}
						TwoAlam();									    //操作成功提示
						ReInputEn=1;									//允许重置密码输入
						CorrectCont=0;									//正确计数器清零
					}
				}
	  		}
	
			else			//=========================当第一次使用或忘记密码时可以用131420对其密码初始化============
			{
				if((InputData[0]==adminpassword[0])&&(InputData[1]==adminpassword[1])&&(InputData[2]==adminpassword[2])&&(InputData[3]==adminpassword[3])&&(InputData[4]==adminpassword[4])&&(InputData[5]==adminpassword[5]))
		  	 	{
					WrToROM(initpassword,0,6); 				//强制将初始密码写入24C02存储
					write_1602com(er);
					for(j=0;j<16;j++)
					{
						write_1602dat(initword[j]);				//显示初始化密码
					}
					TwoAlam();									//成功提示音
					Delay400Ms();								//延时400ms
					TwoAlam();									//成功提示音
					N=0;										//输入位数计数器清零
				}
				else											//密码输入错误
				{
					write_1602com(er);
					for(j=0;j<16;j++)
					{
						write_1602dat(Error[j]);				 //显示错误信息
					}
 					ThreeAlam();										//错误提示音
					pass=0;	
				}
			}
		}

		else											//当已经开启重置密码功能时,而按下开锁键,
		{
			//DisplayListChar(0,1,Er_try);
			write_1602com(er);
			for(j=0;j<16;j++)
			{
				write_1602dat(Er_try[j]);			  //错误,请重新输入
			}
			ThreeAlam();							  //错误提示音
		}
	}

	else				   //密码没有输入到6位时,按下确认键时
	{
		//DisplayListChar(0,1,Error);
		write_1602com(er);
		for(j=0;j<16;j++)
		{
			write_1602dat(Error[j]);		 //显示错误
		}

 		ThreeAlam();										//错误提示音
		pass=0;	
	}
	
	N=0;													//将输入数据计数器清零,为下一次输入作准备
}


//==============================主函数===============================
void main(void)
{
 	unsigned char KEY,NUM;
	unsigned char i,j;
 	P1=0xFF; 				   //P1口复位
	TMOD=0x11;				   //定义工作方式
 	TL0=0xB0;
 	TH0=0x3C;				   //定时器赋初值
 	EA=1;					   //打开中断总开关
 	ET0=1;					   //打开中断允许开关
 	TR0=0;					   //打开定时器开关
 	Delay400Ms(); 	//启动等待,等LCM讲入工作状态
 	lcd_init(); 	//LCD初始化
	write_1602com(yi);//日历显示固定符号从第一行第0个位置之后开始显示
	for(i=0;i<16;i++)
	{
		write_1602dat(name[i]);//向液晶屏写开机画面
	}
	write_1602com(er);
	for(i=0;i<16;i++)
	{
		write_1602dat(start_line[i]);//写输入密码等待界面
	}
	write_1602com(er+9);	//设置光标位置
	write_1602com(0x0f);	//设置光标为闪烁
 	Delay5Ms(); //延时片刻(可不要)

 	N=0;														//初始化数据输入位数
 	while(1)		 //进入循环
 	{
		if(key_disable==1)						//锁定键盘标志为1时
			Alam_KeyUnable();					//报警键盘锁
		else
			ALAM=1;								//关报警

		KEY=keynum();							//读按键的位置码
		if(KEY!=0)								//当有按键按下时
		{	
			if(key_disable==1)					//锁定键盘标志为1时
			{
				second=0;						//秒清零
			}
			else								//没有锁定键盘时
			{
				NUM=coding(KEY);				//根据按键的位置将其编码,编码值赋值给NUM
				{
					switch(NUM)					//判断按键值
					{
						case ('A'): 	; 					break;
						case ('B'):		;     				break;
						case ('C'):
									write_1602com(yi);//日历显示固定符号从第一行第0个位置之后开始显示
									for(i=0;i<16;i++)
									{
										write_1602dat(name[i]);//向液晶屏写开机画面
									}
									if(N>=1) N--;	OneAlam();								//按键提示音						
									//DisplayOneChar(6+N,1,'*');
									for(j=N;j<16;j++)
									{
										write_1602com(er+6+j);
										write_1602dat(' ');
									}
									for(j=0;j<N;j++)
									{
										write_1602com(er+6+j);				//显示位数随输入增加而增加
										write_1602dat('*');					//但不显示实际数字,用*代替
									}  
									InputData[N]=N+4;
									break;		//ABC是无定义按键
						case ('D'): ResetPassword();		break;      //重新设置密码
						case ('*'): Cancel();				break;      //取消当前输入
						case ('#'): Ensure(); 				break;   	//确认键,
						default: 										//如果不是功能键按下时,就是数字键按下
						{	
							//DisplayListChar(0,1,Input);
							if(N<6)                   					//当输入的密码少于6位时,接受输入并保存,大于6位时则无效。
							{ 
								write_1602com(er);
								for(i=0;i<16;i++)
								{
									write_1602dat(Input[i]);				//显示输入画面
								} 
								OneAlam();								//按键提示音	
						 		for(j=0;j<=N;j++)
								{
									write_1602com(er+6+j);				//显示位数随输入增加而增加
									write_1602dat('*');					//但不显示实际数字,用*代替
								}
								InputData[N]=NUM;						//将数字键的码赋值给InputData[]数组暂存
								N++;									//密码位数加
							}
							else										//输入数据位数大于6后,忽略输入
							{
								N=6;									//密码输入大于6位时,不接受输入
						 		break;
							}
						}
					}
				}
			}
	 	} 
	}
}

//*********************************中断服务函数**************************************
void  time0_int(void) interrupt 1 		   //定时器T0
{
 	TL0=0xB0;
 	TH0=0x3C;		  //定时器重新赋初值
 	//TR0=1;
 	countt0++;			   //计时变量加,加1次时50ms
  	if(countt0==20)		   //加到20次就是1s
   	{
		countt0=0;		   //变量清零
		second++;		   //秒加
		if(pass==1)		   //开锁状态时
		{
			if(second==1)			//秒加到1s时
			{
				TR0=0;				//关定时器
				TL0=0xB0;
 				TH0=0x3C;			//再次赋初值
				second=0;			//秒清零
			}
		}
		else						//不在开锁状态时
		{
			if(second==3)			//秒加到3时
			{
				TR0=0;				//关闭定时器
				second=0;			//秒清零
				key_disable=0;		//锁定键盘清零
				s3_keydown=0;	
				TL0=0xB0;
				TH0=0x3C;			//重新赋初值
			}
			else
			    TR0=1;				//打开定时器
		}
			
   	}
}

源文件下载

链接: 源文件下载.

  • 42
    点赞
  • 475
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 16
    评论
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个小小白 - 呀吼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值