1. 程式人生 > >基於51微控制器的簡易密碼鎖

基於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電路圖 下載:關注公眾號,首頁回覆“電子密碼鎖”獲取資料
在這裡插入圖片描述