標(biāo)題:
基于51單片機的密碼鎖Proteus仿真程序設(shè)計 LCD1602顯示 超過三次輸入錯誤自動鎖定
[打印本頁]
作者:
小小張。。
時間:
2020-11-13 23:23
標(biāo)題:
基于51單片機的密碼鎖Proteus仿真程序設(shè)計 LCD1602顯示 超過三次輸入錯誤自動鎖定
第一次發(fā)帖,難免有錯請指出
由STC89C52單片機系統(tǒng)(主要是STC89C52單片機最小系統(tǒng))、4×4矩陣鍵盤、LCD1602顯示和報警系統(tǒng)等組成一個密碼鎖,具有設(shè)置、修改六位用戶密碼、超次報警、超次鎖定、密碼錯誤報警等功能。
密碼正確顯示OPEN! 密碼錯誤顯示error!超過三次輸入錯誤自動鎖定。
輸入密碼時在LCD屏幕上顯示*號,若密碼輸入錯誤次數(shù)超過3次,蜂
鳴器報警并且鎖定鍵盤。
對輸入的6位密碼進行隱藏;通過發(fā)光二極管和蜂鳴器,對解密正確或者錯誤進行聲光報警;
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
捕獲.PNG
(88.9 KB, 下載次數(shù): 49)
下載附件
2020-11-13 23:19 上傳
單片機源程序如下:
//<font style="background-color:rgb(255, 255, 255)">
#include <reg51.h>
#include<intrins.h>
#define LCM_Data P0
#define uchar unsigned char
#define uint unsigned int
#define w 6 //定義密碼位數(shù)
sbit lcd1602_rs=P2^7;
sbit lcd1602_rw=P2^6;
sbit lcd1602_en=P2^5;
sbit Scl=P3^4; //24C02串行時鐘
sbit Sda=P3^5; //24C02串行數(shù)據(jù)
sbit ALAM = P2^1; //報警
sbit KEY = P3^6; //開鎖
sbit open_led=P2^2; //開鎖指示燈
bit operation=0; //操作標(biāo)志位
bit pass=0; //密碼正確標(biāo)志
bit ReInputEn=0; //重置輸入充許標(biāo)志
bit s3_keydown=0; //3秒按鍵標(biāo)志位
bit key_disable=0; //鎖定鍵盤標(biāo)志
unsigned char countt0,second; //t0中斷計數(shù)器,秒計數(shù)器
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]; //輸入密碼暫存區(qū)
unsigned char CurrentPassword[6]={1,3,1,4,2,0}; //當(dāng)前密碼值
unsigned char TempPassword[6];
unsigned char N=0; //密碼輸入位數(shù)記數(shù)
unsigned char ErrorCont; //錯誤次數(shù)計數(shù)
unsigned char CorrectCont; //正確輸入計數(shù)
unsigned char ReInputCont; //重新輸入計數(shù)
unsigned char code initpassword[6]={0,0,0,0,0,0};
//=====================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_();
_nop_();
_nop_();
_nop_();
}
/*起始條件*/
void Start(void)
{
Sda=1;
Scl=1;
Nop();
Sda=0;
Nop();
}
/*停止條件*/
void Stop(void)
{
Sda=0;
Scl=1;
Nop();
Sda=1;
Nop();
}
/*應(yīng)答位*/
void Ack(void)
{
Sda=0;
Nop();
Scl=1;
Nop();
Scl=0;
}
/*反向應(yīng)答位*/
void NoAck(void)
{
Sda=1;
Nop();
Scl=1;
Nop();
Scl=0;
}
/*發(fā)送數(shù)據(jù)子程序,Data為要求發(fā)送的數(shù)據(jù)*/
void Send(uchar Data)
{
uchar BitCounter=8;
uchar temp;
do
{
temp=Data;
Scl=0;
Nop();
if((temp&0x80)==0x80)
Sda=1;
else
Sda=0;
Scl=1;
temp=Data<<1;
Data=temp;
BitCounter--;
}
while(BitCounter);
Scl=0;
}
/*讀一字節(jié)的數(shù)據(jù),并返回該字節(jié)值*/
uchar Read(void)
{
uchar temp=0;
uchar temp1=0;
uchar BitCounter=8;
Sda=1;
do{
Scl=0;
Nop();
Scl=1;
Nop();
if(Sda)
temp=temp|0x01;
else
temp=temp&0xfe;
if(BitCounter-1)
{
temp1=temp<<1;
temp=temp1;
}
BitCounter--;
}
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)
//----------------延時函數(shù),后面經(jīng)常調(diào)用----------------------
void delay(uint xms)//延時函數(shù),有參函數(shù)
{
uint x,y;
for(x=xms;x>0;x--)
for(y=110;y>0;y--);
}
//--------------------------寫指令---------------------------
write_1602com(uchar com)//****液晶寫入指令函數(shù)****
{
lcd1602_rs=0;//數(shù)據(jù)/指令選擇置為指令
lcd1602_rw=0; //讀寫選擇置為寫
P0=com;//送入數(shù)據(jù)
delay(1);
lcd1602_en=1;//拉高使能端,為制造有效的下降沿做準(zhǔn)備
delay(1);
lcd1602_en=0;//en由高變低,產(chǎn)生下降沿,液晶執(zhí)行命令
}
//-------------------------寫數(shù)據(jù)-----------------------------
write_1602dat(uchar dat)//***液晶寫入數(shù)據(jù)函數(shù)****
{
lcd1602_rs=1;//數(shù)據(jù)/指令選擇置為數(shù)據(jù)
lcd1602_rw=0; //讀寫選擇置為寫
P0=dat;//送入數(shù)據(jù)
delay(1);
lcd1602_en=1; //en置高電平,為制造下降沿做準(zhǔn)備
delay(1);
lcd1602_en=0; //en由高變低,產(chǎn)生下降沿,液晶執(zhí)行命令
}
//-------------------------初始化-------------------------
void lcd_init(void)
{
write_1602com(0x38);//設(shè)置液晶工作模式,意思:16*2行顯示,5*7點陣,8位數(shù)據(jù)
write_1602com(0x0c);//開顯示不顯示光標(biāo)
write_1602com(0x06);//整屏不移動,光標(biāo)自動右移
write_1602com(0x01);//清顯示
}
//========================================================================================
//=========================================================================================
//==============將按鍵值編碼為數(shù)值=========================
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;
}
//=====================顯示輸入的N個數(shù)字,用H代替以便隱藏============================
void DisplayOne(void)
{
// DisplayOneChar(9+N,1,'*');
write_1602com(yi+5+N);
write_1602dat('*');
}
//=======================顯示提示輸入=========================
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]);
}
}
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 DisplayInput(void)
{
unsigned char i;
if(CorrectCont==1)
{
//DisplayListChar(0,0,Input);
write_1602com(er);
for(i=0;i<16;i++)
{
write_1602dat(Input[i]);
}
}
}
//========================重置密碼==================================================
//==================================================================================
void ResetPassword(void)
{
unsigned char i;
unsigned char j;
if(pass==0)
{
pass=0;
DisplayChar();
ThreeAlam();
}
else
{
if(ReInputEn==1)
{
if(N==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]);
}
ThreeAlam(); //錯誤提示
pass=0;
ReInputEn=0; //關(guān)閉重置功能,
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]; //將第一次輸入的數(shù)據(jù)暫存起來
}
}
N=0; //輸入數(shù)據(jù)位數(shù)計數(shù)器清零
}
}
}
}
//=======================輸入密碼錯誤超過三過,報警并鎖死鍵盤======================
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; //關(guān)閉鎖
ALAM=1; //報警關(guān)
operation=0; //操作標(biāo)志位清零
pass=0; //密碼正確標(biāo)志清零
ReInputEn=0; //重置輸入充許標(biāo)志清零
ErrorCont=0; //密碼錯誤輸入次數(shù)清零
CorrectCont=0; //密碼正確輸入次數(shù)清零
ReInputCont=0; //重置密碼輸入次數(shù)清零
open_led=1;
s3_keydown=0;
key_disable=0;
N=0; //輸入位數(shù)計數(shù)器清零
}
//==========================確認(rèn)鍵,并通過相應(yīng)標(biāo)志位執(zhí)行相應(yīng)功能===============================
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])
{
i++;
}
else
{
ErrorCont++;
if(ErrorCont==3) //錯誤輸入計數(shù)達三次時,報警并鎖定鍵盤
{
write_1602com(er);
for(i=0;i<16;i++)
{
write_1602dat(Error[i]);
}
do
Alam_KeyUnable();
while(1);
}
else
{
TR0=1; //開啟定時
key_disable=1; //鎖定鍵盤
pass=0;
break;
}
}
}
if(i==6)
{
CorrectCont++;
if(CorrectCont==1) //正確輸入計數(shù),當(dāng)只有一次正確輸入時,開鎖,
{
//DisplayListChar(0,1,LockOpen);
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(LockOpen[j]);
}
TwoAlam(); //操作成功提示音
KEY=0; //開鎖
pass=1; //置正確標(biāo)志位
TR0=1; //開啟定時
open_led=0; //開鎖指示燈亮
for(j=0;j<6;j++) //將輸入清除
{
InputData[i]=0;
}
}
else //當(dāng)兩次正確輸入時,開啟重置密碼功能
{
//DisplayListChar(0,1,SetNew);
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(SetNew[j]);
}
TwoAlam(); //操作成功提示
ReInputEn=1; //允許重置密碼輸入
CorrectCont=0; //正確計數(shù)器清零
}
}
else //=========================當(dāng)?shù)谝淮问褂没蛲浢艽a時可以用131420對其密碼初始化============
{
if((InputData[0]==1)&&(InputData[1]==3)&&(InputData[2]==1)&&(InputData[3]==4)&&(InputData[4]==2)&&(InputData[5]==0))
{
WrToROM(initpassword,0,6); //強制將初始密碼寫入24C02存儲
//DisplayListChar(0,1,initword); //顯示初始化密碼
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(initword[j]);
}
TwoAlam();
Delay400Ms();
TwoAlam();
N=0;
}
else
{
//DisplayListChar(0,1,Error);
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(Error[j]);
}
ThreeAlam(); //錯誤提示音
pass=0;
}
}
}
else //當(dāng)已經(jīng)開啟重置密碼功能時,而按下開鎖鍵,
{
//DisplayListChar(0,1,Er_try);
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(Er_try[j]);
}
ThreeAlam();
}
}
else
{
//DisplayListChar(0,1,Error);
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(Error[j]);
}
ThreeAlam(); //錯誤提示音
pass=0;
}
N=0; //將輸入數(shù)據(jù)計數(shù)器清零,為下一次輸入作準(zhǔn)備
operation=1;
}
//==============================主函數(shù)===============================
void main(void)
{
unsigned char KEY,num;
unsigned char i,j;
P1=0xF0;
TMOD=0x11;
TL0=0xB0;
TH0=0x3C;
EA=1;
ET0=1;
TR0=0;
Delay400Ms(); //啟動等待,等LCM講入工作狀態(tài)
lcd_init(); //LCD初始化
write_1602com(yi);//日歷顯示固定符號從第一行第0個位置之后開始顯示
for(i=0;i<16;i++)
{
write_1602dat(name[i]);//向液晶屏寫日歷顯示的固定符號部分
}
write_1602com(er);//時間顯示固定符號寫入位置,從第2個位置后開始顯示
for(i=0;i<16;i++)
{
write_1602dat(start_line[i]);//寫顯示時間固定符號,兩個冒號
}
write_1602com(er+9); //設(shè)置光標(biāo)位置
write_1602com(0x0f); //設(shè)置光標(biāo)為閃爍
Delay5Ms(); //延時片刻(可不要)
N=0; //初始化數(shù)據(jù)輸入位數(shù)
while(1)
{
if(key_disable==1)
Alam_KeyUnable();
else
ALAM=1;
num++;
if(num>20)
{
num=0;
}
KEY=keynum();
if(KEY!=0)
{
if(key_disable==1)
{
second=0;
}
else
……………………
…………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼
所有資料51hei提供下載:
密碼鎖.zip
(29.3 KB, 下載次數(shù): 141)
2020-11-13 23:21 上傳
點擊文件名下載附件
程序
下載積分: 黑幣 -5
密碼鎖。DSN.zip
(21.03 KB, 下載次數(shù): 113)
2020-11-13 23:21 上傳
點擊文件名下載附件
仿真
下載積分: 黑幣 -5
作者:
2283076406
時間:
2020-11-27 18:44
仿真是proteus那個版本啊?
作者:
2283076406
時間:
2020-11-27 19:04
老哥 重置密碼的兩次具體怎么操作欸
作者:
摸摸
時間:
2020-12-15 15:04
樓主您好,有物料清單嗎
作者:
alex_how
時間:
2020-12-27 10:52
仿真成功,謝謝樓主
作者:
12345678900-
時間:
2025-1-2 22:03
初始密碼是啥呀
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1