电子密码锁设计.docx
《电子密码锁设计.docx》由会员分享,可在线阅读,更多相关《电子密码锁设计.docx(31页珍藏版)》请在冰豆网上搜索。
电子密码锁设计
成绩评定表
学生姓名
班级学号
专业
计算机科学与技术
课程设计题目
电子密码锁
评
语
组长签字:
成绩
日期
2013年1月12日
课程设计任务书
学院
信息科学与工程学院
专业
计算机科学与技术
学生姓名
班级学号
课程设计题目
电子密码锁设计
实践教学要求与任务:
1.学习Proteus仿真系统下的原理图设计方法和系统仿真调试方法;
2.学习使用Protel99SE软件绘制电路原理图和线路版图;
3.掌握简单的51单片机应用系统的软硬件设计方法;
4.在Keil51开发环境下,采用51汇编语言或C51语言编写实现程序。
具体任务如下:
(1)通过检索、查资料和研究学习,设计应用系统原理图;
(2)编写电子密码锁应用系统程序;
(3)软硬件仿真调试,实现应用系统设计目标;
(4)写出设计总结报告。
工作计划与进度安排:
第16—19周:
布置课程设计任务,查阅资料,分组设计原理图,编写程序代码。
第20周:
系统仿真调试,验收,答辩,编写课程设计报告。
指导教师:
2013年1月12日
专业负责人:
2013年1月12日
学院教学副院长:
2013年1月12日
目录
1题目设计的要求4
2系统的组成及工作原理4
2.2主控制器4
2.3LCD1602的指令格式5
2.424C04EEPROM存储器芯片6
2.4.1SCL串行时钟7
2.4.2SDA串行数据/地址7
2.4.3A1,A2器件地址输入端7
2.4.4WP写保护7
3Protel99SE下的线路原理图的设计9
4系统软件设计10
4.1程序流程10
4.1.1主程序流程10
4.1.2子程序流程图10
4.2Uvision4开发平台下的程序代码11
5系统仿真调试20
5.1Proteus下的仿真原理图设计20
5.2程序代码链接与仿真运行过程21
5.3仿真运行结果22
6总结与心得24
7参考资料24
1题目设计的要求
利用51单片机和1602字符LCD设计电子密码锁,实现6位密码的设置,修改,输入,状态显示等功能。
完成以下设计环节:
1)使用protel99SE开发工具,设计电路原理图
2)使用Uvision4开发平台,采用C语言或汇编语言设计软件程序。
3)使用PROTEUS仿真软件,设计仿真原理图并运行软件程序,完成系统仿真。
2系统的组成及工作原理
2.1系统的组成及工作原理
AT89C51,1602字符LCD,EEPROM存储器芯片24C04A,respack-8排阻,LED黄色提示灯,发声器。
以AT89C51为主控芯片作为密码数据的传输;LCD1602为显示屏,用于提示用户输入输出信息;显示利用单片机的读写控制,扩展电路等功能部件设计电子密码锁。
(1)系统设置6位密码,密码通过键盘输入,若密码正确,则将锁打开。
(2)密码由用户自己设定,在开锁状态下,用户可自行修改密码。
(3)具有自动报警功能,系统工作时,用户通过按键输入6位密码,若密码不正确,则要求重新输入密码,重新输入密码的次数不能超过3次,若三次输入的密码都不正确,则发出报警信号。
2.2主控制器
AT89C51是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM—FalshProgrammableandErasableReadOnlyMemory)的低电压,高性能CMOS8位微处理器,俗称单片机。
AT89C2051是一种带2K字节闪烁可编程可擦除只读存储器的单片机。
单片机的可擦除只读存储器可以反复擦除100次。
该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,AT89C2051是它的一种精简版本。
AT89C单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
T89C2051的一些特殊功能口如下所示:
p1口引脚:
reshuffle功能
p1.0:
T2(定时器T2外部输入)
p3口引脚
P3.0:
RXD(串行出入口)
P3.1:
TXD(串行输出口)
P3.2:
INTO(外部中断0)
P3.4:
INT1(外部中断1)
P3.5:
T0(定时器1外部输入)
P3.6:
WR(外部数据存储器写选通)
P3.7:
RD(外部数据存储器读选通)
AT89C51引脚图如图2.1
图2.1
2.3LCD1602的指令格式
1.清屏指令
功能:
<1>清除液晶显示器,即将DDRAM的内容全部填入"空白"的ASCII码20H;
<2>光标归位,即将光标撤回液晶显示屏的左上方;
<3>将地址计数器(AC)的值设为0。
2.光标归位指令
功能:
<1>把光标撤回到显示器的左上方;
<2>把地址计数器(AC)的值设置为0;
<3>保持DDRAM的内容不变。
3.进入模式设置指令
功能:
设定每次定入1位数据后光标的移位方向,并且设定每次写入的一个字符是否移动。
参数设定的情况如下所示:
位名设置I/D0=写入新数据后光标左移1=写入新数据后光标右移S0=写入新数据后显示屏不移动1=写入新数据后显示屏整体右移1个字符
4.显示开关控制指令
功能:
控制显示器开/关、光标显示/关闭以及光标是否闪烁。
参数设定的情况如下:
位名设置D0=显示功能关1=显示功能开C0=无光标1=有光标B0=光标闪烁1=光标不闪烁
5.设定显示屏或光标移动方向指令
功能:
使光标移位或使整个显示屏幕移位。
参数设定的情况如下:
S/CR/L设定情况00光标左移1格,且AC值减101光标右移1格,且AC值加110显示器上字符全部左移一格,但光标不动11显示器上字符全部右移一格,但光标不动
6.功能设定指令
功能:
设定数据总线位数、显示的行数及字型。
参数设定的情况如下:
位名设置DL0=数据总线为4位1=数据总线为8位N0=显示1行1=显示2行F0=5×7点阵/每字符1=5×10点阵/每字符
7.设定CGRAM地址指令
功能:
设定下一个要存入数据的CGRAM的地址。
8.设定DDRAM地址指令
功能:
设定下一个要存入数据的CGRAM的地址。
9.读取忙信号或AC地址指令
功能:
<1>读取忙碌信号BF的内容,BF=1表示液晶显示器忙,暂时无法接收单片机送来的数据或指令;当BF=0时,液晶显示器可以接收单片机送来的数据或指令;
<2>读取地址计数器(AC)的内容。
10.数据写入DDRAM或CGRAM指令一览
功能:
<1>将字符码写入DDRAM,以使液晶显示屏显示出相对应的字符;
<2>将使用者自己设计的图形存入CGRAM。
11.从CGRAM或DDRAM读出数据的指令一览
功能:
读取DDRAM或CGRAM中的内容。
2.424C04EEPROM存储器芯片
本设计中为了在系统掉电时能够保存系统的设置密码,使用了具有IC总线接口的E2PROM的24C04芯片保存密码锁的密码。
仿真器件符号如图34.1所示:
图34.1
2.4.1SCL串行时钟
AT24C04串行时钟输入管脚用于产生器件所有数据发送或接受的时钟,这是一个输入管脚。
2.4.2SDA串行数据/地址
AT24C04双向串行数据/地址管脚用于器件所有数据的发送或接受,SDA是一个开漏输出或集电极开路输出进行线或(wire-OR)。
2.4.3A1,A2器件地址输入端
这些输入脚用于多个级联时设置器件地址,当这些脚悬空默认值为0.当使用AT24C02时最大可级联8个器件,如果只有一个AT24C04总线寻址,这两个地址输入脚(A1,A2)可悬空或链接到Vss,如果只有一个AT24C04总线寻址这两个地址输入脚(A1,A2)必须连接到Vss。
2.4.4WP写保护
如果WP连接到Vcc,所有的内容都被写保护只能读。
当WP管脚连接到Vss或悬空容许器件进行正常的读/写操作。
2.5矩阵键盘的设计
密码的输入用4×4键盘来实现,由0~9数字和开锁,上锁,输入新密码,保存新密码,重新输入的功能键组成,还有一个按键未定义。
在这种行列式矩阵键盘编码的单片机系统中,键盘处理程序首先执行等待按键并确认有无按键按下的程序段,还要对按键进行消抖处理。
当确认有按键按下后,就要识别是哪一个按键被按下。
本次设计使用的是线反转法。
给行线置为0x0f,给列线置为0xf0,再将行列进行逻辑或结果为0xff,当有按键按下时相应的按键位行列均为0,行列逻辑或不为0xff,由此可利用行列逻辑或后的值是否为0xff来判断是否有按键按下。
再根据扫描结果判断按下键的位置。
给相应的按键赋值即可实现数字键和功能键。
对功能键进行相应的软件编程即可实现按键功能。
若有按键被按下时,就将该按键译码出来,本设计采用双重循环做计数编号,当某一按键按下时,其按键编号便是计数编号,有关按键编号,扫描信号及读取按键数据返回码整理如表4。
编号
按键数据输入码
P1.7P1.6P1.5P1.4
扫描输出信号
P1.3P1.2P1.1P1.0
所侦测的按键
0
1110
1110
K0键
1
1101
1110
K1键
2
1011
1110
K2键
3
0111
1110
K3键
4
1110
1101
K4键
5
1101
1101
K5键
6
1011
1101
K6键
7
0111
1101
K7键
8
1110
1011
K8键
9
1101
1011
K9键
10
1011
1011
K10键
11
0111
1011
K11键
表4
数码管显示部分如图2.5
图2.5
3Protel99SE下的线路原理图的设计
图4.1
4系统软件设计
4.1程序流程
4.1.1主程序流程
图51.1
4.1.2子程序流程图
(1)键盘扫描流程图,如图51.2
图51.2图51.3
(2)开锁子程序流程图,如图51.3
(3)上锁子程序流程图,如图51.4
图51.4图51.5
(4)输入新密码子程序流程图,如图51.5
(5)保存新密码子程序流程图,如图51.6
4.2Uvision4开发平台下的程序代码
#include
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineLCDIOP0
#definedelay4us()_nop_();_nop_();_nop_();_nop_();
ucharbuffer[6]={0};
sbitsda=P3^3;
sbitscl=P3^2;
sbitbeep=P3^7;
bitflag=0,aa;//用户蹲渊义定时溢出标志位
ucharDSY_BUFFER[16]="";
ucharDSY_BUFFER1[16]="";
ucharUserpassword[6]={0};
sbitrs=P2^0;
sbitrd=P2^1;
sbitlcden=P2^2;
sbitled=P2^7;
ucharcodetable2[]="654321";
ucharcodetable[]="YourPassword...";
voiddelayms(uintz)
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
voiddelay()//短延时,两个机器周期,做总线的延时用
{;;}
voidwrite_com(ucharcom)
{
rs=0;
rd=0;
lcden=0;
P0=com;
delayms(3);
lcden=1;
delayms(3);
lcden=0;
}
voidwrite_date(uchardate)
{
rs=1;
rd=0;
lcden=0;
P0=date;
delayms(3);
lcden=1;
delayms(3);
lcden=0;
}
voidDisplay_String(uchar*p,ucharcom)
{uchari;
write_com(com);
for(i=0;i<16;i++)
{
write_date(p[i]);
}
}
voidinit_lcd()
{
lcden=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
Display_String(table,0x80);
Display_String("LockOK!
",0xc0);
}
voidstart()
{
sda=1;
scl=1;
delay4us();
sda=0;
delay4us();
scl=0;
}
voidstop()
{
sda=0;
scl=1;
delay4us();
sda=1;
delay4us();
scl=0;
}
voidinit()//初始化
{
sda=1;
delay();
scl=1;
delay();
}
voidack()
{
sda=0;
scl=1;
delay4us();
scl=0;
sda=1;
}
voidnoack()
{
sda=1;
scl=1;
delay4us();
scl=0;
sda=0;
}
ucharrecbyte()
{
uchari,rd;
rd=0x00;
sda=1;
for(i=0;i<8;i++)
{
scl=1;
rd<<=1;
rd|=sda;
delay4us();
scl=0;
delay4us();
}
scl=0;
delay4us();
returnrd;
}
ucharsendbyte(ucharwd)
{
uchari;
bitack0;
for(i=0;i<8;i++)
{
sda=(bit)(wd&0x80);
_nop_();
_nop_();
scl=1;
delay4us();
scl=0;
wd<<=1;
}
delay4us();
sda=1;
scl=1;
delay4us();
ack0=!
sda;
scl=0;
delay4us();
returnack0;
}
ucharRecstring(ucharslave,ucharsubaddr,uchar*buffer,ucharn)
{
uchari;
start();
if(!
sendbyte(slave))return0;
if(!
sendbyte(subaddr))return0;
start();
if(!
sendbyte(slave+1))return0;
for(i=0;i{
buffer[i]=recbyte();
ack();
}
buffer[n-1]=recbyte();
noack();
stop();
return1;
}
ucharSendstring(ucharslave,ucharsubaddr,uchar*buffer,ucharn)
{
uchari;
start();
if(!
sendbyte(slave))return0;
if(!
sendbyte(subaddr))return0;
for(i=0;i{
if(!
sendbyte(buffer[i]))return0;
}
stop();
return1;
}
voidclear_password()
{uchari;
for(i=0;i<6;i++)
{
Userpassword[i]='';
}
for(i=0;i<16;i++)
{
DSY_BUFFER[i]='';
}
}
ucharKeys_Scan()
{
uchartemp,keynum;
P1=0x0F;
delayms(5);
temp=P1^0x0F;
switch(temp)
{
case1:
keynum=0;break;
case2:
keynum=1;break;
case4:
keynum=2;break;
case8:
keynum=3;break;
break;
}
P1=0xF0;
delayms(5);
temp=P1>>4^0x0F;
switch(temp)
{
case1:
keynum+=0;break;
case2:
keynum+=4;break;
case4:
keynum+=8;break;
case8:
keynum+=12;break;
break;
}
delayms(600);
returnkeynum;
}
voidmain()
{uchartemp,i=0,j=0,k=0,n;
ucharIS_valid_user;
beep=0;
init();
init_lcd();
delayms(5);
aa=Sendstring(0xa0,1,table2,6);
delayms(5);
aa=Recstring(0xa0,1,buffer,6);
delayms(10);
P1=0x0f;
while
(1)
{
if(P1!
=0x0f)
{
temp=Keys_Scan();
switch(temp)
{
case0:
case1:
case2:
case3:
case4:
case5:
case6:
case7:
case8:
case9:
if(i<=5)//密码限制在6位以内
{
Userpassword[i]=temp;
DSY_BUFFER[i]='*';
Display_String(DSY_BUFFER,0xc0);
i++;
}
break;
case10:
//按A键开锁
for(k=0;k<6;k++)
{
if(buffer[k]==(Userpassword[k]+48))
flag=1;
else
flag=0;
}
if(flag==1)
{flag=0;
i=0;
led=0;//点亮LED
clear_password();
Display_String("OPENOK!
",0xc0);
IS_valid_user=1;
j=0;
}
else
{
j++;
led=1;//关闭LED
clear_password();
Display_String("ERROR!
Havetry",0xc0);
write_com(0xcf);
write_date(0x30+j);
IS_valid_user=0;
}
i=0;
break;
case11:
//按B键上锁
led=1;
clear_password();
Display_String(table,0x80);
Display_String("LockOK!
",0xc0);
i=0;
IS_valid_user=0;
break;
case12:
//按C键设置新密码
//如果是合法用户则提示输入新密码
if(!
IS_valid_user)
{
i=0;
Display_String("Norights!
",0xc0);
delayms(1000);
Display_String("YourPassword...",0x80);
Display_String("LockOK!
",0xc0);
}
else
{
i=0;
Display_String("NewPassword:
",0x80);
Display_String("",0xc0);
}
break;
case13:
//按D键保存新密码
if(!
IS_valid_user)
{i=0;
Display_String("Norights!
",0xc0);
delayms(1000);
Display_String("YourPassword...",0x80);
Display_String("LockOK!
",0xc0);
}
else
{i=0;
init();
delayms(5);
for(k=0;k<6;k++)
{
Userpassword[k]=Userpassword[k]+48;
}
aa=Sendstring(0xa0,1,Userpassword,6);
delayms(5);
aa=Recstring(0xa0,1,buffer,6);
delayms(5);
clear_password();
Display_String(table,0x00);
Display_String("PasswordSaved!