摘要:随着社会的发展,电子密码锁在日常生活中的作用越来越明显。本电子密码锁是基于单片机的设计,主要划分为四大模块,由单片机最小系统、矩阵键盘、LCD显示、声光报警模块等组成。单片机最小系统的主要功能是对外部输入的数据进行处理,显示电路将所要操作的步骤显示出来,指导用户使用,报警电路是对输入错误密码时的警告报警。系统能完成开锁、密码输入错误报警、密码删除、密码修改等基本功能[1]。
关键词:解锁;数据处理;单片机;LCD显示;报警
The Design of Electronic Password Locks Based on MCU
Abstract: With the development of our society, electronic password locks play a more and more important role in nowadays. The design of this electronic password locks based on MCU mainly divided into four modules, including the MCU minimum system, matrix keyboard, LCD display, sound and light alarm module circuit and so on. The MCU minimum system processes the input data from matrix keyboard. The LCD displaies the operating steps one by one and guides the users to operate. If the input password is wrong the sound and light alarm module circuit will work. The system can realize the basic function, such as opening the electronic locks completely, alarming with the error password, deleting the password, modifying the password and so on[1].
Key words: unlocking, data processing, MCU, LCD display, alarm
一、引言
在日常的生活和工作中,住宅与部门的安全防范、单位文件档案、财务报表以及一些个人资料的保存多以加锁的办法来解决,若使用传统的机械式钥匙开锁,人门常需要携带多把钥匙,使用极其不方便,且钥匙丢失后安全性将大打折扣。随着科学技术的不断发展,人们对日常生活中的安全保险器件的要求越来越高。为满足人们对锁的使用要求,增加其安全性,用密码代替钥匙的电子密码锁应运而生。电子密码锁具有安全性高、成本低、功耗低、易操作等特点[2]。
本电子密码锁是基于单片机的设计,主要划分为四大模块,由单片机最小系统、矩阵键盘、LCD显示、声光报警模块等组成。单片机最小系统的主要功能是对外部输入的数据进行处理,显示电路将所要操作的步骤显示出来,指导用户使用,声光报警模块是对输入错误密码次数超过三次时的警告报警。系统能完成开锁、密码输入错误报警、密码删除、密码修改等功能。
二、系统总方案设计
本设计的系统总方案设计方框图如图1所示。
图1 系统总设计方框图
三、具体硬件电路设计
1、键盘输入模块设计:键盘选用4*4矩阵,具有数字键0-9、开锁键、删除键、修改密码键和消除报警键等。4*4键盘输入模块如图2所示。
图2 4*4键盘输入模块电路图
2、单片机最小系统设计:本设计选用STCC51单片机作为控制核心。STCC51是具有高性能和低功耗优点的8位可编程控制器,内核具有丰富的指令集和32个通用工作寄存器,可以通过软件编程来实现电子密码锁设计中的各项要求和功能,而且单片机的 I/O 口也足够使用,硬件电路连接比较简单。单片机最小系统如图3所示[3]。
图3 单片机最小系统电路图
3、LCD显示模块设计:LCD显示模块选用LCD1602 作为主液晶显示器。此液晶显示屏能输入两行的字母或数字,功能比较简单,通用性强。本次设计中要显示输入密码的数据值和各功能的提示,使用 LCD1602 液晶来作为显示模块比较直观形象。LCD显示模块如图4所示。
图4 LCD显示模块电路图
4、声光报警模块设计:采用声和光两种方式的双重效果进行报警,如果错误密码输入次数超过三次则报警灯闪烁而且蜂鸣器会报警,这样就能多角度进行密码错误报警。声光报警模块如图5所示。
图5 声光报警模块电路图
四、软件设计
1、主程序流程图:主程序主要完成LCD初始化、检查有无按键按下、以及调用显示、密码修改程序等等。主程序流程图如图6所示。
图6 主程序流程图
2、LCD显示模块流程图:本系统使用LCD1602实现显示,参照LCD1602的使用手册进行初始化和程序编写就可以显示,即在程序编写中添加LCD1602的驱动程序。这里的驱动程序主要包括:初始化函数、设置显示坐标、写字符函数及写字符串函数。在时钟界面时显示时间的运行,在密码锁界面时主要显示提示信息和输入的密码,当然,当输入密码数字时,输出不是显示数字,而是用“*”显示代替。LCD1602的部分读写控制时序程序如图7所示。
图7 LCD显示模块流程图
五、结束语
这一次做的电子密码锁及LCD显示。原理看似简单,但过程让我深深感受到再简单的电路图,理论与实际也会有一定的差入。在参考书原理图的基础上经过了个人的改进,让功能更完善,特别是程序的调试,花的时间最多,也是最难的一个地方。通过本次设计,培养了创新意识和综合素质,更好地掌握了电子产品设计与制作的工艺和流程,提高个人基本能力、实验及设计能力和工作能力,基本知识更加牢固,会看图、会测量、会查资料。
六、参考文献
[1] 杭和平. 单片机原理与应用. 北京:机械工业出版社,2008
[2] 李朝青. 单片机原理与接口技术.北京:航空航天出版社,2009
[3] 宋彩利. 单片机原理与C51编程 [M]. 西安交通大学出版社,2007
附录一:系统设计总原理图
附录二:系统设计程序
#include #include #define ulong unsigned long #define uint unsigned int #define uchar unsigned char uchar temp,num,flag,sum=0,r; uchar code table1[]=" Welcome!(^_^)"; uchar code table2[]="01234567ABCDEF"; uchar code table3[]="******"; uchar code table4[]="Code is wrong!"; uchar code table5[]="You are right!"; uchar code table6[]="The second time!"; uchar code table7[]="The last time!"; uchar code table8[]="Input new code:"; uchar code table9[]="Modify right!!!"; uchar code table10[]="Password:"; uchar code table11[]=" Wang rui xiang"; uchar code table12[]=" Calling...."; uchar code table13[]=" "; uchar code table14[]="Input again:"; uchar code table15[]="Modify error!!!"; uchar init_pswd[6]={1,2,3,4,5,6};//初始化密码 uchar pswd[6]={0}; sbit led0=P1^0; sbit led1=P1^1; sbit led2=P1^2; sbit lcdrs=P2^4; sbit lcdrw=P2^5; sbit lcden=P2^6; sbit beep=P2^0; /*****************************************子函数声明*/ void delay(uint z); void init();//初始化子函数 void write_com(uchar com);//写指令子函数 void write_data(uchar dat1);//写数据子函数 void keyscan(); void mima(); void mima1(); void delete(); /************************************************液晶驱动*/ void init() { lcden=0; write_com(0x38); write_com(0x0e); write_com(0x06); write_com(0x01); write_com(0x80); } void write_com(uchar com) //写指令 { lcdrs=0; lcdrw=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; } void write_data(uchar dat1) { lcdrs=1; lcdrw=0; P0=dat1; delay(5); lcden=1; delay(5); lcden=0; } void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void keyscan() { P3=0xef; temp=P3; temp=temp&0x0f; while(temp!=0x0f) { delay(5); temp=P3; temp=temp&0x0f; while(temp!=0x0f) { temp=P3; switch(temp) { case 0xee:num=0;flag=1;break; case 0xed:num=1;flag=1;break; case 0xeb:num=2;flag=1;break; case 0xe7:num=3;flag=1;break; } while(temp!=0x0f) { temp=P3; temp=temp&0x0f; } } } P3=0xdf; temp=P3; temp=temp&0x0f; while(temp!=0x0f) { delay(5); temp=P3; temp=temp&0x0f; while(temp!=0x0f) { temp=P3; switch(temp) { case 0xde:num=4;flag=1;break; case 0xdd:num=5;flag=1;break; case 0xdb:num=6;flag=1;break; case 0xd7:num=7;flag=1;break; } while(temp!=0x0f) { temp=P3; temp=temp&0x0f; } } } P3=0xbf; temp=P3; temp=temp&0x0f; while(temp!=0x0f) { delay(5); temp=P3; temp=temp&0x0f; while(temp!=0x0f) { temp=P3; switch(temp) { case 0xbe:num=8;flag=1;break; case 0xbd:num=9;flag=1;break; case 0xbb:num=10;break; case 0xb7:num=11;break; } while(temp!=0x0f) { temp=P3; temp=temp&0x0f; } } } P3=0x7f; temp=P3; temp=temp&0x0f; while(temp!=0x0f) { delay(5); temp=P3; temp=temp&0x0f; while(temp!=0x0f) { temp=P3; switch(temp) { case 0x7e:num=12;flag=1;break; case 0x7d:num=13;flag=1;break; case 0x7b:num=14;flag=1;break; case 0x77:num=15;flag=1;break; } while(temp!=0x0f) { temp=P3; temp=temp&0x0f; } } } } /**********************主程序*****************************/ void main() { uchar m=0,w=0; init(); for(r=0;r<15;r++) { delay(5); write_data(table1[r]); } write_com(0x80+0x40); for(r=0;r<15;r++) { delay(5); write_data(table11[r]); } write_com(0x0c); do { keyscan(); } while(num!=15); mima(); while((pswd[m]==init_pswd[m])&m<6)//密码比较 { m++; } if(m>=6)//密码正确 { led0=0; keyscan(); while(flag==1&&num==13); mima1(); } else//密码有误 { m=0; write_com(0x80+0x40); for(r=0;r<14;r++) { delay(20); write_data(table4[r]); } delay(2000); init(); for(r=0;r<16;r++) { delay(20); write_data(table6[r]); } delay(2000); mima(); while((pswd[m]==init_pswd[m])&m<6)//再次比较 { m++; } if(m>=6) { mima1(); } else { m=0; write_com(0x80+0x40); for(r=0;r<14;r++) { delay(20); write_data(table4[r]); } delay(2000); init(); for(r=0;r<14;r++) { delay(20); write_data(table7[r]); } delay(2000); mima(); while((pswd[m]==init_pswd[m])&m<6)//第三次比较 { m++; } if(m>=6) { mima1(); } else { init(); write_com(0x80+0x40); for(r=0;r<14;r++) { delay(20); write_data(table12[r]); } write_com(0x0c); while(1) { delay(1); led1=0; beep=~beep; keyscan() if(flag==1&&num==12) { led1=1;beep=0;break;} } } } } } void mima() { uchar w=0;//局部变量很重要 init(); for(r=0;r<9;r++) { delay(20); write_data(table10[r]); } do { flag=0; keyscan(); write_com(0x80+9+w); if(flag==1&&num<=9) { pswd[w]=num; write_data(table3[w]); w++; if(w==6) write_com(0x0c); } if(flag==1&&num==14) //14则删除误输入的密码,即返回上一步. { w--; if(w==255) w=w+1; write_com(0x80+9+w); write_data(table13[w+1]); if(flag==1&&num<=9) { pswd[w]=num; write_data(table3[w]); } } } while(w<=5); } /********************输入初始密码正确后,密码修改*********************************************/ void mima1() { uchar f=0,n=0,d=0; if(sum==0) { write_com(0x80+0x40); for(r=0;r<14;r++) { delay(20); write_data(table5[r]); } delay(2000); do { num=16; keyscan(); }while(num!=13); if(flag==1&&num==13) { led0=1; led2=0; init(); for(r=0;r<15;r++) { delay(20); write_data(table8[r]); } write_com(0x0c); write_com(0x80+0x40+n); write_com(0x0e); } //////////////////////////第一次输入修改密码//////////////////////////////// do{ num=16; keyscan(); write_com(0x80+0x40+n); if(flag==1&&num<=9) { init_pswd[n]=num; write_data(table3[n]); n++; if(n==6) write_com(0x0c); } if(flag==1&&num==14) { n--; if(n==255) n=n+1; write_com(0x80+0x40+n); write_data(table13[n]); if(flag==1&&num<=9) { pswd[n]=num; write_data(table3[n]); } } }while(n<=5); ///////////////////////第二次输入修改密码,并判断是否正确///////////////////////////////////////// init(); for(r=0;r<12;r++) { delay(20); write_data(table14[r]); } do { flag=0; keyscan(); write_com(0x80+0x40+d); if(flag==1&&num<=9) { pswd[d]=num; write_data(table3[d]); d++; if(d==6) write_com(0x0c); } if(flag==1&&num==14) { d--; if(d==255) d=d+1; write_com(0x80+0x40+d); write_data(table13[d+1]); if(flag==1&&num<=9) { pswd[d]=num; write_data(table3[d]); } } } while(d<=5); while((pswd[f]==init_pswd[f])&f<6)//密码比较 { f++; } if(f>=6)//密码正确 { init(); for(r=0;r<15;r++) { delay(20); write_data(table9[r]); } delay(5000); led2=1; main(); } else { init(); for(r=0;r<15;r++) { delay(20); write_data(table15[r]); } delay(5000); main(); } } }