(1)設(shè)置6位密碼,密碼通過(guò)鍵盤輸入,若密碼正確,則將鎖打開(kāi),初始化密碼為(123456)。 (2)密碼可以由用戶自己修改設(shè)定(支持6位密碼),鎖打開(kāi)后才能修改密碼。修改密碼之前必須再次輸入密碼,在輸入新密碼時(shí)候需要二次確認(rèn),以防止誤操作。 (3)報(bào)警、鎖定鍵盤功能。密碼輸入錯(cuò)誤數(shù)碼顯示器會(huì)出現(xiàn)錯(cuò)誤提示,若密碼輸入錯(cuò)誤次數(shù)超過(guò)4次,蜂鳴器報(bào)警并且鎖定鍵盤。 (4)密碼修改后有存儲(chǔ)功能。 (5)一鍵恢復(fù)初始密碼功能。
)]@D%F)G[2W0(UVC4X9U~XO.png (23.34 KB, 下載次數(shù): 120)
下載附件
仿真圖
2017-4-10 21:43 上傳
源程序:
- #include<reg51.h>
- #include<intrins.h>
- typedef unsigned char uchar;
- typedef unsigned int uint;
- sbit beep=P2^4;//蜂鳴器接口
- sbit D1=P2^2;//開(kāi)鎖信號(hào)
- sbit k1=P3^2;//恢復(fù)初始密碼按鍵
- sbit RS=P2^7;//數(shù)據(jù)命令選擇
- sbit RW=P2^6;//讀寫控制
- sbit E=P2^5;//液晶使能
- sbit SDA=P2^1; //數(shù)據(jù)線接口
- sbit SCL=P2^0;//時(shí)鐘線接口
- uchar idata table1[6]={1,2,3,4,5,6}; //初始密碼
- uchar dd;
- uchar aa;//存放密碼錯(cuò)誤的次數(shù),夠三次報(bào)警
- uchar bb;
- uchar cc;
- //延時(shí)子函數(shù)
- void delay1(uint z)
- {
- uint x,y;
- for(x=0;x<z;x++)
- for(y=0;y<110;y++);
- }
- void delay2()
- {
- ;;
- }
- //總線初始化子函數(shù)
- void i2cinit()
- {
- SDA=1;
- delay2();
- SCL=1;
- delay2();
- }
- //啟動(dòng)信號(hào)子函數(shù)
- void start()
- {
- SDA=1;
- SCL=1;
- delay2();
- SDA=0;
- delay2();
- }
- //停止信號(hào)子函數(shù)
- void stop()
- {
- SDA=0;
- delay2();
- SCL=1;
- delay2();
- SDA=1;
- delay2();
- }
- //應(yīng)答信號(hào)子函數(shù)
- void respons()
- {
- uchar i=0;
- SCL=1;
- delay2();
- while(SDA==1&&i<255)//等待應(yīng)答,過(guò)一段時(shí)間不應(yīng)答退出循環(huán)
- i++;
- SCL=0;
- delay2();
- }
- //寫一個(gè)字節(jié)子函數(shù)
- void writebyte(uchar date)
- {
- uchar i,temp;
- temp=date;
- for(i=0;i<8;i++)
- {
- temp<<=1;//temp左移一位后高位進(jìn)CY
- SCL=0;
- delay2();
- SDA=CY;
- delay2();
- SCL=1;
- delay2();
- }
- SCL=0;//應(yīng)答信號(hào)中SCL = 1,所以這里要置0
- delay2();
- SDA=1;//用完要釋放數(shù)據(jù)總線
- delay2();
- }
- //讀一個(gè)字節(jié)子函數(shù)
- uchar readbyte()
- {
- uchar i,k;
- SCL=0;
- delay2();
- SDA=1;
- for(i=0;i<8;i++)
- {
- SCL=1;
- delay2();
- k=(k<<1)|SDA; //和最低位或,一位位送到K
- SCL=0;
- delay2();
- }
- delay2();
- return k;
- }
- //向地址寫一個(gè)字節(jié)數(shù)據(jù)子函數(shù)
- void write_add(uchar address,uchar date)
- {
- start();
- writebyte(0xa0);//A0,A1,A2接地,AT24C02芯片地址為1010,送控制字為1010A2A1A0R/~W
- respons();
- writebyte(address);
- respons();
- writebyte(date);
- respons();
- stop();
- }
- //向地址讀一個(gè)字節(jié)數(shù)據(jù)子函數(shù)
- uchar read_add(uchar address)
- {
- uchar date;
- start();
- writebyte(0xa0);//A0,A1,A2接地,AT24C02芯片地址為1010,送控制字為1010A2A1A0R/~W
- respons();
- writebyte(address);
- respons();
- start();
- writebyte(0xa1);//A0,A1,A2接地,AT24C02芯片地址為1010,送控制字為1010A2A1A0R/~W
- respons();
- date=readbyte();
- stop();
- return date;
- }
- //向地址寫n個(gè)字節(jié)數(shù)據(jù)子函數(shù)
- void write_n_add(uchar *p,uchar address,uchar n)
- {
- uchar i;
- for(i=0;i<n;i++)
- {
- write_add((address+i),*(p+i));
- delay1(20);//一定要適當(dāng)延時(shí),不然寫不進(jìn)去
- }
- }
- //向地址讀n個(gè)字節(jié)數(shù)據(jù)子函數(shù)
- void read_n_add(uchar *p,uchar address,uchar n)
- {
- uchar i;
- for(i=0;i<n;i++)
- {
- *(p+i)=read_add(address+i);
- }
- }
- //LCD1602液晶讀忙子函數(shù)
- bit LCD1602_busy()
- {
- bit a;
- RS=0;
- RW=1;
- E=1;
- _nop_();
- _nop_();
- a=(bit)(P0&0x80);
- E=0;
- return a;
- }
- //LCD1602液晶寫命令子函數(shù)
- void write_com(uchar com)
- {
- while(LCD1602_busy());
- RW=0;
- RS=0;
- E=0;
- P0=com;
- delay1(5);
- E=1;
- delay1(5);
- E=0;
- }
- //LCD1602液晶寫數(shù)據(jù)子函數(shù)
- void write_date(uchar date)
- {
- while(LCD1602_busy());
- RW=0;
- RS=1;
- E=0;
- P0=date;
- delay1(5);
- E=1;
- delay1(5);
- E=0;
- }
- //寫一個(gè)字符子函數(shù)
- void write_1_char(uchar zifu)
- {
- write_date(zifu);
- }
- //向液晶寫n個(gè)字符子函數(shù)
- void write_n_char(uchar zifu[])
- {
- uchar i;
- for(i=0;;i++)
- {
- write_1_char(zifu[i]);
- if(zifu[i+1]=='\0')
- break;
- }
- }
- //設(shè)置液晶顯示位置子函數(shù)
- void LCD1602_pos(uchar x,uchar y)
- {
- uchar pos;
- if(x==0)
- x=0x80;
- else if(x==1)
- x=0x80+0x40;
- pos=x+y;
- write_com(pos);
- }
- //LCD1602液晶初始化子函數(shù)
- void LCD1602_init()
- {
- E=0;
- write_com(0x38);//設(shè)置16x2顯示,5x7點(diǎn)陣,8位數(shù)據(jù)口
- write_com(0x0c);//設(shè)置開(kāi)顯示,不顯示光標(biāo)
- write_com(0x06);//寫一個(gè)字符后地址指針加1
- write_com(0x01);//顯示清0,數(shù)據(jù)指針清0
- }
- //報(bào)警子函數(shù)
- void baojing1()
- {
- int i;
- for(i=0;i<5;i++)
- {
- beep=1;
- D1=0;
- delay1(5);
- beep=0;
- D1=1;
- delay1(5);
- }
- }
- void baojing2()
- {
- uchar i;
- for(i=0;i<10;i++)
- {
- baojing1();
- }
- }
- //矩陣按鍵掃描子函數(shù)
- uchar keyscan()
- {
- uchar temp,key;
- key=0xff;
- P1=0xfe; //將第一行線置低電平
- temp=P1;//讀JPJK的當(dāng)前狀態(tài)到 temp
- temp&=0xf0;// temp = temp & 0xf0 按位與
- if(temp!=0xf0)
- {
- delay1(10);//延時(shí)去抖
- temp=P1;
- temp&=0xf0;
- if(temp!=0xf0)//第一行有鍵被按下
- {
- temp=P1;//讀被按下的鍵
- baojing1();
- switch(temp)
- {
- case 0xee: key=1;
- break;
- case 0xde: key=2;
- break;
- case 0xbe: key=3;
- break;
- case 0x7e: key=0x0a;
- break;
- }
- while(temp!=0xf0)//等待按鍵釋放
- {
- temp=P1;
- temp&=0xf0;
- }
- }
- }
- P1=0xfd; //將第二行線置低電平
- temp=P1;//讀JPJK的當(dāng)前狀態(tài)到 temp
- temp&=0xf0;// temp = temp & 0xf0
- if(temp!=0xf0)
- {
- delay1(10);//延時(shí)去抖
- temp=P1;
- temp&=0xf0;
- if(temp!=0xf0)//第二行有鍵被按下
- {
- temp=P1;//讀被按下的鍵
- baojing1();
- switch(temp)
- {
- case 0xed: key=4;
- break;
- case 0xdd: key=5;
- break;
- case 0xbd: key=6;
- break;
- case 0x7d: key=0x0b;
- break;
- }
- while(temp!=0xf0)//等待按鍵釋放
- {
- temp=P1;
- temp&=0xf0;
- }
- }
- }
- P1=0xfb; //將第 三行線置低電平
- temp=P1;//讀JPJK的當(dāng)前狀態(tài)到 temp
- temp&=0xf0;// temp = temp & 0xf0
- if(temp!=0xf0)
- {
- delay1(10);//延時(shí)去抖
- temp=P1;
- temp&=0xf0;
- if(temp!=0xf0)//第三行有鍵被按下
- {
- temp=P1;//讀被按下的鍵
- baojing1();
- switch(temp)
- {
- case 0xeb: key=7;
- break;
- case 0xdb: key=8;
- break;
- case 0xbb: key=9;
- break;
- case 0x7b: key=0x0c;
- break;
- }
- while(temp!=0xf0)//等待按鍵釋放
- {
- temp=P1;
- temp&=0xf0;
- }
- }
- }
- P1=0xf7; //將第四行線置低電平
- temp=P1;//讀JPJK的當(dāng)前狀態(tài)到 temp
- temp&=0xf0;// temp = temp & 0xf0
- if(temp!=0xf0)
- {
- delay1(10);//延時(shí)去抖
- temp=P1;
- temp&=0xf0;
- if(temp!=0xf0)//第四行有鍵被按下
- {
- temp=P1;//讀被按下的鍵
- baojing1();
- switch(temp)
- {
- case 0xe7: key=0;
- break;
- case 0xd7: key=0;
- break;
- case 0xb7: key=0x0f;
- break;
- case 0x77: key=0x0d;
- break;
- }
- while(temp!=0xf0)//等待按鍵釋放
- {
- temp=P1;
- temp&=0xf0;
- }
- }
- }
- return key; //返回按下的鍵
- }
- //比較密碼子函數(shù)
- bit sfj1(uchar *string1,uchar *string2)
- {
- uchar i;
- for(i=0;i<6;i++)
- {
- if(string1[i]!=string2[i])
- return 0;
- }
- return 1;
- }
- //選擇輸入密碼或修改密碼函數(shù)
- uchar step_choose()
- {
- uchar key;
- key=0xff;
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- LCD1602_pos(0,0);
- write_n_char(" Input password ");
- LCD1602_pos(1,0);
- write_n_char(" Press key A ");
- while((key!=0x0a)&&(key!=B))
- key=keyscan();
- return key;
- }
- //輸入密碼子函數(shù)
- bit input_mima(uchar * mima)
- {
- uchar i,key;
- LCD1602_pos(1,0);
- for(i=0;i<7;i++)
- {
- delay1(100);
- if(i<6)
- {
- do
- {
- key=keyscan();
- }//掃描鍵盤
- while(key==0xff);
- if((key!=0x0f)&&(key!=0x0a)&&(key!=0x0c))//不是退格也不是確認(rèn)鍵
- {
- write_date('*');//是數(shù)字鍵顯示*
- mima[i]=key;
- }
- if(key==0x0f)//是退格鍵
- {
- if(i>0)
- {
- LCD1602_pos(1,--i);//光標(biāo)前移一位
- write_date(' ');//清空一位
- mima[i]=' ';//寫空
- LCD1602_pos(1,i);
- i--;//密碼計(jì)數(shù)器減一 ,因?yàn)檠h(huán)后會(huì)+1,所以在這里要加1
- }
- }
- if(key==0x0c)//沒(méi)完成密碼輸入返回錯(cuò)誤信息
- {
- LCD1602_pos(0,0);
- return(0);
- }
- }
- if(i==6)
- {
- do
- {
- key=keyscan();
- }
- while((key!=0x0f)&&(key!=0x0c));
- if(key==0x0f)
- {
- LCD1602_pos(1,--i);
- write_date(' ');
- mima[i]=' ';
- LCD1602_pos(1,i);
- i--;
- }
- if(key==0x0c)//密碼位數(shù)正確
- {
- return(1);//返回1正確信號(hào)
- }
- }
- }
- }
- //密碼處理子函數(shù)
- void sfj2()
- {
- uchar key,i;
- uchar idata table2[6]={' ',' ',' ',' ',' ',' '};//存放密碼緩沖區(qū)
- uchar idata table3[6]={' ',' ',' ',' ',' ',' '};
- uchar idata table4[6]={' ',' ',' ',' ',' ',' '};
- key=step_choose();
- if(key==0x0a)//A被按下,接收輸入密碼,處理
- {
- read_n_add(table2,0x00,6);
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_com(0x0f);//顯示光標(biāo)
- LCD1602_pos(0,0);
- write_n_char(" press password ");
- if(input_mima(table3)) //處理輸入密碼
- {
- if(sfj1(table3,table2)) //密碼正確
- {
- LCD1602_pos(0,0);
- write_com(0x0c);
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_n_char(" password right ");
- aa=0; //清除密碼錯(cuò)誤次數(shù)
- D1=0; //開(kāi)鎖
- beep=1; //響一下
- delay1(1000);
- beep=0;
- TR0=1;
- cc=1;
- while(key!=0x0d&&cc) //D沒(méi)按下一直開(kāi)
- {
- key=keyscan();
- }
- TR0=0;
- D1=1;//D按下了關(guān)鎖
- }
- else //密碼 不正確
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //關(guān)光標(biāo)
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_n_char(" password wrong");
- delay1(1000);
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //密碼不正確報(bào)警
- while(i--)
- baojing2();
- }
- }
- }
- else //密碼沒(méi)有輸入正確或完成
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //關(guān)光標(biāo)
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_n_char(" password wrong");
- delay1(1000);
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //密碼不正確報(bào)警
- while(i--)
- baojing2();
- }
- }
- }
- if(key==0x0b)//B被按下,修改密碼
- {
- read_n_add(table2,0x00,6);
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_com(0x0f);//顯示光標(biāo)
- LCD1602_pos(0,0);
- write_n_char(" input password");
- write_com(0x0f);//顯示光標(biāo)
- if(input_mima(table3)) //處理輸入密碼
- {
- if(sfj1(table3,table2)) //密碼正確
- {
- LCD1602_pos(0,0);
- write_com(0x0c);
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_n_char("password right ");
- aa=0; //清除密碼錯(cuò)誤次數(shù)
- delay1(1500);
- dd=1;
- while(dd) //下面開(kāi)始修改密碼
- {
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_com(0x0f);//顯示光標(biāo)
- LCD1602_pos(0,0);
- write_n_char("In new password");
- delay1(1500);
- if(input_mima(table3)) //處理輸入密碼
- {
- LCD1602_pos(0,0);
- write_com(0x0c);
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_n_char("Input new pass"); //確定新密碼
- LCD1602_pos(1,0);
- write_n_char("word again");
- delay1(2000);
- LCD1602_pos(0,0);
- write_com(0x0f);//顯示光標(biāo)
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_n_char("In new password");
- if(input_mima(table4)) //處理輸入密碼
- {
- if(sfj1(table3,table4)) //密碼正確
- {
- LCD1602_pos(0,0);
- write_com(0x0c);
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_n_char("password has");
- LCD1602_pos(1,0);
- write_n_char("change already");
- write_n_add(table4,0x00,6); //把修改的密碼存進(jìn)24C02
- delay1(2000);
- dd=0;
- }
- else //密碼 不正確
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //關(guān)光標(biāo)
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_n_char("password wrong");
- delay1(1000);
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //3次輸入密碼不正確報(bào)警
- while(i--)
- baojing2();
- }
- dd=0;
- }
- }
- else //密碼沒(méi)有輸入正確或完成
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //關(guān)光標(biāo)
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_n_char(" password wrong");
- delay1(1000);
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //3次輸入密碼不正確報(bào)警
- while(i--)
- baojing2();
- }
- }
- }
- else //密碼沒(méi)有輸入正確或完成
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //關(guān)光標(biāo)
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_n_char("password wrong");
- delay1(1000);
- dd=0;
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //3次輸入密碼不正確報(bào)警
- while(i--)
- baojing2();
- }
- }
- }
- }
- else //密碼 不正確
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //關(guān)光標(biāo)
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_n_char("password wrong");
- delay1(1000);
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //3次輸入密碼不正確報(bào)警
- while(i--)
- baojing2();
- }
- }
- }
- else //密碼沒(méi)有輸入正確或完成
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //關(guān)光標(biāo)
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_n_char("password wrong");
- delay1(1000);
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //3次輸入密碼不正確報(bào)警
- while(i--)
- baojing2();
- }
- }
- }
- }
- //主函數(shù)
- void main()
- {
- LCD1602_init();//調(diào)用液晶初始化子函數(shù)
- i2cinit();//調(diào)用24C02總線初始化子函數(shù)
- beep=0;
- D1=1; //關(guān)鎖
- TMOD=0x01;//選擇定時(shí)器0方式1
- EA=1;//打開(kāi)總中斷
- ET0=1;//打開(kāi)定時(shí)器0中斷
- EX0=1; //打開(kāi)外部中斷0
- IT0=1;//下降沿觸發(fā)
- TR0=0;//關(guān)閉定時(shí)器
- TH0=0x4c;//50ms裝初值
- TL0=0x00;
- while(1)
- {
- sfj2();//調(diào)用密碼處理子函數(shù)
- }
- }
- //外部中斷0子函數(shù)
- void wb0() interrupt 0
- {
- delay1(2000);
- if(!k1)
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //關(guān)光標(biāo)
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- i2cinit();//24C02總線初始化
- write_n_add(table1,0x00,6);
- write_n_char("password renew");
- LCD1602_pos(1,0);
- write_n_char("already");
- delay1(1000);
- LCD1602_pos(0,0);
- write_com(0x0c); //關(guān)光標(biāo)
- write_com(0x06);//寫一個(gè)字符后地址指針加 1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_n_char("Input password");
- LCD1602_pos(1,0);
- write_n_char("Press key A");
- }
- }
- //定時(shí)器0中斷子函數(shù)
- void t0() interrupt 1
- {
- TH0=0x4c;//50ms定時(shí)
- TL0=0x00;
- bb++;
- if(bb==200)//10秒時(shí)間到
- {
- bb=0;
- cc=0;
- }
- }
-
復(fù)制代碼
0.png (43.7 KB, 下載次數(shù): 140)
下載附件
2017-4-10 22:30 上傳
下載:
3、基于51單片機(jī)電子密碼鎖的設(shè)計(jì).zip
(108.29 KB, 下載次數(shù): 456)
2017-4-10 21:43 上傳
點(diǎn)擊文件名下載附件
程序和protues仿真 下載積分: 黑幣 -5
|