C51单片机学习——密码锁的实现

C51单片机学习——密码锁的实现

  • 说在前面:因为我的板子是液晶屏和数码管不能同时用,所以下面我使用的是液晶屏,下面的代码通俗易懂也有注释,如果有的控件不知到如何使用的可以查看我之前的几篇C51文章,这个密码锁就是基于之前的笔记所写的内容
#include<reg52.h>
//#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define data1602 P0
#define LED P2
/*******引脚定义*******/
//按键的控制引脚
sbit S1 = P3^7;
sbit S2 = P3^6;
sbit S3 = P3^5;
sbit S4 = P3^4;
sbit S5 = P3^3;
sbit S6 = P3^2;

//LCD1602的控制引脚
sbit RS = P1^0;
sbit RW = P1^1;
sbit E = P1^2;
sbit BF = data1602^7; //BF表示data1602的最高位,判断是忙还是闲

sbit Alam = P1^5;//蜂鸣器引脚
//sbit key = P3^3;//开锁

bit	 isInitPass = 1;//是否在初始化密码
bit  pass=0;                   //密码正确标志
bit  isReset = 0;             //是否在重设密码  
uchar countNum = 0;	 //选择数字位数
uchar countPass = 1;//输入密码位数
uchar ErrorCont = 0;                    //错误次数计数
uchar timeNum=0;		        //计时间次数
uchar trueTime='5';		  // 锁定时间                  
//液晶显示数据数组
uchar code initLock1[] = {"   Welcome to   "};
uchar code initLock2[] = {"  password lock "};
uchar code SetNew[] = {"==SetPassword== "};
uchar code Input[] = {"input:          "};  //INPUT
uchar code start_line1[] = {"==please input=="};
uchar code start_line2[] = {"password:       "};
uchar code superPassword[] = {"=Super Password="};
uchar code Correct[] = {"     correct    "};  //输入正确
uchar code Error[] = {"      error     "};    //输入错误
uchar code codepass[] = {"      pass      "}; 
uchar code LockOpen[] = {"      open      "};   //OPEN
uchar code Reset[] = {"=ResetPassword= "};
uchar code oldPassword[] = {"please input old"}; //输入旧密码
uchar code setOK[] = {"Set Password OK "};
uchar code NULL[] = {"                "};
uchar code ResetOK[] = {"ResetPasswordOK!"};
uchar code initword[] = {"Init password..."};
uchar code ErrorTry[] = {"error,try again!"};
uchar code again[] = {"input again     "};
uchar code wait[] = {"please wait   s  "};
uchar code table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//流水灯

uchar InitPassword[6]={'0','0','0','0','0','0'};       //初始化密码暂存数组
uchar CurrentPassword[6]={'0','0','0','0','0','0'};//输入密码暂存数组
uchar adminpassword[6]={'1','3','1','4','2','0'};//管理员密码
uchar PassNum[10] = {'0','1','2','3','4','5','6','7','8','9'};  //存放所有数字

/*******延时函数*******/
void delay(uint z)//z毫秒
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);
}
/*******空函数*******/
/*void Nop(void)                  //空操作
{
	_nop_();                  //仅作延时用一条语句大约1us
    _nop_();
    _nop_();
    _nop_();
}*/
/*******忙检测函数*******/
bit LCD_busy()
{
	bit busy;
	P0 = 0xff;//防止干扰
	RS = 0;	 //命令模式
	RW = 1;   //读模式
	E = 1;
	busy = BF;//将忙标志位的数值赋给busy
	E = 0;
	return busy;
}
/*******写命令函数*******/
void LCD_write_cmd(uchar cmd)//cmd为需要写的命令
{
	while(LCD_busy());//只有当LCD_busy()为0(闲)时才跳出循环   
	RS = 0;		   //命令模式
	RW = 0;		   //写模式
	data1602 = cmd;	   //将命令内容的十六进制送到P0端口
	delay(1);
	E = 1;         //拉高使能端,为制造有效的下降沿做准备
	delay(1);
	E = 0;			//由高变低,产生下降沿,液晶执行命令,使命令送到LCD1602的DB0~DB7
}
/*******写数据函数*******/
void LCD_write_data(uchar dat)//dat为需要写的数据
{
	while(LCD_busy());//只有当LCD_busy()为0(闲)时才跳出循环   
	RS = 1;		   //数据模式
	RW = 0;		   //写模式
	data1602 = dat;	   //将数据内容的十六进制送到P0端口
	delay(1);
	E = 1;
	delay(1);
	E = 0;			//使能端,高电平有效,使命令送到LCD1602的DB0~DB7
}
/*******IT0中断初始化函数*******/
void IT_init()
{
	IT0 = 0; //设置低电平触发外部中断
	EA = 1;  //开总中断
	EX0 = 1;//开外部中断
}
/*******定时器T0中断初始化函数*******/
void Time_init()
{
	TMOD = 0x01;//将定时器0设为方式1,即16位定时器
	TH0 = (65536-45872)/256;//给定时器的高八位赋初值
	TL0 = (65536-45872)%256;//给定时器的低八位赋初值
	EA = 1;//开总中断
	ET0 = 1;//开定时器0中断
}
/*******LCD初始化函数*******/
void LCD_init()
{
	LCD_write_cmd(0x38); //将设置“两行、八位数据、5*7的点阵”命令写入LCD的控制器
	LCD_write_cmd(0x0c); //开显示关光标
	LCD_write_cmd(0x06); //光标右移指令
	LCD_write_cmd(0x01); //清除显示
}
/*******LCD写显示地址函数*******/
void LCD_write_address(uchar x,uchar y)
{
	x&=0x0f;  //列地址限制在0~15之间
	y&=0x01;  //行地址限制在0~1
	if(y==0)
		LCD_write_cmd(x|0x80);//数据指针=80+地址变量,写入列地址
	else
		LCD_write_cmd((x+0x40)|0x80);	  //如果是第二行,将列地址写入
}
/*******LCD显示函数*******/
void LCD_display(uchar x,uchar y,uchar buf)	//x:列 y:行,buf:显示的字符
{
	LCD_write_address(x,y);//先将地址写入
	LCD_write_data(buf);	//再写入要显示的数据
}

/*******一声提示音,表示有效输入*******/
void OneAlam()
{
	Alam=0;	   //蜂鸣器响
    delay(100);  //延时5ms
   	Alam=1;	   //蜂鸣器关
}

/*******两声提示音,表示操作成功*******/
void TwoAlam()
{
	uchar i = 0;
	for(i=0;i<2;i++)
	{
		Alam=0;	   //蜂鸣器响
    	delay(100);  //延时5ms
   		Alam=1;	   //蜂鸣器关
		delay(100);	
	}
}

/*******三声提示音,表示错误*******/
void ThreeAlam()
{
	uchar i = 0;
	for(i=0;i<3;i++)
	{
		Alam=0;	   //蜂鸣器响
    	delay(100);  //延时5ms
   		Alam=1;	   //蜂鸣器关
		delay(100);	
	}
}
/*******流水灯函数*******/
void LED_display()
{
	uint i;
	for(i=0;i<8;i++)   //数组控制流水灯
	{
		LED = table[i];
		delay(500);
	}
	LED = 0x00;
	delay(1000);
	LED = 0xff;
}

/*******初始化界面函数*******/
void init_display()
{
	uchar i;
	for(i=0;i<16;i++)
		LCD_display(i,0,initLock1[i]);
	for(i=0;i<16;i++)
		LCD_display(i,1,initLock2[i]);
}
/*******按键控制输入密码函数*******/
void pushBtn_password()
{
	countNum = 0;
	countPass = 1;
	LCD_write_cmd(0x0e); //光标闪烁
	while(1)
	{
		if(S1 == 0)     //第一次检测按键被按下
		{
			delay(8);   //延时8ms进行消抖
			if(S1 == 0)	  //再次检测按键被按下,说明确实被按下了
			{
				if(isInitPass)
					LCD_display(6+countPass,1,PassNum[countNum]); //显示数字
				else
					LCD_display(9+countPass,1,PassNum[countNum]);			
				LCD_write_cmd(0x10);	//光标左移
				if(isInitPass)
					InitPassword[countPass-1] = PassNum[countNum]; //将输入的数字存到初始化数组中
				else
					CurrentPassword[countPass-1] = PassNum[countNum];//将输入的数字存到当前数组中

				if(countNum == 9)
					countNum = 0;
				else
					countNum++;			
			}
			delay(300);
		}
		if(S3 == 0)     //第一次检测按键被按下
		{
			delay(8);   //延时8ms进行消抖
			if(S3 == 0)	  //再次检测按键被按下,说明确实被按下了
			{
				countNum = 0;
				if(countPass == 6)
					countPass = 1;
				else
					countPass++;
				if(isInitPass)
					LCD_display(6+countPass,1,InitPassword[countPass-1]); 
				else
					LCD_display(9+countPass,1,CurrentPassword[countPass-1]);	
				LCD_write_cmd(0x10);			
			}
			delay(250);
		}
		if(S4 == 0)
		{
			delay(8);   //延时8ms进行消抖
			if(S4 == 0)	  //再次检测按键被按下,说明确实被按下了
			{
				countNum = 0;
				if(countPass>1)
					countPass--;
				else
					countPass = 1;
	   		}
			if(isInitPass)
				LCD_display(6+countPass,1,InitPassword[countPass-1]); 
			else
				LCD_display(9+countPass,1,CurrentPassword[countPass-1]);			
			LCD_write_cmd(0x10);
			delay(300);
		}
		if(S5 == 0)
		{
			delay(8);
			if(S5 == 0)
			{
				break;
			}
		}
	}
	LCD_write_cmd(0x0c); //光标不闪烁	
}

/*******最初设置密码函数*******/
void init_password()
{
	uchar i = 0;
	for(i=0;i<16;i++)
		LCD_display(i,0,SetNew[i]);
	for(i=0;i<16;i++)
		LCD_display(i,1,Input[i]);
	pushBtn_password();    //按键控制输入密码
	for(i=0;i<16;i++)
		LCD_display(i,0,NULL[i]);
	for(i=0;i<16;i++)
		LCD_display(i,1,NULL[i]);

	for(i=0;i<13;i++)
		LCD_display(i,0,initword[i]);
	delay(500);
	LCD_display(13,0,initword[13]);//滚动显示初始化中
	delay(500);
	LCD_display(14,0,initword[14]);
	delay(500);
	LCD_display(15,0,initword[15]);
	delay(500);
	for(i=0;i<16;i++)
		LCD_display(i,0,setOK[i]);
	TwoAlam();//两声提示音,表示操作成功
	isInitPass = 0; 		
}
/*******判断是否输入正确函数*******/
void judge()
{
	uchar jg = 0;
	uchar i;
	if((CurrentPassword[0]==InitPassword[0])&&(CurrentPassword[1]==InitPassword[1])&&(CurrentPassword[2]==InitPassword[2])&&(CurrentPassword[3]==InitPassword[3])&&(CurrentPassword[4]==InitPassword[4])&&(CurrentPassword[5]==InitPassword[5]))
	{
		if(isReset==0)
			jg = 1;	//正确输入密码
		else
			jg = 3;	//正确输入密码且在重设密码
		pass = 1;   //密码正确
	}	
	else if((CurrentPassword[0]==adminpassword[0])&&(CurrentPassword[1]==adminpassword[1])&&(CurrentPassword[2]==adminpassword[2])&&(CurrentPassword[3]==adminpassword[3])&&(CurrentPassword[4]==adminpassword[4])&&(CurrentPassword[5]==adminpassword[5]))
	{
		if(isReset==0)
			jg = 2;	//正确输入管理员超级密码
		else
			jg = 4;	//正确输入管理员超级密码且在重设密码
		pass = 1;
	}
	else
		ErrorCont++;  //错误次数+1
			
	if(jg==1)
	{
		for(i=0;i<16;i++)
			LCD_display(i,0,Correct[i]);
		for(i=0;i<16;i++)
			LCD_display(i,1,LockOpen[i]);
		OneAlam();
		LED_display();
	}
	else if(jg==2)
	{
		for(i=0;i<16;i++)  
			LCD_display(i,0,superPassword[i]);
		for(i=0;i<16;i++)
			LCD_display(i,1,LockOpen[i]);
		OneAlam();
		LED_display();
	}else if(jg==3)
	{
		for(i=0;i<16;i++)
			LCD_display(i,0,Correct[i]);
		for(i=0;i<16;i++)
			LCD_display(i,1,NULL[i]);
		OneAlam();
	}
	else if(jg==4)
	{
		for(i=0;i<16;i++)  
			LCD_display(i,0,superPassword[i]);
		for(i=0;i<16;i++)
			LCD_display(i,1,NULL[i]);
		OneAlam();
	}
	else
	{
		for(i=0;i<16;i++)  
			LCD_display(i,0,ErrorTry[i]);
		for(i=0;i<16;i++)
			LCD_display(i,1,NULL[i]);
		ThreeAlam();
	}
}
/*******显示输入密码函数*******/
void input_Password()
{
	uchar i;
	do{
		if(ErrorCont==3)
		{	
			TR0 = 1;    //启动定时器T0 
			ErrorCont = 0;
			for(i=0;i<16;i++)
				LCD_display(i,0,wait[i]);
			LCD_display(12,0,trueTime);
			for(i=0;i<16;i++)
				LCD_display(i,1,again[i]);
			
			while(trueTime >= 48)
			{
				if(timeNum == 20) //num=20代表用了50ms*20  = 1s
				{
					timeNum = 0;
					trueTime--;  //锁定时间减1
					LCD_display(12,0,trueTime);
				}
			}
			TR0 = 0;    //关闭定时器T0
			trueTime = '5';
		}
		for(i=0;i<16;i++)
		LCD_display(i,0,start_line1[i]);
		for(i=0;i<16;i++)
		LCD_display(i,1,start_line2[i]);	
		pushBtn_password();
		judge();
	}while(pass==0);
		
}

/*******main函数*******/
void main()
{ 
	LCD_init();
	IT_init();
	Time_init();
	init_display();
	delay(2000);
	init_password();
	delay(2000);
	while(1)
	{
		input_Password();
		delay(1000);
	}
			
}
void reSetPassword() interrupt 0
{
	uchar i;
	isReset = 1;
	isInitPass = 0; 

	do{
		/*if(ErrorCont==3)
		{	
			TR0 = 1;    //启动定时器T0 
			ErrorCont = 0;
			for(i=0;i<16;i++)
				LCD_display(i,0,wait[i]);
			LCD_display(12,0,trueTime);
			for(i=0;i<16;i++)
				LCD_display(i,1,again[i]);
			
			while(trueTime >= 48)
			{
				if(timeNum == 20) //num=20代表用了50ms*20  = 1s
				{
					timeNum = 0;
					trueTime--;  //锁定时间减1
					LCD_display(12,0,trueTime);
				}
			}
			TR0 = 0;    //关闭定时器T0
			trueTime = '5';
		}*/
		if(ErrorCont==3)
		{
			
		}
		for(i=0;i<16;i++)
		LCD_display(i,0,oldPassword[i]);
		for(i=0;i<16;i++)
		LCD_display(i,1,start_line2[i]);	
		pushBtn_password();
		judge();
	}while(pass==0&&ErrorCont<3);

	delay(1000);
	if(pass == 1)
	{
		for(i=0;i<16;i++)	 
		LCD_display(i,0,Reset[i]);
	for(i=0;i<16;i++)
		LCD_display(i,1,Input[i]);
	isInitPass = 1;
	pushBtn_password();    //按键控制输入密码
	for(i=0;i<16;i++)  
		LCD_display(i,0,ResetOK[i]);
	for(i=0;i<16;i++)
		LCD_display(i,1,NULL[i]);
	TwoAlam();
	delay(1000);		
	}
	
	for(i=0;i<16;i++)
	LCD_display(i,0,start_line1[i]);
	for(i=0;i<16;i++)
	LCD_display(i,1,start_line2[i]);
	isInitPass = 0;
	isReset = 0;
}
void TimeCount() interrupt 1
{
	TH0 = (65536-45872)/256;//重装初值
	TL0 = (65536-45872)%256;
	timeNum++;			  //每发生一次中断后,num++
}




  • 23
    点赞
  • 174
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
以下是一个基于C51单片机的简单密码锁程序示例: ```c #include <reg52.h> #define PASSWORD "1234" // 设置密码 #define LED P0 // 控制LED灯亮灭的端口 void delay(unsigned int count) { unsigned int i; while (count--) { i = 100; while (i--); } } void main() { unsigned char passwordIndex = 0; unsigned char input; while (1) { input = P1; // 读取输入的按键值 if (input != 0xFF) { // 如果有按键按下 if (input == PASSWORD[passwordIndex]) { // 如果输入正确 passwordIndex++; // 继续输入下一个密码 if (passwordIndex == sizeof(PASSWORD) - 1) { // 如果密码输入完毕 LED = 0; // 点亮LED表示解锁成功 delay(5000); // 延时5秒 LED = 1; // 熄灭LED passwordIndex = 0; // 重新开始输入密码 } } else { // 如果输入错误 passwordIndex = 0; // 重新开始输入密码 } delay(100); // 延时一段时间,以免按键误触 } } } ``` 上述程序中,我们首先定义了一个密码常量`PASSWORD`,然后在主循环中不断读取输入的按键值。如果有按键按下,则将其与当前密码位置的字符进行比较。如果相等,则继续输入下一个密码;如果不相等,则重新开始输入密码。如果密码输入完毕,则点亮LED表示解锁成功,并延时5秒后熄灭LED,然后重新开始输入密码。 注意,上述程序中的延时函数`delay()`的实现方式比较简单,只是简单地循环等待一段时间。在实际应用中,应该使用更加准确的延时方法,例如使用定时器中断等方式实现。同时,为了提高密码安全性,应该考虑使用加密算法对密码进行加密存储。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值