标题: 基于51单片机的电子密码锁proteus仿真加源程序 [打印本页]
作者: mumu98 时间: 2017-4-10 21:44
标题: 基于51单片机的电子密码锁proteus仿真加源程序
(1)设置6位密码,密码通过键盘输入,若密码正确,则将锁打开,初始化密码为(123456)。
(2)密码可以由用户自己修改设定(支持6位密码),锁打开后才能修改密码。修改密码之前必须再次输入密码,在输入新密码时候需要二次确认,以防止误操作。
(3)报警、锁定键盘功能。密码输入错误数码显示器会出现错误提示,若密码输入错误次数超过4次,蜂鸣器报警并且锁定键盘。
(4)密码修改后有存储功能。
(5)一键恢复初始密码功能。
源程序:
- #include<reg51.h>
- #include<intrins.h>
- typedef unsigned char uchar;
- typedef unsigned int uint;
- sbit beep=P2^4;//蜂鸣器接口
- sbit D1=P2^2;//开锁信号
- sbit k1=P3^2;//恢复初始密码按键
- sbit RS=P2^7;//数据命令选择
- sbit RW=P2^6;//读写控制
- sbit E=P2^5;//液晶使能
- sbit SDA=P2^1; //数据线接口
- sbit SCL=P2^0;//时钟线接口
- uchar idata table1[6]={1,2,3,4,5,6}; //初始密码
- uchar dd;
- uchar aa;//存放密码错误的次数,够三次报警
- uchar bb;
- uchar cc;
- //延时子函数
- void delay1(uint z)
- {
- uint x,y;
- for(x=0;x<z;x++)
- for(y=0;y<110;y++);
- }
- void delay2()
- {
- ;;
- }
- //总线初始化子函数
- void i2cinit()
- {
- SDA=1;
- delay2();
- SCL=1;
- delay2();
- }
- //启动信号子函数
- void start()
- {
- SDA=1;
- SCL=1;
- delay2();
- SDA=0;
- delay2();
- }
- //停止信号子函数
- void stop()
- {
- SDA=0;
- delay2();
- SCL=1;
- delay2();
- SDA=1;
- delay2();
- }
- //应答信号子函数
- void respons()
- {
- uchar i=0;
- SCL=1;
- delay2();
- while(SDA==1&&i<255)//等待应答,过一段时间不应答退出循环
- i++;
- SCL=0;
- delay2();
- }
- //写一个字节子函数
- void writebyte(uchar date)
- {
- uchar i,temp;
- temp=date;
- for(i=0;i<8;i++)
- {
- temp<<=1;//temp左移一位后高位进CY
- SCL=0;
- delay2();
- SDA=CY;
- delay2();
- SCL=1;
- delay2();
- }
- SCL=0;//应答信号中SCL = 1,所以这里要置0
- delay2();
- SDA=1;//用完要释放数据总线
- delay2();
- }
- //读一个字节子函数
- 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;
- }
- //向地址写一个字节数据子函数
- 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();
- }
- //向地址读一个字节数据子函数
- 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个字节数据子函数
- 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);//一定要适当延时,不然写不进去
- }
- }
- //向地址读n个字节数据子函数
- 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液晶读忙子函数
- bit LCD1602_busy()
- {
- bit a;
- RS=0;
- RW=1;
- E=1;
- _nop_();
- _nop_();
- a=(bit)(P0&0x80);
- E=0;
- return a;
- }
- //LCD1602液晶写命令子函数
- 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液晶写数据子函数
- void write_date(uchar date)
- {
- while(LCD1602_busy());
- RW=0;
- RS=1;
- E=0;
- P0=date;
- delay1(5);
- E=1;
- delay1(5);
- E=0;
- }
- //写一个字符子函数
- void write_1_char(uchar zifu)
- {
- write_date(zifu);
- }
- //向液晶写n个字符子函数
- void write_n_char(uchar zifu[])
- {
- uchar i;
- for(i=0;;i++)
- {
- write_1_char(zifu[i]);
- if(zifu[i+1]=='\0')
- break;
- }
- }
- //设置液晶显示位置子函数
- 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液晶初始化子函数
- void LCD1602_init()
- {
- E=0;
- write_com(0x38);//设置16x2显示,5x7点阵,8位数据口
- write_com(0x0c);//设置开显示,不显示光标
- write_com(0x06);//写一个字符后地址指针加1
- write_com(0x01);//显示清0,数据指针清0
- }
- //报警子函数
- 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();
- }
- }
- //矩阵按键扫描子函数
- uchar keyscan()
- {
- uchar temp,key;
- key=0xff;
- P1=0xfe; //将第一行线置低电平
- temp=P1;//读JPJK的当前状态到 temp
- temp&=0xf0;// temp = temp & 0xf0 按位与
- if(temp!=0xf0)
- {
- delay1(10);//延时去抖
- 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的当前状态到 temp
- temp&=0xf0;// temp = temp & 0xf0
- if(temp!=0xf0)
- {
- delay1(10);//延时去抖
- 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的当前状态到 temp
- temp&=0xf0;// temp = temp & 0xf0
- if(temp!=0xf0)
- {
- delay1(10);//延时去抖
- 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的当前状态到 temp
- temp&=0xf0;// temp = temp & 0xf0
- if(temp!=0xf0)
- {
- delay1(10);//延时去抖
- 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; //返回按下的键
- }
- //比较密码子函数
- bit sfj1(uchar *string1,uchar *string2)
- {
- uchar i;
- for(i=0;i<6;i++)
- {
- if(string1[i]!=string2[i])
- return 0;
- }
- return 1;
- }
- //选择输入密码或修改密码函数
- uchar step_choose()
- {
- uchar key;
- key=0xff;
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- 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;
- }
- //输入密码子函数
- 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))//不是退格也不是确认键
- {
- write_date('*');//是数字键显示*
- mima[i]=key;
- }
- if(key==0x0f)//是退格键
- {
- if(i>0)
- {
- LCD1602_pos(1,--i);//光标前移一位
- write_date(' ');//清空一位
- mima[i]=' ';//写空
- LCD1602_pos(1,i);
- i--;//密码计数器减一 ,因为循环后会+1,所以在这里要加1
- }
- }
- if(key==0x0c)//没完成密码输入返回错误信息
- {
- 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)//密码位数正确
- {
- return(1);//返回1正确信号
- }
- }
- }
- }
- //密码处理子函数
- void sfj2()
- {
- uchar key,i;
- uchar idata table2[6]={' ',' ',' ',' ',' ',' '};//存放密码缓冲区
- uchar idata table3[6]={' ',' ',' ',' ',' ',' '};
- uchar idata table4[6]={' ',' ',' ',' ',' ',' '};
- key=step_choose();
- if(key==0x0a)//A被按下,接收输入密码,处理
- {
- read_n_add(table2,0x00,6);
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_com(0x0f);//显示光标
- 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);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_n_char(" password right ");
- aa=0; //清除密码错误次数
- D1=0; //开锁
- beep=1; //响一下
- delay1(1000);
- beep=0;
- TR0=1;
- cc=1;
- while(key!=0x0d&&cc) //D没按下一直开
- {
- key=keyscan();
- }
- TR0=0;
- D1=1;//D按下了关锁
- }
- else //密码 不正确
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //关光标
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_n_char(" password wrong");
- delay1(1000);
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //密码不正确报警
- while(i--)
- baojing2();
- }
- }
- }
- else //密码没有输入正确或完成
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //关光标
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_n_char(" password wrong");
- delay1(1000);
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //密码不正确报警
- while(i--)
- baojing2();
- }
- }
- }
- if(key==0x0b)//B被按下,修改密码
- {
- read_n_add(table2,0x00,6);
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_com(0x0f);//显示光标
- LCD1602_pos(0,0);
- write_n_char(" input password");
- write_com(0x0f);//显示光标
- if(input_mima(table3)) //处理输入密码
- {
- if(sfj1(table3,table2)) //密码正确
- {
- LCD1602_pos(0,0);
- write_com(0x0c);
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_n_char("password right ");
- aa=0; //清除密码错误次数
- delay1(1500);
- dd=1;
- while(dd) //下面开始修改密码
- {
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_com(0x0f);//显示光标
- 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);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_n_char("Input new pass"); //确定新密码
- LCD1602_pos(1,0);
- write_n_char("word again");
- delay1(2000);
- LCD1602_pos(0,0);
- write_com(0x0f);//显示光标
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_n_char("In new password");
- if(input_mima(table4)) //处理输入密码
- {
- if(sfj1(table3,table4)) //密码正确
- {
- LCD1602_pos(0,0);
- write_com(0x0c);
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_n_char("password has");
- LCD1602_pos(1,0);
- write_n_char("change already");
- write_n_add(table4,0x00,6); //把修改的密码存进24C02
- delay1(2000);
- dd=0;
- }
- else //密码 不正确
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //关光标
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_n_char("password wrong");
- delay1(1000);
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //3次输入密码不正确报警
- while(i--)
- baojing2();
- }
- dd=0;
- }
- }
- else //密码没有输入正确或完成
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //关光标
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_n_char(" password wrong");
- delay1(1000);
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //3次输入密码不正确报警
- while(i--)
- baojing2();
- }
- }
- }
- else //密码没有输入正确或完成
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //关光标
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_n_char("password wrong");
- delay1(1000);
- dd=0;
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //3次输入密码不正确报警
- while(i--)
- baojing2();
- }
- }
- }
- }
- else //密码 不正确
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //关光标
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_n_char("password wrong");
- delay1(1000);
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //3次输入密码不正确报警
- while(i--)
- baojing2();
- }
- }
- }
- else //密码没有输入正确或完成
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //关光标
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_n_char("password wrong");
- delay1(1000);
- aa++;
- if(aa==4)
- {
- aa=0;
- i=20; //3次输入密码不正确报警
- while(i--)
- baojing2();
- }
- }
- }
- }
- //主函数
- void main()
- {
- LCD1602_init();//调用液晶初始化子函数
- i2cinit();//调用24C02总线初始化子函数
- beep=0;
- D1=1; //关锁
- TMOD=0x01;//选择定时器0方式1
- EA=1;//打开总中断
- ET0=1;//打开定时器0中断
- EX0=1; //打开外部中断0
- IT0=1;//下降沿触发
- TR0=0;//关闭定时器
- TH0=0x4c;//50ms装初值
- TL0=0x00;
- while(1)
- {
- sfj2();//调用密码处理子函数
- }
- }
- //外部中断0子函数
- void wb0() interrupt 0
- {
- delay1(2000);
- if(!k1)
- {
- LCD1602_pos(0,0);
- write_com(0x0c); //关光标
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- 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); //关光标
- write_com(0x06);//写一个字符后地址指针加 1
- write_com(0x01);//显示清零,数据指针清零
- write_n_char("Input password");
- LCD1602_pos(1,0);
- write_n_char("Press key A");
- }
- }
- //定时器0中断子函数
- void t0() interrupt 1
- {
- TH0=0x4c;//50ms定时
- TL0=0x00;
- bb++;
- if(bb==200)//10秒时间到
- {
- bb=0;
- cc=0;
- }
- }
-
复制代码
下载:
3、基于51单片机电子密码锁的设计.zip
(108.29 KB, 下载次数: 456)
作者: zgh035 时间: 2017-5-21 11:28
很厉害哦
作者: ggg620 时间: 2017-7-7 12:02
太棒了,谢谢哦。哈哈
作者: h770380530 时间: 2017-11-24 09:27
谁能给我下载这个文件?
作者: XDQ 时间: 2017-12-7 01:00
大神您这个程序为什么用Keil uVision4再次编译成HEX文件烧写到仿真里的时候。按下修改密码键没有任何的反应
作者: XDQ 时间: 2017-12-7 01:25
谢谢分享!大神为什么你的程序重新生成HEX文件后在烧写到仿真图里面,修改密码的功能就不能使用是改过什么地方吗?
作者: 150230117 时间: 2017-12-20 18:25
楼主很棒
作者: Visper 时间: 2018-1-4 10:46
logic contention detected on 是咋回事啊?
作者: 635040759 时间: 2018-1-15 14:59
黑币不够,谁可以给我这个文件啊,名字是扣扣,红包奖励
作者: A-NEW-YOUNG 时间: 2018-1-17 10:52
这个帖子对我帮助很大,谢谢!!!
作者: a153315 时间: 2018-1-23 22:54
要怎么下载啊、
作者: zhang_123456 时间: 2018-1-28 13:50
为什么总是仿真总是密码错误呢
作者: 黄aa啊啊 时间: 2018-5-3 12:28
非常有用!
作者: 1443351061 时间: 2018-5-18 15:55
怎么样啊
作者: 赵思惠 时间: 2018-5-20 09:24
同上问题啊 再次生成新的hex文件烧写进去一直只能输入密码
作者: 3117195754 时间: 2018-5-21 13:57
不知道都有啥元件,大神指示一下
作者: kruijie0422 时间: 2018-5-23 19:23
厉害了。
作者: 加油兄弟 时间: 2018-6-7 11:14
不错我可以学习挺久时间啦
作者: 天涯海 时间: 2018-6-18 13:15
密码改了没反应
作者: 转山 时间: 2018-6-18 15:10
楼主厉害,谢谢共享
作者: 小小斑鸠 时间: 2018-8-25 13:36
谢谢大佬,很厉害
作者: retr 时间: 2018-9-12 12:31
为什么我打不开仿真文件
作者: yuchanghao 时间: 2019-7-13 11:14
不能修改密码
作者: WJ雅 时间: 2019-12-27 13:22
为什么运行代码有错误
作者: DWADAW 时间: 2020-5-22 17:16
很好很实用
作者: 大迪a 时间: 2020-6-5 17:01
密码修改不了怎么办
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |