接口技术课程设计报告.docx
《接口技术课程设计报告.docx》由会员分享,可在线阅读,更多相关《接口技术课程设计报告.docx(41页珍藏版)》请在冰豆网上搜索。
接口技术课程设计报告
接口技术课程设计报告
学号:
接口技术课程设计报告
题目:
基于单片机的电子密码锁设计
学院(系):
机械与电子工程学院
专业年级:
电信082
学生姓名:
指导教师:
完成日期:
2011年7月7日
成绩:
一、设计目的与要求
1、采用二个按键实现密码的输入功能,密码长度为6位。
2、当密码输入正确之后,锁就打开,如果输入的三次的密码不正确,就锁定按键3秒钟,同时发现报警声,3种后,才打开按键锁定功能。
3、开锁信号可用发光二极管指示。
二、硬件电路设计
2.1键盘电路设计
使用矩阵键盘,所以本设计就采用行列式键盘,同时也能减少键盘与单片机接口时所占用的I/O线的数目,在按键比较多的时候,通常采用这样方法。
其原理如图2.1
图2.1键盘电路
每一条水平(行线)与垂直线(列线)的交叉处不相通,而是通过一个按键来连通,利用这种行列式矩阵结构只需要N条行线和M条列线,即可组成具有N×M个按键的键盘。
按键功能见表2.1
按键
键名
功能说明
1-9键
数字键
输入密码
确定键
比较密码
返回键
退出开锁
重置键
密码重置
存储键
保存密码
表2.1按键功能
2.2LED显示电路
系统的显示采用串行显示的方式,只使用单片机的一个串行口,利用两个74HC573(U1、U2)分别驱动数码管发光显示数码和控制位选信号,就可以完成单片机的显示功能,显示电路的电路原理图如图2.2所示。
AT89C51的P0.0—P0.7分别接两个74HC573的D0—D7口,P2.0接U1的LE口,P2.1U2的LE口。
U1的Q0—Q7接LED的七段显示,U2的Q0—Q5接LED的位显示。
通过软件实现数字和位控制。
原理如图2.2
图2.2LED显示电路
2.3开锁电路
基于节省材料的原则,暂时用发光二极管代替电磁锁,绿色发光管亮,表示开锁;红色发光管亮,表示没有开锁。
蓝色发光管亮,表示开始密码重置功能。
黄色发光管亮,表示密码重置成功。
电路图如3.3所示。
图2.3开锁电路
2.4晶振电路与复位电路
图2.4晶振电路
2.524C02缓存器电路
图2.5复位电路
2.6报警电路
图2.6报警电路
三、软件流程及程序设计
3.1软件设计思路
电子密码锁工作的主要过程是LED数码管提示开始输入密码,通过键盘输入密码,同时LED显示密码输入情况,按下确认键后判断密码的正确性,作出开锁或报警处理。
当输入密码连续输入错误3次时,系统报警。
密码的设定,在此程序中密码是固定40H—45H中,假设预设的密码为"123456"共6位密码。
由于采用两个按键来完成密码的输入,那么其中一个按键为功能键,另一个按键为数字键。
在输入过程中,首先输入密码的长度,接着根据密码的长度输入密码的位数,直到所有长度的密码都已经输入完毕;或者输入确认功能键之后,才能完成密码的输入过程。
进入密码的判断比较处理状态并给出相应的处理过程。
3.2软件流程
开始
↓
系统初始化
↓
得到键按值keyval
↓
与存储器中密码对比
↓错误3次
密码正确显示0,绿灯亮,如果错误红灯亮→报警
↓
正确
↓
可以重置密码,蓝灯亮
↓
保存密码,黄灯亮,返回,重新登录
3.3主程序
voidmain()
{
uchari,keyval,k,times=0;
bitFlag=1,RUN=1,flag1=1,flag2=1;//标志位参数
LED_YELLOW=0;//黄灯
LED_BLUE=0;
SystemInit();
for(k=0;k<6;k++)
WriteSet(k,password[k]);//在24c08的地址2中写入数据sec
k=0;
while(RUN)
{
SDA=1;//SDA=1,SCL=1,使主从设备处于空闲状态
SCL=1;
keyval=keyscan();//扫描键盘
if(keyval==CANCEL)//取消键功能区,返回初始状态
{
k=0;
for(i=0;i<6;i++)
DisTemp[i]=0x7f;//初始化显示全8
flag1=1;//改密码按键标志位
flag2=1;
times=0;
}
if(keyval==OK)//确认键按键功能区
{
Flag=1;//先把比较标志位置1
for(i=0;i<6;i++)//把存储器中密码取出来,循环比较6个数值,如果有一个不等则最终Flag值为0
{
mima[i]=ReadSet(i);//在24c08的地址0-5中取出初始密码
Flag=Flag&&(keypassword[i]==mima[i]);//比较密码是否相等
}
if(Flag==0)//密码错误
{
LED_RED=1;
times++;//错误次数
for(i=0;i<10;i++)
DelayMs(50);//大致一秒
LED_RED=0;
for(i=0;i<6;i++)//密码错误延时1秒,继续显示6个8
DisTemp[i]=0x7f;
k=0;
}
if(Flag==1)//密码正确
{
LED_GREEN=1;//绿灯亮1秒
for(i=0;i<10;i++)
DelayMs(50);//大致一秒
LED_GREEN=0;
for(i=0;i<6;i++)
DisTemp[i]=0x3f;//密码正确显示000000
flag1=1;
while(flag1)//密码正确可以进行更改密码
{
keyval=keyscan();//扫描键盘
if(keyval==GAIMI)
{
LED_BLUE=1;
for(i=0;i<10;i++)
DelayMs(50);//大致一秒
LED_BLUE=0;
flag2=1;
k=0;
while(flag2)
{
keyval=keyscan();//扫描键盘
if((keyval!
=0xff)&&(keyval!
=OK)&&(keyval!
=CANCEL)&&(keyval!
=GAIMI)&&(keyval!
=SAVE))//数字输入
{
if(k<6)//得到6个输入数字//将输入的6个字符赋给密码参量数组
{
mima[k]=keyval;
DisTemp[k]=0x40;//各个数码管显示'-'
k++;
}
}
if(keyval==SAVE)//保存键按下后把新密码存入24c02
{
for(k=0;k<6;k++)
WriteSet(k,mima[k]);//在24c08的地址2中写入数据sec
LED_YELLOW=1;
for(i=0;i<10;i++)
DelayMs(50);//大致一秒
LED_YELLOW=0;
flag2=0;
flag1=0;
}
}
}
}
}
k=0;
}
if((keyval!
=0xff)&&(keyval!
=OK)&&(keyval!
=CANCEL)&&(keyval!
=GAIMI)&&(keyval!
=SAVE))
//按下非公能键表示是数字输入
{
if(k<6)//得到6个输入数字
{
keypassword[k]=keyval;//把6次按键值赋给参量数组
DisTemp[k]=0x71;//对应数码管显示F
k++;
}
}
if(times==3)//密码错误3次结束该循环
RUN=0;
}
DelayMs(500);
BEEP();
DelayMs(500);
BEEP();
DelayMs(500);
BEEP();
}
3.4各子程序
1.键盘扫描子程序
ucharkeyscan()
{
uchartempA,tempB,tempAB=0;
P3=0x0f;
if(P3!
=0x0f)
{
DelayMs(6);
if(P3!
=0x0f)
{
tempA=P3&0x0f;
P3=0xf0;
DelayUs(4);//稍微延时稳定数据
tempB=P3&0xf0;
tempAB=tempA|tempB;
}
while(P3!
=0xf0);//松手检测
}
switch(tempAB)
{
case0x00:
return0xff;
case0xee:
return1;
case0xde:
return2;
case0xbe:
return3;
case0x7e:
return4;
case0xed:
return5;
case0xdd:
return6;
case0xbd:
return7;
case0x7d:
return8;
case0xeb:
return9;
case0xdb:
return0;
case0xbb:
returnOK;
case0x7b:
returnCANCEL;
default:
return0xff;
}
}
2.LED显示子程序
voiddis_shuma(ucharweidat,ucharduandat)
{
DataPort=0xff;
LATCH2=1;
LATCH2=0;
DataPort=DisTemp[duandat];
LATCH1=1;
LATCH1=0;
DataPort=WeiMa[weidat];
LATCH2=1;
LATCH1=0;
}
3.晶振与报警电路子程序
voidDelayUs(uchart)
{
while(t--);
}
/*------------------------------------------------
mS延时函数,其值的范围是
0~255这里使用晶振12M,
大致1ms
------------------------------------------------*/
voidDelayMs(uinttt)
{
while(tt--)
{
DelayUs(245);
DelayUs(245);
}
}
voidBEEP()
{
uintm,n;
for(m=0;m<1000;m++)//P1.0脚发声提示
{
for(n=0;n<100;n++);//延时
beep=~beep;//取反输出到喇叭的信号
}
}
4.定时器0初始化程序
voidTimer0Init()
{
TMOD=0x01;
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
ET0=1;
EA=1;
TR0=1;
}
voidSystemInit()
{
Timer0Init();
P3=0x0f;
LED_GREEN=0;
LED_RED=0;
}
5.定时器中断子程序
voidTimer0_isr(void)interrupt1using1
{
staticucharcount=0;
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
switch(count)//数码管动态烧苗
{
case0:
dis_shuma(count,count);
count=1;
break;
case1:
dis_shuma(count,count);
count=2;
break;
case2:
dis_shuma(count,count);
count=3;
break;
case3:
dis_shuma(count,count);
count=4;
break;
case4:
dis_shuma(count,count);
count=5;
break;
case5:
dis_shuma(count,count);
count=0;
break;
default:
break;
}
}
6.AT24c02缓存器
/***************************************************
函数功能:
向AT24Cxx的当前地址写入数据
入口参数:
y(储存待写入的数据)
***************************************************/
//在调用此数据写入函数前需首先调用开始函数start(),所以SCL=0
voidWriteCurrent(unsignedchary)
{
unsignedchari;
for(i=0;i<8;i++)//循环移入8个位
{
SDA=(bit)(y&0x80);//通过按位“与”运算将最高位数据送到S
//因为传送时高位在前,低位在后
_nop_();//等待一个机器周期
SCL=1;//在SCL的上升沿将数据写入AT24Cxx
_nop_();//等待一个机器周期
_nop_();//等待一个机器周期
SCL=0;//将SCL重新置为低电平,以在SCL线形成传送数据所需的8个脉冲
y<<=1;//将y中的各二进位向左移一位
}
}
/***************************************************
函数功能:
向AT24Cxx中的指定地址写入数据
入口参数:
add(储存指定的地址);dat(储存待写入的数据)
***************************************************/
voidWriteSet(unsignedcharadd,unsignedchardat)
//在指定地址addr处写入数据WriteCurrent
{
start();//开始数据传递
WriteCurrent(OP_WRITE);//选择要操作的AT24Cxx芯片,并告知要对其写入数据
Ask();
WriteCurrent(add);//写入指定地址
Ask();
WriteCurrent(dat);//向当前地址(上面指定的地址)写入数据
Ask();
stop();//停止数据传递
DelayMs(4);//1个字节的写入周期为1ms,最好延时1ms以上
}
/***************************************************
函数功能:
从AT24Cxx中的当前地址读取数据
出口参数:
x(储存读出的数据)
***************************************************/
unsignedcharReadCurrent()
{
unsignedcharx;
start();//开始数据传递
WriteCurrent(OP_READ);//选择要操作的AT24Cxx芯片,并告知要读其数据
Ask();
x=ReadData();//将读取的数据存入x
stop();//停止数据传递
returnx;//返回读取的数据
}
/***************************************************
函数功能:
从AT24Cxx中的指定地址读取数据
入口参数:
set_addr
出口参数:
x
***************************************************/
unsignedcharReadSet(unsignedcharset_addr)
//在指定地址读取
{
start();//开始数据传递
WriteCurrent(OP_WRITE);//选择要操作的AT24Cxx芯片,并告知要对其写入数据
Ask();
WriteCurrent(set_addr);//写入指定地址
Ask();
return(ReadCurrent());//从指定地址读出数据并返回
}
四、系统调试及仿真
本次调试采用Protues软件仿真。
首先设计电子密码锁的源程序,源程序经过汇编后,生成的目标文件经过仿真调试。
初始LED显示如图4.1
图4.1LED初始化显示
由于程序中进行了加密,因此依次按下1,2,3,4,5,6后,LED显示如图4.2
图4.2LED数值显示
重置密码时,LED显示如图4.3
图4.3密码重置
当输入正确密码后,绿色二极管亮,表示密码正确开锁成功。
如图4.4
图4.4密码正确开锁
当输入错误密码后,红色二极管亮,表示密码错误开锁失败。
如图4.5
图4.5密码错误
当输入正确密码后,点击重置按钮是,蓝色二极管亮,表示可以进行密码重置。
如图4.6
图4.6密码重置
当重新输入密码后,点击存储按钮时,黄色二极管亮,表示密码重置成功。
如图4.7
图4.7密码重置成功
当连续三次输入错误密码后,键盘自动锁闭,蜂鸣器报警3s。
如图4.8
图4.8三次错误密码后报警
五、总结
在着手本次课程设计时,通过查阅网络与图书馆搜集到的资料,加上指导老师指点,结合生活中对密码锁的功能特性要求,设计出了这一套电子密码锁系统的主要硬件结构和软件结构,基本完成了课题。
不过由于了解的专业知识尚浅,对课题的研究经验的不足,使得在技术的解决与运用上显得粗糙了一些,特别是功能键的设定。
在设计的过程当中经历和克服了许多困难,暴露我们知识和经验不足的同时也积累了实践经验,检阅了大学所学的知识,使所学的知识得到复习和巩固。
通过这次毕业设计我学到了很多东西,复习了理论知识,特别是单片机外围电路模块电路设计及其应用编程;学会收集和处理资料的一些基本问题,提高获取新知识的能力、分析和解决问题的能力以及交流与合作的能力。
这次课程设计终于顺利完成了,在设计中遇到了很多编程问题,在同学的帮助下,终于一一解决。
非常感谢大家的帮助!
附录
源程序清单
/*
开始
↓
系统初始化
↓
得到键按值keyval
↓
与存储器中密码对比
↓错误3次
密码正确显示0,绿灯亮,如果错误红灯亮→报警
↓
正确
↓
可以重置密码,蓝灯亮
↓
保存密码,黄灯亮,返回,重新登录
*/
#include
#include//包含_nop_()函数定义的头文件
#defineucharunsignedchar
#defineuintunsignedint
#defineOK(uchar)11
#defineCANCEL(uchar)12
#defineGAIMI(uchar)13
#defineSAVE(uchar)14
#defineOP_READ0xa1//器件地址以及读取操作,0xa1即为10100001B
#defineOP_WRITE0xa0//器件地址以及写入操作,0xa1即为10100000B
sbitSCL=P1^1;//将串行时钟总线SCL位定义在为P3.4引脚
sbitSDA=P1^2;//将串行数据总线SDA位定义在为P3.5引脚
bitwrite=0;//写24C08的标志;
ucharcodepassword[6]={1,2,3,4,5,6};//可以更改此密码做多组测试
ucharmima[6];
ucharkeypassword[6];//输入的键盘密码
ucharcodeWeiMa[]={0xdf,0xef,0xf7,0xfb,0x7d,0xfe};//分别对应相应的数码管点亮,即位码
#defineDataPortP0//定义数据端口
sbitLATCH1=P2^0;//段锁存
sbitLATCH2=P2^1;//位锁存
sbitLED_RED=P2^2;//红灯
sbitLED_GREEN=P2^3;//绿灯
sbitLED_YELLOW=P2^5;//黄灯
sbitLED_BLUE=P2^4;//蓝灯
sbitbeep=P1^0;
ucharDisTemp[6]={0x7f,0x7f,0x7f,0x7f,0x7f,0x7f};//显示缓存F
/*------------------------------------------------
uS延时函数,0~255这里使用晶振12M,大致延时
长度如下T=(tx2+5)uS
------------------------------------------------*/
voidDelayUs(uchart)
{
while(t--);
}
/*------------------------------------------------
mS延时函数,其值的范围是
0~255这里使用晶振12M,
大致1ms
------------------------------------------------*/
voidDelayMs(uinttt)
{
while(tt--)
{
DelayUs(245);
DelayUs(245);
}
}
voidBEEP()
{
uintm,n;
for(m=0;m<700;m++)//P1.0脚发声提示
{
for(n=0;n<100;n++);//延时
beep=~beep;//取反输出到喇叭的信号
}
}
/***************************************************
函数