基于51单片机的简易密码锁

一个基于51单片机的简易密码锁,废话不多说,直接贴图贴代码

1.电路图
在这里插入图片描述
电路组成:5V电源+51单片机最小系统+LCD1602显示屏+4*4矩阵键盘

2.程序分析
(1)LCD1602驱动程序

#include "1602.h"
#include "delay.h"

#define CHECK_BUSY

sbit RS = P2^4;   //定义端口 
sbit RW = P2^5;
sbit EN = P2^6;

#define RS_CLR RS=0 
#define RS_SET RS=1

#define RW_CLR RW=0 
#define RW_SET RW=1 

#define EN_CLR EN=0
#define EN_SET EN=1

#define DataPort P0

/*------------------------------------------------
              判忙函数
------------------------------------------------*/
 bit LCD_Check_Busy(void) 
 { 
	#ifdef CHECK_BUSY
	DataPort= 0xFF; 
 	RS_CLR; 
 	RW_SET; 
 	EN_CLR; 
 	_nop_(); 
 	EN_SET;
 	return (bit)(DataPort & 0x80);
	#else
 	return 0;
	#endif
 }
/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
 void LCD_Write_Com(unsigned char com) 
 {  
	 while(LCD_Check_Busy()); //忙则等待
 	 RS_CLR; 
	 RW_CLR; 
	 EN_SET; 
	 DataPort= com; 
 	_nop_(); 
 	EN_CLR;
 }
/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
 void LCD_Write_Data(unsigned char Data) 
 { 
 	while(LCD_Check_Busy()); //忙则等待
 	RS_SET; 
	RW_CLR; 
 	EN_SET; 
 	DataPort= Data; 
 	_nop_();
 	EN_CLR;
 }

/*------------------------------------------------
                清屏函数
------------------------------------------------*/
 void LCD_Clear(void) 
 { 
 	LCD_Write_Com(0x01); 
	 DelayMs(5);
 }
/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
 {         
 	while (*s) 
 	{     
		 LCD_Write_Char(x,y,*s);     
 		s ++;  x++;   
 	}
 }
/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
 {     
	if (y == 0) 
 	{     
 		LCD_Write_Com(0x80 + x);     
 	}    
	 else 
 	{     
 		LCD_Write_Com(0xC0 + x);     
 	}        
 	LCD_Write_Data( Data);  
 }
/*------------------------------------------------
              初始化函数
------------------------------------------------*/
 void LCD_Init(void) 
 {
   LCD_Write_Com(0x38);    /*显示模式设置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38);  
   LCD_Write_Com(0x08);    /*显示关闭*/ 
   LCD_Write_Com(0x01);    /*显示清屏*/ 
   LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x0C);    /*显示开及光标设置*/
  }   

(2)4*4矩阵键盘驱动程序

#define KeyPort P1

/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsigned char KeyScan(void)  //键盘扫描函数,使用行列反转扫描法
{
 	unsigned char cord_h,cord_l;//行列值中间变量
 	KeyPort=0x0f;            //行线输出全为0
 	cord_h=KeyPort&0x0f;     //读入列线值
 	if(cord_h!=0x0f)    //先检测有无按键按下
 	{
  		DelayMs(10);        //去抖
  		if((KeyPort&0x0f)!=0x0f)
  		{
    			cord_h=KeyPort&0x0f;  //读入列线值
    			KeyPort=cord_h|0xf0;  //输出当前列线值
    			cord_l=KeyPort&0xf0;  //读入行线值
    			while((KeyPort&0xf0)!=0xf0);//等待松开并输出
    			return(cord_h+cord_l);//键盘最后组合码值
   		}
  	}
  	return(0xff);     //返回该值
}
/*------------------------------------------------
按键值处理函数,返回扫键值
------------------------------------------------*/
unsigned char KeyPro(void)
{
 switch(KeyScan())
 {
  case 0x7e:return 0;break;//0 按下相应的键显示相对应的码值
  case 0x7d:return 1;break;//1
  case 0x7b:return 2;break;//2
  case 0x77:return 3;break;//3
  case 0xbe:return 4;break;//4
  case 0xbd:return 5;break;//5
  case 0xbb:return 6;break;//6
  case 0xb7:return 7;break;//7
  case 0xde:return 8;break;//8
  case 0xdd:return 9;break;//9
  case 0xdb:return 10;break;//a
  case 0xd7:return 11;break;//b
  case 0xee:return 12;break;//c
  case 0xed:return 13;break;//d
  case 0xeb:return 14;break;//e
  case 0xe7:return 15;break;//f
  default:return 0xff;break;
 }
}

(3)主程序

main()
{
 unsigned char num,i,j;                  
 unsigned char passwordtemp[16];        //最大输入16个
 unsigned char inputtimes;              //密码输入错误次数
 unsigned char passwordlength,PLEN;     //输入密码长度,实际密码长度
 bit Flag;
 PLEN=sizeof(password)/sizeof(password[0]);//用于计算出实际密码长度
 
 LCD_Init();         //初始化液晶屏
 DelayMs(10);        //延时用于稳定,可以去掉
 LCD_Clear();        //清屏
 LCD_Write_String(0,0,"  Welcome! ");    //写入第一行信息,主循环中不再更改此信息,所以在while之前写入
 LCD_Write_String(0,1,"Input password!");    //写入第二行信息,提示输入密码
 while (1)         //主循环
 {
 	num=KeyPro();  //扫描键盘
 	if(num!=0xff)  //如果扫描是按键有效值则进行处理
   	{ 
    		if(i==0)    //输入是第一个字符的时候需要把改行清空,方便观看密码
	  	LCD_Write_String(0,1,"                ");//清除该行
		if(i<16)
	  	{
       		passwordtemp[i]=num;
       		LCD_Write_Char(i,1,'*');//输入的密码用"*"代替
	   	}
		i++;   //输入数值累加
		if((15==num)|| (i==16))//输入按键值15或者密码输入到最大值16,表示输入结束,需要进行比对
	 	{
      		passwordlength=i-1;  //计算输入密码长度
	  		i=0;  //计数器复位
	  		if(passwordlength==PLEN)//长度相等则比较,否则直接输出错误
	    	{
	     		Flag=1;//先把比较位置1
	     		for(j=0;j<PLEN;j++)//循环比较8个数值,如果有一个不等 则最终Flag值为0
	        		Flag=Flag&&(passwordtemp[j]==password[j]);//比较输入值和已有密码
         	}
      		if(Flag)//如果比较全部相同,标志位置1
	   		{
	    		LCD_Write_String(0,1,"                ");//清除该行
        		LCD_Write_String(0,1,"Right Open!>>>>");//密码正确显示的信息
        		inputtimes=0;//输入正确则次数清零,重新计数
        		Flag=0;      //清除正确标志
			}
	  		else 
	    	{
				LCD_Write_String(0,1,"                ");//清除该行
				LCD_Write_String(0,1,"Wrong! Retry!");//密码错误,提示重新输入
				inputtimes++;//连续输入错误,则次数累加
				if(inputtimes==3)
		 		 {
		   			LCD_Write_String(0,1,"                ");//清除该行
		   			LCD_Write_String(0,1,"Wrong 3 times!");//密码错误,提示重新输入
		   			while(1);//停止该位置,重启电源后才能输入,实际实用中则需要等到一定时间后才能再次输入。
		  		 }
			}
	  	}
    }	
  }
}

源码+AD电路图 下载:关注公众号,首页回复“电子密码锁”获取资料
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lin5103151/article/details/85012631