天天看點

proteus仿真c51簡單密碼鎖

具體工程檔案和運作截圖在文檔裡面,歡迎大家下載下傳,有問題留言,謝謝!

https://pan.baidu.com/s/1h5evW4UYoknQLxmORouCGA

密碼鎖:

功能介紹:

1.可設定1-4位密碼

2.密碼輸入顯示在數位管上

3.密碼驗證結果顯示在數位管上

4.顯示密碼錯誤次數

5.輸入可回退

6.可更改密碼

7.密碼正确小燈亮起

8.錯誤次數達到3次數位管顯示倒計時60s并報警

密碼鎖工作使用流程:

1.一個密碼鎖必須有密碼,是以最開始我們點選SETKEY開始設定密碼,點選輸入準備READY開始輸入密碼,DELETE可回退,輸入完成後點選SURE儲存密碼然後點選CLOSE

2.每次要輸入密碼時都需點選READY準備輸入然後進行輸入密碼開鎖

3.當密碼正确小燈會亮,數位管顯示ON即密碼鎖打開,并且可以點選MODIFY進行修改密碼

4.當密碼錯誤時數位管顯示err,并且單獨的數位管顯示錯誤次數,當錯誤達到三次則會進行倒計時報警

仿真原理圖:

矩陣鍵盤(輸入):接在P1口且用一個4與門,上拉電阻來通過中斷方式來實作。

4位數位管(顯示螢幕):位選接P3的0,1,6,7口,段選接在P2的0-6口,不需要點。

1位數位管(顯示錯誤次數):通過上拉電阻接在P0的0-6口。

小燈(标志密碼輸入正确):接在P3的3口。

蜂鳴器(警報):接在P3的5口。

proteus仿真c51簡單密碼鎖

流程圖:

密碼鎖因為初始無密碼,是以程式首先運作一個設定密碼程式讓使用者設定一個1-4位的密碼,輸入密碼中可回删。然後程式會進入一個循環輸入密碼的環節。密碼設定完成後點選關閉鍵後,螢幕關閉。點選準備輸入即可開始輸入密碼,輸入密碼完了點選确認鍵,螢幕會顯示打開與否即on與err,顯示錯誤次數的數位管也會實時顯示錯誤次數。當輸入次數達到三次後,将在1分鐘内無法輸入無法關閉且在螢幕顯示倒計時同時蜂鳴器報警,其他時刻都可點選關閉鍵。當密碼輸入正确後,小燈亮,且可以點選修改密碼鍵,讓使用者輸入新的密碼,然後确定。

proteus仿真c51簡單密碼鎖

具體代碼分析注釋以及運作結果截圖分析在文檔裡面,歡迎大家下載下傳! ! !

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit LED=P3^3;   //小燈
sbit ALTER=P3^5;  //警報器
void delay(uint);  //延遲函數
void Show_Pwd();  //數位管顯示密碼
void Show_on();   //數位管顯示on
void Show_err();  //數位管顯示err
void Sure_on_err();     //判斷密碼是否正确
void Show_Sixty();  //數位管顯示倒計時60s
void Show_Time(uint); //數位管顯示給定的數字(倒計時)
void Init();   //初始化
void Total_Show();  //數位管總顯示
void Close_Init();  //close關閉後的初始化
void Pwd_Modity();  //修改密碼
void SetPwd();   //設定密碼
char Key=-1;       //儲存鍵号
uchar PwdRight=0;        //正确密碼的位數(因為我設定的是1-4為密碼都可以,是以判斷比較密碼時需要密碼位數)
char PwdDigit=-1;     //記錄目前輸入密碼的位數(友善存數組,比較是以初始值為-1)
uchar PwdErrTime=0;      //密碼錯誤次數(觸發警報的判斷依據)
uchar TimeCount=0;       //計時器中斷函數計數器   (定時器計了50000us即50ms,則加1,達到20次即計了1s)
uchar ShowSign=1;        //Total_Show()函數根據該标志來判斷顯示什麼資訊
uchar Keycount=0;        //循環功能按鍵的次數(當該功能按鍵次數改變即有功能按鍵按下,則進入switch-case中選擇執行,防止不按功能按鍵時,主程式依然繼續執行上一次的功能)
char Password[4]={-1,-1,-1,-1};      //儲存密碼
uchar Pwd_Now[4]={10,10,10,10};       //儲存目前輸入的密碼
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x37,0x7b,0x31}; //數模0-9與'-'(10),'n'(11),'e'(12),'r'(13)
uchar code key_buf[]={0xd7,0xeb,0xdb,0xbb,0xed,0xdd,0xbd,0xee,
                      0xde,0xbe,0xb7,0x7e,0x7d,0x7b,0x77,0xe7};    
     //鍵模0-9,sure(10),delete(11),setpwd(12),modify(13),close(14),ready(15)
void delay(uint time)
{
 uchar i=0;
 for(;time>0;time--)
  for(i=0;i<113;i++);
}
void Getkey(void) interrupt 0
{
 uchar key_scan[]={0xef,0xdf,0xbf,0x7f}; //鍵掃描碼(1-4列)
 uchar i=0,j=0;
 for(i=0;i<4;i++)
 {
  P1=key_scan[i];      //P1送出鍵掃描碼
  if((P1&0x0f)!=0x0f)       //判斷有無按鍵按下
  {
   delay(10);
   if((P1&0x0f)!=0x0f)
   {
    for(j=0;j<16;j++)
    { 
     if(key_buf[j]==P1)  //找到按鍵
     {
          while(P1!=key_scan[i])  //按鍵松開
       {
        Total_Show();  //按鍵時數位管顯示
       }  
       Key=j;        //擷取鍵值
       if(j<10)
       {
        PwdDigit++;   //隻有按下數字鍵該密碼位數才會自加
      if(PwdDigit<4)
         Pwd_Now[PwdDigit]=j;  //存儲有效密碼
       }
       else if(j!=12&&j!=15)
        Keycount++; //循環功能(除了setpwd和ready)按鍵的次數
       P1=0x0f;
       return;
     }
    }
   }
  }
 }
}
void Show_Pwd()
{
  switch(PwdDigit)   //通過密碼位數來實時顯示密碼的輸入,目前存儲的密碼作為下标顯示密碼
  {
     case 3: P3=0x4f;P2=table[Pwd_Now[3]];delay(10);    //隻打開第四個位選,P3.2=1(無影響),P3.3=1關閉LED,P3.5=0關閉警報
      case 2: P3=0x8f;P2=table[Pwd_Now[2]];delay(10);    //隻打開第三個位選,P3.2=1(無影響),P3.3=1關閉LED,P3.5=0關閉警報
      case 1: P3=0xcd;P2=table[Pwd_Now[1]];delay(10);    //隻打開第二個位選,P3.2=1(無影響),P3.3=1關閉LED,P3.5=0關閉警報
      case 0: P3=0xce;P2=table[Pwd_Now[0]];delay(10);break;  //隻打開第一個位選,P3.2=1(無影響),P3.3=1關閉LED,P3.5=0關閉警報
      default:P3=0x0c;P2=table[10];PwdDigit=-1;delay(10);break;//打開所有位選,P3.2=1(無影響),P3.3=1關閉LED,P3.5=0關閉警報
                  //顯示'-',當PwdDigit=-1與delay(10)位置不同有問題
  }
}
void Total_Show()
{
 switch(ShowSign)   //根據數位管展示的标志位來判斷展示不同的資訊
 {
  case 1:Show_Pwd();break;  //顯示輸入的密碼
  case 2:Show_on();break;      //顯示密碼輸入正确的on并點亮小燈
  case 3:Show_err();break;     //顯示密碼輸入錯誤的err
  case 4:Show_Sixty();break;   //顯示60s倒計時并打開警報
 }
}
void Show_on()
{
 P3=0xc6;    //隻打開第一個位選,P3.2=1(無影響),P3.3=0打開LED,P3.5=0關閉警報
 P2=table[0];   //顯示0
 delay(15);
 P3=0xc5;    //隻打開第二個位選,P3.2=1(無影響),P3.3=0打開LED,P3.5=0關閉警報
 P2=table[11];  //顯示n
 delay(15);
}
void Show_err()
{
 P3=0xce;    //隻打開第一個位選,P3.2=1(無影響),P3.3=1關閉LED,P3.5=0關閉警報
 P2=table[12];  //顯示'e'
 delay(10);
 P3=0xcd;    //隻打開第二個位選,P3.2=1(無影響),P3.3=1關閉LED,P3.5=0關閉警報
 P2=table[13];  //顯示'r'
 delay(10);
 P3=0x8e;    //隻打開第三個位選,P3.2=1(無影響),P3.3=1關閉LED,P3.5=0關閉警報
 P2=table[13];  //顯示'r'
 delay(10);
}   
void Sure_on_err()
{ 
 uchar i=0;
 ShowSign=3;                              //預設輸入錯誤,數位管顯示标志為3顯示err
 if(PwdRight==PwdDigit)      //當正确密碼的位數與目前輸入的密碼的位數相同
 {
  for(i=0;i<=PwdDigit;i++)    //每一位密碼進行比較
  {
   if(Password[i]!=Pwd_Now[i])   //當有一位不同就退出循環比較
    break;
  }
  if(i==PwdDigit+1)
  {                      //如果密碼正确,比較完不滿足判斷條件退出的循環則i=PwdDigit+1
   ShowSign=2;       //更改數位管顯示的标志為2顯示on點亮小燈
   PwdErrTime=0;      //将錯誤次數清0
  }                  
  else         //如果是break退出的循環則錯誤次數加1,不需要更改數位管顯示标志
   PwdErrTime++; 
 }
 else          //如果正确密碼的位數與目前輸入的密碼的位數不相同,則錯誤次數加1
  PwdErrTime++;  
 if(PwdErrTime==3)       //密碼錯誤次數達到三次
 {
  P0=table[PwdErrTime];     //單個數位管先顯示密碼錯誤次數3
  ShowSign=4;        //更改數位管顯示的标志為4顯示倒計時并打開警報
 }  
}
void SetPwd()
{
 uchar i=0;
 uchar count=0;                    //存儲按功能鍵的次數
 uchar sign=0;      //是否确認密碼标志(0:未确認,1:已确認)
 P1=0x7f;                         //将第四列設為低電平
 while(P1!=key_buf[12]);          //setpwd第一次設定密碼 
 P1=0xef;                         //将第一列設為低電平
 while(P1!=key_buf[15]);          //查詢是否按下ready鍵
 EX0=1;                           //打開按鍵中斷開關
 while(1)
 {
  Total_Show(); 
  if(count!=Keycount&&Key==11) //當有delete功能按鍵按下時将密碼位數減1(count!=Keycount為了防止當按下delete後,由于在循環體中位數會一直自減)
  { 
   count=Keycount;    //功能鍵次數重新指派給count
   PwdDigit--;     //目前密碼位數--
  } 
  if(PwdDigit>=0&&Key==10)     //輸完1-4位密碼并且按下sure鍵後顯示并儲存密碼
   {
   ShowSign=2;              //數位管顯示on并點亮小燈
   Total_Show();
   sign=1;               //表示已确認設定密碼  
   for(i=0;i<=PwdDigit;i++) //儲存密碼
    Password[i]=Pwd_Now[i];
   PwdRight=PwdDigit;   //将目前密碼位數指派給正确密碼位數标志
  }
  if(Key==14&&sign==1)         //隻能确認設定完密碼才能點選close退出
  {
   return;
  }
 }
}
void Show_Time(uint number)
{ 
 P3=0xee;    //隻打開第一個位選,P3.2=1(無影響),P3.3=1關閉LED,P3.5=1打開警報
 P2=table[10];   //顯示 -
 delay(5);
 P3=0xed;    //隻打開第二個位選,P3.2=1(無影響),P3.3=1關閉LED,P3.5=1打開警報
 P2=table[number/10]; //顯示十位
 delay(5);
 P3=0xaf;    //隻打開第三個位選,P3.2=1(無影響),P3.3=1關閉LED,P3.5=1打開警報
 P2=table[number%10]; //顯示個位
 delay(5);
 P3=0x6f;    //隻打開第四個位選,P3.2=1(無影響),P3.3=1關閉LED,P3.5=1打開警報
 P2=table[10];   //顯示 -
 delay(5);
}
void Show_Sixty()
{
 uchar toal=60;    //倒計時總時間
 EX0=0;      //關閉鍵盤中斷(防止按鍵進行中斷數位管顯示)
 TR0=1;      //打開定時器開關
 do
 {
  if(TimeCount==20) //中斷一次50ms,TimeCount++,當達到20次即1s顯示值減一
  {
   TimeCount=0;  //重新指派為0
   toal--;    //顯示值--
  }
  Show_Time(toal);  //掉用顯示函數
  }while(toal>0);   //當顯示到0時退出      
  TR0=0;      //關閉定時器開關
  EX0=1;      //打開鍵盤中斷開關
  PwdErrTime=0;    //錯誤次數重新指派為0
  PwdDigit=-1;    //密碼位數指派為-1重新輸入
  ShowSign=1;    //數位管顯示标志設為1,顯示密碼
}
int0_srv() interrupt 1
{
 TimeCount++;        
}      
void Init()
{
 IT0=0;      //設為跳變沿有問題
 TMOD=0x01;  //定時器0工作方式為1
 TH0=0x3c;
 TL0=0xb0;   //一次定時50ms
 ET0=1;     //打開定時器0的中斷開關
 EA=1;     //打開總開關
 P0=table[0];//單個數位管顯示0
 LED=1;  //關閉數位管
 ALTER=0; //關閉警報器
}
void Close_Init()
{ 
  uchar i=0;    
 P3=0xcf;      //關閉所有位選,P3.2=1(無影響),P3.3=1關閉LED,P3.5=0關閉警報
 EX0=0;       //關閉鍵盤中斷
 PwdDigit=-1;     //密碼位數指派為-1
 P1=0xef;      //将第一列設為低電平
 while(P1!=key_buf[15]);//查詢是否按下ready鍵
 ShowSign=1;      //數位管顯示密碼
 EX0=1;       //打開鍵盤中斷
 for(i=0;i<4;i++)    //将目前密碼初始化
  Pwd_Now[i]=10; 
}
void Pwd_Modity()
{ 
 uchar count=0;       //存儲按功能鍵的次數
 PwdDigit=-1;       //密碼位數指派為-1
 ShowSign=1;        //數位管顯示密碼
 while(1)
 { 
  
  Total_Show();
  if(count!=Keycount&&Key==11)  //當有delete功能按鍵按下時将密碼位數減1(count!=Keycount為了防止當按下delete後,由于在循環體中位數會一直自減)
  { 
   count=Keycount;     //功能鍵次數重新指派給count
   PwdDigit--;      //目前密碼位數--
  } 
  if(PwdDigit>=0&&Key==10)   //輸完1-4位密碼并且按下sure鍵後顯示并儲存密碼
  {
   uchar i=0;
   for(i=0;i<=PwdDigit;i++)  //儲存密碼
    Password[i]=Pwd_Now[i];
   for(i=PwdDigit+1;i<4;i++) //将不是密碼位初始化位-1
    Password[i]=-1;
   PwdRight=PwdDigit;     //将目前密碼位數指派給正确密碼位數标志
   ShowSign=2;       //數位管顯示on并點亮小燈
   Key=12;                    //防止傳回主函數後進入switch-case
   return;
  }
 }
}       
void main(void)
{
 uchar count=0;//功能按鍵的次數
 Init();   //初始化
 SetPwd();  //設定密碼
 while(1)
 {  
    P0=table[PwdErrTime]; //close關閉後單個數位管關閉
    if(count!=Keycount)        //當有功能按鍵按下時進入switch-case(為了防止當按下delete後,由于在循環體中位數會一直自減)
    {
      count=Keycount;       //功能按鍵次數重新指派給count
   switch(Key)
   {
    case 10:Sure_on_err();break;      //調用确認密碼函數
    case 11:if(ShowSign==1){PwdDigit--;Pwd_Now[PwdDigit+1]=10;}break; //密碼位數減1,并把上一位存儲的密碼初始化為10
    case 13:if(ShowSign==2)Pwd_Modity();break;   //當密碼正确了才能修改密碼
    case 14:Close_Init();break;       //close關閉後的初始化
   }
    }
       Total_Show();
 } 
}
           

繼續閱讀