电子系统设计报告
系 部: 物理与机电工程学院 实验项目: 多功能密码锁 专业班级: 学 号: 学生姓名: 同组成员: 指导教师: 完成时间: 2011-06-19 报告成绩:
评阅意见: 评阅教师 日期
电子密码锁
一、设计任务与要求
1、采用STC89C52单片机为主控芯片,结合外围电路,通过软件程序实现多功能电子密码锁功能;
2、在没输入密码时显示万年历,并可调;
3、通过按键来确定输入密码,实现密码锁功能,正确输入密码后有开锁提示;
二、方案设计与论证
方案一:采用数字电路控制
用以74LS112双JK触发器构成的数字逻辑电路作为密码锁的核心控制,将密码保存在JK触发器中,与输入密码通过比较器比较,判断结果是否相符合[4]。采用数字电路设计的方案好处就是设计简单,但控制的准确性和灵活性差,故不采用。 方案二:采用以单片机为核心的控制方案
选用单片机作为系统的核心部件,实现控制与处理的功能。单片机具有资源丰富、速度快、编程容易等优点。利用单片机内部的随机存储器(RAM)和只读存储器(ROM)及其引脚资源,外接液晶显示(LCD),键盘输入等实现数据的处理传输和显示功能,基本上能实现设计指标。
因此综合考虑,本系统采用方案二。
三、硬件电路设计
本设计主要由单片机、矩阵键盘、独立按键、液晶显示器等部分组成。其中矩阵键盘用于输入数字密码,独立按键用于实现可调万年历。由用户通过连接单片机的矩阵键盘输入密码,后经过单片机对用户输入的密码与自己保存的密码进行对比,从而判断密码是否正确,然后控制引脚的高低电平传到开锁电路或者报警电路控制开锁还是报警,实际使用时只要将单片机的负载由继电器换成电子密码锁的电磁铁吸合线圈即可。系统整体框图如图3-1所示。
键盘输入模块 复位电路 独立按键 STC89C52 显示模块 开锁电路 图3-1 系统结构框图
各模块功能如下:
1.键盘输入模块:分为密码输入按键与几个功能按键,用于完成密码锁输入功能。 2.显示模块:用于完成对系统状态显示及操作提示功能。 3.复位电路:完成系统的复位。
4.独立键盘:用于完成可调万年历功能。
6.开锁电路:应用继电器及发光二极管模拟开锁,完成开锁及开锁提示。 (一)、各个模块设计: 1、复位电路模块:
该电路上电单片机自动复位,按下按键手动复位。
2、晶振电路模块:
3、开关电路模块:
4、矩阵键盘电路模块:
用P1口组成4*4的矩阵键盘,各键的定义一次为:0、1、2、3、4、5、6、7、8、9、*、#、enetr(程序中设计只有该键按下才能进行密码输入等操作)、del(当密码按错时可以按下该键删除)、unclock(解锁键,即三次密码都错了只能按下它进行解锁)。 5、独立按键模块:
Tiao是位功能选择,通过选择位来决定万年历的调整,+1、-1是调节功能键。
5、液晶1602显示电路模块:
6、继电器电路模块:
6、原理图
7、PCB图
四、软件设计
总程序流程图如下:
开始 初始化 N Tiao按下否? Y Enter按下否? Y 输入密码 N N 第几次按下? Y 位选择 N OK! “+”功能键按下否 密码输入错误? Y N Y 被调数加一 3秒到否 N Y N “-”功能键按下否 Y 被调数减一 第八次按下 显示调后万年历 结束
键功能程序流程图如下图所示:
N Y N Y 设置程序 N Y Y 键功能程序 键值=0~9? 密码输入程序 键值=开锁? 开锁程序 键值=设置? 键值=确认?
N 确认程序 返回
开锁程序流程图如下图所示:
输入密码
开锁流程图
Y 返回 开锁成功 N 输入密码正确? 报警程序 确认程序 按开锁键 LCD初始化 开锁
程序清单见附录
六、仿真过程与仿真结果
上电初始状态仿真图:
按下独立按键Tiao后,选择位功能仿真图如下:
调整完时间之后:
请输入密码,程序实时扫描矩阵键盘的输入:
密码输入正确的仿真效果图,继电器处于工作状态:
密码输入正确后3秒钟跳回时间显示:
密码输入出错时仿真效果图:
六、安装与调试
经过腐蚀制板、焊接元件,再上电调试各模块电路都能按照仿真里的正常工作。 初始上电的时候
LCD1602 上电显示:设置正常 其他状态都能正常显示 4*4矩阵键盘 独立按键 开锁驱动电路(8550驱动继电器) 各功能键正常工作,密码键正常输入 各功能键能正常工作 有开锁信号时继电器正常动作 七、结论与心得
八、参考文献
[1] 叶启明.单片机制作的新型安全密码锁[J].家庭电子.2000,第六期:24-27
[2] 郭海英.基于单片机的电子安全密码锁的设计[J].现代电子技术.2005,第三期:57-58 [3] 李明喜.新型电子密码锁的设计[J].机电产品开发与创新.2004,第八期:77-79 [4] 祖龙起.刘仁杰.孙乃凌.一种新颖的电子密码锁[J].电子世界.2001,第六期:88-90
[5] 李明喜.新型电子密码锁的设计[J].机电产品开发与创新.2004,第五期:22-28 [6] 长沙太阳人电子有限公司通用型1602液晶PDF资料. [7] 周立功单片机开发网. 附1:
程序清单如下: #include #define uchar unsigned char #define uint unsigned int #define no_key 20 //无按键时的返回值 sbit rs=P3^0; sbit rw=P3^1;//lcd数据命令选择端 sbit e=P3^2;//lcd使能信号端 sbit key1=P3^3; sbit key2=P3^4; sbit key3=P3^5; sbit key=P3^7;//开锁信号控制端 sbit enter=P1^3;//该键按下后才能进行输入密码等操作 uchar conflag,keyflag=3; uchar jz=20;//键值变量 uchar temp1;//用此变量来存储键盘扫描的返回值,以便判断是否有键按下 uchar code table0[6]={3,0,3,0,3,0};//初始密码 uchar code table9[6]={3,1,3,1,3,1};//初始密码 uchar code table1[]=\"2011-05-07 w-6\"; uchar code table2[]=\" Time-03:03:00\"; uchar code table3[]=\"Enter please:\"; uchar code table4[]=\"OK!\"; uchar code table6[]=\"ERRO!\"; uchar code table7[]=\"Enter again:\"; uchar code table8[]=\"LOCKED!\"; uchar code table10[]=\"UNLOCKED!\"; uchar code table11[]=\"Can't open!\"; unsigned char m; uchar num,t0,keynum,hour,min,sec,year,month,day,week; uchar table5[6];//定义输入密码值存储数组 /************************************** **函数名称:delay **函数功能:软件延时,时间为z毫秒 **入口参数:z延时控制值,值越大,延时越长 **出口参数:无 ***************************************/ void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } /************************************** **函数名称:write_com **函数功能:1602写命令函数,可以用此函数写不同的指令 **入口参数:com **出口参数:无 ***************************************/ void write_com(uchar com) { rs=0; rw=0; e=0; P2=com; delay(5); e=1; delay(5); e=0; } /************************************** **函数名称:write_date **函数功能:1602写数据函数,可以用此函数写不同的数据,程序对应的硬件1602的数据口为P2口 **入口参数:date **出口参数:无 ***************************************/ void write_date(uchar date) { rs=1; rw=0; e=0; P2=date; delay(5); e=1; delay(5); e=0; } /*显示位*/ void write_week(uchar dte) { uchar shi,ge; shi=dte/10; ge=dte%10; write_com(0x80+13); write_date(0x30+ge); } void write_clock(uchar add,uchar dat) { uchar first,second; second=dat/10; first=dat%10; write_com(0x80+0x40+add); write_date(0x30+second); write_com(0x80+0x40+add+1); write_date(0x30+first); } void write_nyr(uchar add,uchar dte) { uchar shi,ge; shi=dte/10; ge=dte%10; write_com(0x80+add); delay(5); write_date(0x30+shi); write_com(0x80+add+1); delay(5); write_date(0x30+ge); } /************************************** **函数名称:init **函数功能:初始化函数 **入口参数:无 **出口参数:无 ***************************************/ void init() { uchar hour=3,min=3,year=11,month=5,day=7,week=6; uchar num; e=0; write_com(0x38);//设置16*2显示,5*7点阵,8位数据接口 write_com(0x0c);//开显示,不显示光标 write_com(0x06);//当读或写一个字符后地址指针加1,且光标加1 write_com(0x01);//显示清屏:数据指针、所有显示清0 write_com(0x80);//设置数据地址指针 for(num=0;num<15;num++) { write_date(table1[num]);//LCD显示\"初始设置时间\"; delay(5); } write_com(0x80+0x40); for(num=0;num<14;num++) { write_date(table2[num]);//LCD显示\"初始设置时间\"; delay(5); } /*定时器初始化*/ TMOD=0x01; TH0=(65536-50000)/256; TL0=(65536-50000)%256; EA=1; ET0=1; TR0=1; while(1) { if(key1==0) //时钟设置//key1按下 { delay(5); if(key1==0) //key1真的按下了 { keynum++; while(!key1) //去键抖 TR0=0; //时钟暂停 if(keynum==1) //key1按下第一次 { write_com(0x80+0x40+13); write_com(0x0f); } if(keynum==2) //key1按下第二次 { write_com(0x80+0x40+10); } if(keynum==3) //key1按下第三次 { write_com(0x80+0x40+7); } if(keynum==4) //key1按下第三次 { write_com(0x80+13); } if(keynum==5) //key1按下第三次 { write_com(0x80+9); } if(keynum==6) //key1按下第三次 { write_com(0x80+6); } if(keynum==7) //key1按下第三次 { write_com(0x80+3); } if(keynum==8) //key1按下第四次 { keynum=0; //按键次数清零 write_com(0x0c); TR0=1; //继续运行时钟 } } } /*按键加*/ if(keynum!=0) { if(key2==0) { delay(80); if(key2==0) { while(!key2); if(keynum==1) { sec++; if(sec==60) sec=0; write_clock(12,sec); write_com(0x80+0x40+13); } if(keynum==2) { min++; if(min==60) min=0; write_clock(9,min); write_com(0x80+0x40+10); } if(keynum==3) { hour++; if(hour==24) hour=0; write_clock(6,hour); write_com(0x80+0x40+7); } if(keynum==4) { week++; if(week==8) week=1; write_week(week); write_com(0x80+13); } if(keynum==5) { day++; if(month==1||month==3||month==5||month==7||month==8||month==10||month==12) { if(day==32) day=1; } else if(month==2) //注意这里没有考虑闰年 { if(day==29) day=1; } else { if(day==31) day=1; } write_nyr(8,day); write_com(0x80+9); } if(keynum==6) { month++; if(month==13) month=1; write_nyr(5,month); write_com(0x80+6); } if(keynum==7) { year++; if(year==99) year=0; write_nyr(2,year); write_com(0x80+3); } } } /*按键减*/ if(key3==0) { delay(80); if(key3==0) { while(!key3); if(keynum==1) { sec--; if(sec==-1) sec=59; write_clock(12,sec); write_com(0x80+0x40+13); } if(keynum==2) { min--; if(min==-1) min=59; write_clock(9,min); write_com(0x80+0x40+10); } if(keynum==3) { hour--; if(hour==-1) hour=23; write_clock(6,hour); write_com(0x80+0x40+7); } if(keynum==4) { week--; if(week==0) week=7; write_week(week); write_com(0x80+13); } if(keynum==5) { day--; if(month==1||month==3||month==5||month==7||month==8||month==10||month==12) { if(day==0) month=31; } else if(month==2) //注意这里没有考虑闰年 { if(day==0) day=28; } else { if(day==0) day=30; } write_nyr(8,day); write_com(0x80+9); } if(keynum==6) { month--; if(month==0) month=12; write_nyr(5,month); write_com(0x80+6); } if(keynum==7) { year--; if(year==-1) year=99; write_nyr(2,year); write_com(0x80+3); } } } } P1=1<<4|1<<0|1<<1|1<<2|1<<3|1<<5|1<<6|0<<7; if(enter==0)break; } /*检测Enter(P1.3)键是否按下,只有该键按下才能进行输入密码等操作*/ P1=0<<4|1<<0|1<<1|1<<2|1<<3|1<<5|1<<6|1<<7; while(enter); if(enter==0) { delay(5); if(enter==0) { TR0=0; write_com(0x01);//显示清屏:数据指针、所有显示清0 write_com(0x80+0x02);//设置数据地址指针 for(num=0;num<13;num++) { write_date(table3[num]);//LCD显示“Enter please:” delay(5); } } while(!enter);//判断按键是否释放 delay(5); while(!enter); } P1=0xff; } /************************************** **函数名称:keyscan **函数功能:3*4键盘扫描 **入口参数:无 **出口参数:jz ***************************************/ uchar keyscan() { uchar temp; P1=0xfe;//第一行扫描 temp=P1; temp=temp&0xf0; while(temp!=0xf0) { } delay(5); temp=P1; temp=temp&0xf0; while(temp!=0xf0) { temp=P1; switch(temp) { case 0xee:jz=0; break; case 0xde:jz=1; break; case 0xbe:jz=2; break; case 0x7e:jz=3; break; } while(temp!=0xf0) { temp=P1; temp=temp&0xf0; } } P1=0xfd;//第二行扫描 temp=P1; temp=temp&0xf0; while(temp!=0xf0) { delay(5); temp=P1; temp=temp&0xf0; while(temp!=0xf0) { temp=P1; switch(temp) { case 0xed:jz=4; break; case 0xdd:jz=5; break; case 0xbd:jz=6; break; return jz; } case 0x7d:jz=7; break; } while(temp!=0xf0) { temp=P1; temp=temp&0xf0; } } } P1=0xfb;//第三行扫描 temp=P1; temp=temp&0xf0; while(temp!=0xf0) { delay(5); temp=P1; temp=temp&0xf0; while(temp!=0xf0) { temp=P1; switch(temp) { case 0xeb:jz=8; break; case 0xdb:jz=9; break; case 0xbb:jz='*'; break; case 0x7b:jz='#'; break; } while(temp!=0xf0) { temp=P1; temp=temp&0xf0; } } } /************************************** **函数名称:codein **函数功能:完成密码输入,并判断密码是否正确 **入口参数:无 **出口参数:无 ***************************************/ void codein() { uchar t=0; write_com(0x80+0x40+0x02);//重新设置LCD数据地址指针 for(t=0;t<6;t++) { temp1=keyscan(); while(temp1==no_key)//若相等则此时没有键按下 { P1=0xdf;//判断是否要删除输入的密码 if(enter==0) { delay(5); if(enter==0) { write_com(0x80+0x41+t); //确定删除对象 write_date(' '); //显示空格即为删除 t--; } while(!enter);//判断按键是否释放 delay(5); while(!enter); } // P1=0xff temp1=keyscan();//继续扫描按键直至有键按下 } table5[t]=temp1;//实时保存输入密码值 write_com(0x80+0x41+t); //重新设置数据地址指针 write_date('*');//LCD显示“******” delay(5); jz=20; } t=0; for(t=0;t<6;t++) { if(table5[t]!=table0[t])//对数组中的内容进行逐一比较,一旦有数据不对马上退出循环 { break; } } if(t==6)//要是条件退出的话说明六个数全对密码 { conflag=1; // 进行标志密码正确 } } /************************************** **函数名称:codeout **函数功能:根据密码输入正确与否作出相应的反应 **入口参数:无 **出口参数:无 ***************************************/ void codeout() { uchar t; if(conflag) { t=0; write_com(0x01);//显示清屏:数据指针、所有显示清0 write_com(0x80+0x07);//设置数据地址指针 for(t=0;t<3;t++) { write_date(table4[t]);//LCD显示“OK!” delay(5); } key=0; while(1); } if(!conflag) { keyflag--; t=0; write_com(0x01);//显示清屏:数据指针、所有显示清0 write_com(0x80+0x05);//设置数据地址指针 for(t=0;t<5;t++) { write_date(table6[t]);//LCD显示“ERRO!” delay(5); } write_com(0x01);//显示清屏:数据指针、所有显示清0 write_com(0x80+0x02);//设置数据地址指针 for(t=0;t<12;t++) { write_date(table7[t]);//LCD显示“Enter again:” delay(5); } } } /************************************** **函数名称:codeen **函数功能:当密码输入错误次数达到3次时,要按下解锁键,输入万能密码,此函数能判断万能密码正确与否并做出相应反应 **入口参数:无 **出口参数:无 ***************************************/ void codeen() { uchar t=0; write_com(0x80+0x40+0x02);//重新设置LCD数据地址指针 for(t=0;t<6;t++) { temp1=keyscan(); while(temp1==no_key)//若相等则此时没有键按下 { //P1=0xdf; P1=0<<5|1<<0|1<<1|1<<2|1<<3|1<<4|1<<6|1<<7; if(enter==0) { delay(5); if(enter==0) { write_com(0x80+0x41+t); //确定删除对象 write_date(' '); //显示空格即为删除 t--; } while(!enter);//判断按键是否释放 delay(5); while(!enter); } P1=0xff; temp1=keyscan();//继续扫描按键直至有键按下 } table5[t]=temp1;//实时保存输入密码值 write_com(0x80+0x41+t); //重新设置数据地址指针 write_date('*');//LCD显示“******” delay(5); jz=20; } t=0; for(t=0;t<6;t++) { if(table5[t]!=table9[t])//对数组中的内容进行逐一比较,一旦有数据不对马上退出循环 { break; } } if(t==6)//要是条件退出的话说明六个数全对密码 { t=0; write_com(0x01);//显示清屏:数据指针、所有显示清0 write_com(0x80+0x03);//设置数据地址指针 for(t=0;t<9;t++) { write_date(table10[t]);//LCD显示“UNLOCKED!” delay(5); } while(1) key=0; } else { t=0; write_com(0x01);//显示清屏:数据指针、所有显示清0 write_com(0x80+0x03);//设置数据地址指针 for(t=0;t<11;t++) { write_date(table11[t]);//LCD显示“Can't open!” delay(5); } while(1) key=1; } } void main() { uchar i=0; uchar j=0; init(); while(keyflag) { codein(); codeout(); } write_com(0x01);//显示清屏:数据指针、所有显示清0 write_com(0x80+0x04);//设置数据地址指针 for(i=0;i<7;i++) { write_date(table8[i]);//LCD显示“LOCKED!” delay(5); } while(1) { P1=0xbf; //判断解锁键是否按下 if(enter==0) { delay(5); if(enter==0) { write_com(0x01);//显示清屏:数据指针、所有显示清0 write_com(0x80+0x02);//设置数据地址指针 for(i=0;i<13;i++) { write_date(table3[i]);//LCD显示“Seeting code:” delay(5); } } while(!enter);//判断按键是否释放 delay(5); while(!enter); P1=0xff; break; } key=1; } codeen(); } /*定时器中断*/ void timer0() interrupt 1 { TMOD=0x01; TH0=(65536-50000)/256; TL0=(65536-50000)%256; t0++; if(t0==20) //1秒到清零 { t0=0; sec++; if(sec==60) //1分钟到清零 { sec=0; min++; if(min==60) { min=0; hour++; if(hour==24) { week++; if(week==8) { week=1; } write_week(week); } if(hour==24) { hour=0; day++; if(day==31) { day=1; month++; if(month==13) { month=1; year++; if(year==100) { year=0; } write_nyr(2,year); } write_nyr(5,month); } write_nyr(8,day); } write_clock(6,hour); } write_clock(9,min); } write_clock(12,sec); } } 因篇幅问题不能全部显示,请点此查看更多更全内容