课程设计.docx

上传人:b****5 文档编号:8525269 上传时间:2023-01-31 格式:DOCX 页数:24 大小:184.93KB
下载 相关 举报
课程设计.docx_第1页
第1页 / 共24页
课程设计.docx_第2页
第2页 / 共24页
课程设计.docx_第3页
第3页 / 共24页
课程设计.docx_第4页
第4页 / 共24页
课程设计.docx_第5页
第5页 / 共24页
点击查看更多>>
下载资源
资源描述

课程设计.docx

《课程设计.docx》由会员分享,可在线阅读,更多相关《课程设计.docx(24页珍藏版)》请在冰豆网上搜索。

课程设计.docx

课程设计

HUBEINORMALUNIVERSITY

单片机课程设计

CurriculumDesign

 

所在院系

教育信息与技术学院

专业名称

信息工程

班级

1002

题目

用24C04与1602LCD设计电子密码锁

指导教师

梅斌

成员

刘桂亮

完成时间

2013/1/6

一、题目:

可改密的六位电子密码锁

二、摘要:

单片机技术是智能化检测与控制领域应用非常普及并且具有很大潜力的技术。

论文阐述一个基于单片机的液晶显示电子密码锁的设计与实现。

系统采用美国Atmel公司的AT89S52单片机作为系统核心,液晶显示器LCD1602作为输出设备显示系统提示信息,4*4矩阵薄膜键盘作为输入设备,配合蜂鸣器、继电器等电路构成整个系统硬件;系统软件采用汇编语言编写。

设计的系统液晶显示,密码修改方便,具有报警、锁定等功能,使用便捷简单,符合住宅、办公用锁需求,具有一定的实用价值

三、任务和要求:

1要求电子密码锁设计

(1)熟悉电路,理解各个元件之间的控制流程。

(2)熟悉PROTEUS平台的运行环境。

(3)熟练掌握汇编语言,矩阵式键盘的实时控制操作。

(4)理解电子密码锁的工作原理。

2任务

(1)确定4×4键盘控制识别方案。

(2)分析电子密码锁的流程。

(3)画出程序流程图。

(4)分析电路图。

(5)编写代码。

(6)程序分析与调试。

四、设计思路:

该电路是一种采用以AT89C51为核心的单片机控制方案。

利用单片机灵活的编程设计和丰富的IO端口,及其控制的准确性,不但能实现基本的密码锁功能,还要根据实际需要添加调电存储、声光提示甚至增加遥控控制功能。

五、方案的确立:

为了实现密码的保密性,采用一个4×4的矩阵式键盘可以任意设置用户密码(1-16位长度),从而提高了密码的保密性。

设计采用一个超级密码,送电开机时,只要输入超级密码便可开门,这样可预防停电后再送电时无密码可用。

采用了1602液晶显示器来作为显示单元,提高了可读性,使用户对密码锁的运行情况一目了然。

6、总体设计方框图:

 

 

图2.1系统结构框图

7、各模块的功能:

1.键盘输入模块:

分为密码输入按键与几个功能按键,用于完成密码锁输入功能。

2.密码存储模块:

用于完成掉电存储功能,使修改的密码断电后仍能保存。

3.蜂鸣器报警电路:

用于完成输错密码时候的警报功能。

4.晶振电路:

用于单片机的起振。

5.复位电路:

完成系统的复位。

6.显示模块:

用于完成对系统状态显示及操作提示功能。

7.LED显示模块:

用于辅助报警与输入提示。

8.开锁电路:

应用继电器及发光二极管模拟开锁,完成开锁及开锁提示。

八、设计原理分析:

本系统外围电路包括键盘输入部分、密码存储部分、复位部分、显示部分、报警部分、开锁部分组成,根据实际情况键盘输入部分选择4×4矩阵键盘,显示部分选择字符型液晶显示LCD1602,密码存储部分选用内部存储器来完成。

其原理图如下:

9、单片机及其外围电路:

1.复位电路:

 

2.时钟电路:

时钟电路为单片机产生时序脉冲,单片机所有运算与控制过程都是在统一的时序脉冲的驱动下的进行的,如果单片机的时钟电路停止工作(晶振停振),那么单片机也就停止运行了。

当采用内部时钟时,连接方法如下图所示,在晶振引脚XTAL1(19脚)和XTAL2(18脚)引脚之间接入一个12MHZ晶振,两个引脚对地分别再接入一个电容即可产生所需的时钟信号,电容的容量一般在几十皮法,

3.矩阵键盘电路的设计

为了加强密码的保密性,采用一个4×4的矩阵式键盘可以任意设置用户密码(1-16位长度),从而提高了密码的保密性,同时也能减少与单片机接口时所占用的I/O口线的数目,节省了单片机的宝贵资源,在按键比较多的时候,通常采用这种方法。

每一行与每一列的交叉处不相同,而是通过一个按键来连通,利用这种行列式矩阵结构只需要N根行线与M根列线,即可组成具有N×M个按键的矩阵键盘。

在这种行列式矩阵键盘编码的单片机系统中,键盘处理程序首先执行等待按键并确认有无按键按下的程序段。

当确认有按键按下后,下一步就是要识别哪一个按键被按下。

对键的识别方法通常有两种:

一种是通用的组行扫描查询法;另一种是速度较快的线反转法。

此系统中,我们采用线反转法。

首先辨别键盘中有无按键被按下,在单片机I/O口向键盘送全扫描字,然后读入行线状态来判断。

具体方法是:

向行线输出全扫描字00H,把全部列线置成低电平,然后将列线的电平状态读入累加器A中。

如果有按键被按下,总会有一根行线电瓶被拉至低电平从而使行线不全为1。

判断键盘中哪一个按键被按下通常是通过将列线逐列至低电平后,检查行输入状态来实现的。

方法是:

依次给列线送低电平,然后检查所有行线状态,如果全为1,则所按下的按键不在此列;如果不全为1,则所按下的按键必在此列,而且是在与零电平行线相交的交点上的那个按键。

4.操作面板

10个数字键用来输入密码,另外6个功能键分别是:

更正、改密、锁定。

其中更正键的功能是当输入密码错误的时候,清除前面已经输入的数据,重新输入。

在输入密码状态下,0-9数字键为有效键,有时间和次数限制功能:

只有三次输入密码机会,每次限制在10秒内完成,输入密码有误或每次输入密码超时,则被认为是密码输入错误。

当3次输入都错误时,程序将返回起始状态。

密码输入正确后,继电器吸合,表示锁被打开。

在密码输入正确的情况下,程序进入查看密码和修改密码状态,。

按“改密”键进入重新设置密码状态,在输入密码时,如发现输入有误,可按“更正”键删除后,重新输入,按“锁定”确认后,程序退出修改密码状态。

5.液晶显示电路

本系统设计的显示电路是为了给使用者以提示而设置的为了达到界面友好的目的,显示部分由液晶显示器LCD1602取代普通的数码管完成。

开锁时,按下键盘上的开锁按键后,利用键盘上的数字键0-9输入密码,每按下一个数字键后在显示器上显示一个*,输入多少位就显示多少个*。

当密码输入完成时,如果输入的密码正确的话,LCD显示“OK”,绿灯亮起,单片机其中P3.0引脚会输出低电平,使三极管T2导通,电磁铁吸合,继电器开关跳转,电子密码锁被打开,如果密码不正确,LCD显示屏会显示“ERROR”,P3.0输出的是高电平,电子密码锁不能打开,同时红灯亮起。

通过LCD显示屏,可以清楚地判断出密码锁所处的状态。

图3.7显示器电路

显示器主要用于显示以下几个字符,指示如图所示。

A

S

W

O

R

D

 

P

S

 

图3.8(a)开机状态

 

D

 

 

等待输入状态

K

 

 

O

 

 

密码输入正确状态

R

O

R

 

E

 

R

 

密码输入错误及输入密码超时的提示

十.系统软件设计

系统的软件设计采用汇编语言编码。

设计方法是先用文本编辑器编写源码,然后用软件KeilC51编译,如果没有错误,可连接生成.HEX格式的文件(需事先在KeilC51中设置)。

如果有错误则无法连接,但可在生成的.OBJ文件中找到代码错误的地方,便于修改。

当然也可以直接在Keil中编码。

生成的HEX文件是记录文本行的ASCII文本文件,在HEX文件中,每一行是一个HEX记录,由十六进制数组成的机器码或者数据常量。

HEX文件经常被用于将程序或数据传输存储到ROM、EPROM,大多数编程器和模拟器使用HEX文件。

1.系统主程序

系统的主程序如图4-1所示。

由于用户在使用系统的过程中,可能在任何时刻按下任何按键,而程序都必须对此作出正确响应。

主程序流程图

2.初始化及按键识别

如图4.2,系统的初始化包括堆栈起始地址的设定,两个定时/计数器的设定,液晶显示模式的设定,密码缓冲区的初始化,一些自定义数据空间的初始化,蜂鸣器初始化发声等操作。

系统初始化并读取密码完成后,液晶显示"PASSWORDCONTROL",提示用户可以输入密码。

此时程序即不断测试按键,检查是否有按键被按下。

如果有,则进行按键识别;如果没有按键按下,或者按下的按键没有被识别,R3赋值0FFH,并跳转至按键测试。

实际程序运行时,绝大部分时间都在测试按键,等待用户输入。

初始化及按键识别流程图

3.开锁处理

首先LCD初始化,输入密码,密码正确则使开锁电路动作,继电器得电,开锁指示灯亮。

开锁流程如图所示。

开锁流程图

4.改密处理

如图,可以看出,改密键的处理流程跟开锁键类似,都需检查密码是否正确,错误的话,提示重新输入,只有输入密码正确才可以进行改密。

然后再按更改键,密码更改程序被调用,进而更改密码,此过程,LCD都会显示信息。

改密流程图

5.液晶显示子程序

液晶显示子程序在每次更新显示内容时都会被调用,其流程如图所示。

液晶显示子程序流程图

每次更新显示内容前,需清显示清空LCD原先的显示内容,清屏指令的指令码为01H,即将P0口赋值01H,然后写入指令寄存器IR。

LCD1602要显示的内容是根据其控制器内置的字符码表,事先列出要显示的ASCII字符串。

每次送一个字符的ASCII码入P0口,然后写入数据寄存器DR,最后将字符地址加一,LCD1602会将写入的ASCII码对应的字符依次显示出来。

由于显示字符串的长度不尽相同,约定每串字符以00H结尾;程序检测到字符码为00H时,即停止写入,返回。

LCD显示的内容在下次更新前会一直保持。

 

十一.源程序如下所示:

 

#include"delay.h"

/*------------------------------------------------

uS延时函数,含有输入参数unsignedchart,无返回值

unsignedchar是定义无符号字符变量,其值的范围是

0~255这里使用晶振12M,精确延时请使用汇编,大致延时

长度如下T=tx2+5uS

------------------------------------------------*/

voidDelayUs2x(unsignedchart)

{

while(--t);

}

/*------------------------------------------------

mS延时函数,含有输入参数unsignedchart,无返回值

unsignedchar是定义无符号字符变量,其值的范围是

0~255这里使用晶振12M,精确延时请使用汇编

------------------------------------------------*/

voidDelayMs(unsignedchart)

{

while(t--)

{

//大致延时1mS

DelayUs2x(245);

DelayUs2x(245);

}

}

 

#include"eeprom.h"

#include"delay.h"

voidStart(void)//I2开始

{

SDA=1;

SCL=1;

NOP4();

SDA=0;

NOP4();

SCL=0;

}

voidStop(void)//I2C停止

{

SDA=0;

SCL=0;

NOP4();

SCL=1;

NOP4();

SDA=1;

}

voidRACK(void)//读取应答

{

SDA=1;

NOP4();

SCL=1;

NOP4();

SCL=0;

}

voidNO_ACK(void)//发送非应答信号

{

SDA=1;

SCL=1;

NOP4();

SCL=0;

SDA=0;

}

voidWrite_A_Byte(ucharb)//写一个字节数据

{

uchari;

for(i=0;i<8;i++)

{

b<<=1;

SDA=CY;//CY进位程序状态字寄存器

_nop_();

SCL=1;

NOP4();

SCL=0;

}

RACK();

}

voidWrite_IIC(ucharaddr,uchardat)//向指写地地址写数据

{

Start();

Write_A_Byte(0xa0);

Write_A_Byte(addr);

Write_A_Byte(dat);

Stop();

DelayMs(10);

}

ucharRead_A_Byte(void)//读取一个字节

{

uchari,b;

for(i=0;i<8;i++)

{

SCL=1;

b<<=1;

b|=SDA;

SCL=0;

}

returnb;

}

ucharRead_Current(void)//从当前地址取数据

{

uchard;

Start();

Write_A_Byte(0xa1);

d=Read_A_Byte();

NO_ACK();

Stop();

returnd;

}

ucharRandom_Read(ucharaddr)//从任意地址读取数据

{

Start();

Write_A_Byte(0xa0);

Write_A_Byte(addr);

Stop();

returnRead_Current();

}

 

#include"key.h"

unsignedcharkey_scan()

{

unsignedchartemp,keyno;

P1=0x0f;

DelayMs

(1);

temp=P1^0x0f;

switch(temp)//纵行

{

case1:

keyno=1/*1*/;break;//第一纵行

case2:

keyno=2/*2*/;break;//第二纵行

case4:

keyno=3/*3*/;break;//第三纵行

case8:

keyno=4/*3*/;break;//第四纵行

}

P1=0xf0;

DelayMs

(1);

temp=P1>>4^0x0f;

switch(temp)

{//横行

case1:

keyno+=0/*A*/;break;//第一行横行

case2:

keyno+=4/*B*/;break;//第一行横行

case4:

keyno+=8/*C*/;break;//第一行横行

case8:

keyno+=12/*D*/;break;//第一行横行

}

P1=0x0f;

returnkeyno;

}

 

#include"LCD.H"

voidwrite_com(unsignedcharcom)//写命令

{

RS_CLR;

RW_CLR;

P0=com;

DelayMs(5);

EN_SET;

DelayMs(5);

EN_CLR;

}

voidwrite_data(unsignedchardate)//写一个字符

{

RS_SET;

RW_CLR;

P0=date;

DelayMs(5);

EN_SET;

DelayMs(5);

EN_CLR;

}

voidinit()//初始化

{

write_com(0x38);

write_com(0x0c);

write_com(0x06);

write_com(0x01);

}

/*------------------------------------------------

写入字符串函数

------------------------------------------------*/

voidLCD_Write_String(unsignedcharx,unsignedchary,unsignedchar*s)

{

if(y==0)

{

write_com(0x80+x);

}

else

{

write_com(0xC0+x);

}

while(*s)

{

write_data(*s);

s++;

}

}

/*------------------------------------------------

写入字符函数

------------------------------------------------*/

voidLCD_Write_Char(unsignedcharx,unsignedchary,unsignedcharData)

{

if(y==0)

{

write_com(0x80+x);

}

else

{

write_com(0xC0+x);

}

write_data(Data);

}

 

#include

#include

#include"lcd.h"

#include"key.h"

#include"delay.h"

#include"eeprom.h"

voidint0(void);

unsignedcharpassword[6]/*={0x01,0x01,0x01,0x01,0x01,0x01}*/;

unsignedcharpassword1[6];

unsignedcharcodeaa[]="Password";

unsignedcharcodegg[]="New";

unsignedcharcodebb[]="ERROR";

unsignedcharcodecc[]="OK";

unsignedcharcodedd[]="";

unsignedcharcodeee[]="Next";

unsignedcharcodeff[]="success";

unsignedcharkeydata;

main()

{

unsignedchari,j,k,l,m,n,o,a1;

/*for(i=0;i<6;i++)

{

Write_IIC(i,password[i]);

}*/

init();//LCD初始化

int0();

P3_6=0;

P3_7=0;

P1=0x0f;

LCD_Write_String(0,0,aa);

LCD_Write_String(1,1,dd);

write_com(0xc0+1);

while

(1)

{

start:

LCD_Write_String(0,0,aa);

LCD_Write_String(1,1,dd);

write_com(0xc0+1);

while

(1)

{

if((0keydata)||(4keydata)||(8keydata)||keydata==14)

//在0-9之间的数字通过

{

password[i]=keydata;//键盘值进行保存

keydata=0;//把键盘值置其它值,不被其它利用,以一样

i++;

write_data('*');//在LCD上显示*这字符代表输入了一个密码

if(i==6)//这里限制了六位密码

{

i=0;

gotopanduan;

}

}

if(keydata==33)//确定进入密码比较

{

keydata=0;

panduan:

i=0;

for(j=0;j<6;j++)

{

l+=password[j];

k+=Random_Read(j);

}

if(l!

=k)//密码不同进行处理

{

l=0;

k=0;

LCD_Write_String(0,0,bb);

DelayMs(1000);

a1+=1;

if(a1==2){while

(1)P3_7=1;P3_6=0;}//两次错误发出报警

gotostart;//第二次输入密码

}

if(l==k)//密码对了,进入运行状态,这里绿灯代表该状态

{

l=0;

k=0;

a1=0;

P3_6=1;

P3_7=0;

LCD_Write_String(0,0,cc);

LCD_Write_String(1,1,dd);

if(o==1)

{

o=0;

LCD_Write_String(0,0,gg);

LCD_Write_String(4,0,aa);

LCD_Write_String(1,1,dd);

write_com(0xc0+1);

gototext2;

}

gotoyingxing;//跳到下面函数中,yingxing里

}

}

}

yingxing:

while

(1)

{

if(keydata==4)//锁定功能

{

P3_6=0;

gotostart;

}

if(keydata==15)//修改密码

{

o++;

if(o==1)gotostart;

text2:

keydata=0;

while

(1)

{

if((0keydata)||(4keydata)||(8keydata)||keydata==14)

//上面表达式0-9之间的数字通过

{

password[m]=keydata;//读取键盘值

keydata=0;

m++;

write_data('*');

if(m==6)//到密码输入到六位的时候进行判断是否再输入,或者判断前后两次密码是否一致

{

m=0;

n++;

if(n==2)gotopanduan1;//输入第二次的时候进行前后两次密码进判断

for(i=0;i<6;i++)//储存前一次密码

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 职业教育 > 职高对口

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1