摘要:本文设计了一种基于单片机的电子密码锁,由单片机系统、矩阵键盘、LED显示和报警系统组成。系统能完成开锁、超次锁定、报警、修改用户密码基本的密码锁的功能。除上述基本的密码锁功能外,还具有掉电存储、声光提示等功能。本密码锁具有安全性高、成本低、功耗低、易操作、记住密码即可开锁等优点。 关键词:STC89C52;电子密码锁;矩阵键盘
1绪论
1.1 课题背景
随着人们生活水平的提高和安全意识的加强,对安全的要求也就越来越高。锁自古以来就是把守护门的铁将军,人们对它要求甚高,既要安全可靠的防盗,又要使用方便,这也是制锁者长期以来研制的主题。随着电子技术的发展,各类电子产品应运而生,电子密码锁就是其中之一。据有关资料介绍,电子密码锁的研究从20世纪30年代就开始了,在一些特殊场所早就有所应用。这种锁是通过键盘输入一组密码完成开锁过程。研究这种锁的初衷,就是为提高锁的安全性。由于电子锁的密钥量(密码量)极大,可以与机械锁配合使用,并且可以避免因钥匙被仿制而留下安全隐患。电子锁只需记住一组密码,无需携带金属钥匙,免除了人们携带金属钥匙的烦恼,而被越来越多的人所欣赏。电子锁的种类繁多,例如数码锁,指纹锁,磁卡锁,IC卡锁,生物锁等。但较实用的还是按键式电子密码锁。 1.2 课题设计目标
本设计采用STC89C52单片机为主控芯片,通过软件程序组成电子密码锁系统,能够实现:
(1) 密码输入错误,蜂鸣器报警。 (2) 密码为6位,可以随意更改, (3) 采用矩阵按键输入。 (4) 通过LCD1602液晶显示。 (5) 有开锁指示灯。
(6)查阅有关文献与资料,深入学习单片机硬件原理图及软件编程相关知识。
2系统方案论证
系统将从主控部分和密码输入方式两方面进行论证。
第 1 页
2.1 主控部分的选择 方案一:采用数字电路控制
用以74LS112双JK触发器构成的数字逻辑电路作为密码锁的核心控制,共设了9个用户输入键,其中只有4个是有效的密码按键,其它的都是干扰按键,若按下干扰键,键盘输入电路自动清零,原先输入的密码无效,需要重新输入;如果用户输入密码的时间超过10秒(一般情况下,用户不会超过10秒,若用户觉得不便,还可以修改)电路将报警20秒,若电路连续报警三次,电路将锁定键盘2分钟,防止他人的非法操作。采用数字电路设计的方案好处就是设计简单但控制的准确性和灵活性差。故不采用。
方案二:采用以单片机为核心的控制方案
选用单片机作为系统的核心部件,实现控制与处理的功能。单片机具有资源丰富、速度快、编程容易等优点。利用单片机内部的随机存储器(RAM)和只读存储器(ROM)及其引脚资源,外接液晶显示(LCD),键盘输入等实现数据的处理传输和显示功能,基本上能实现设计指标,可以看出方案二控制灵活准确性好且保密性强还具有扩展功能,根据现实生活的需要综合考虑,此次设计采用此方案。 2.2 密码输入方式的选择 方案一:指纹输入识别
指纹识别技术主要涉及四个功能:读取指纹图像、提取特征、保存数据和比对。通过指纹读取设备读取到人体指纹的图像,然后要对原始图像进行初步的处理,使之更清晰,再通过指纹辨识软件建立指纹的特征数据。软件从指纹上找到被称为\"节点\"(minutiae)的数据点,即指纹纹路的分叉、终止或打圈处的坐标位置,这些点同时具有七种以上的唯一性特征。通常手指上平均具有70个节点,所以这种方法会产生大约490个数据。这些数据,通常称为模板。通过计算机模糊比较的方法,把两个指纹的模板进行比较,计算出它们的相似程度,最终得到两个指纹的匹配结果,从而判断输入结果的正确与否。考虑到本方案软硬件太过复杂,而且成本也高,故不采用。 方案二:矩阵键盘输入识别
由各按键组成的矩阵键盘每条行线和列线都对应一条I/O口线,键位设在行线和列线的交叉点,当一个键按下就会有某一条行线与某一条列线接触,只要确定接触的是哪两条线,即哪两个I/O口线,就可以确定哪一个键被触动。行线设计成上拉口线,初始时被置高电位,列线悬空,初始置低。通过不断读行线口线,或者中断方式触发键位扫描。当发现有键按下,将列线逐一置低,其他列线置高,读行线口线。当某条列线置低时,某条行线也被拉低,则确定这两条线的交点处的按钮被按下。每个按键都可通过程序赋予功能,从而完成密码识别。本方案简单易行,故采用。
第 2 页
3 硬件电路设计
3.1 硬件系统总体电路设计
本设计主要由单片机、矩阵键盘、液晶显示器和密码存储等部分组成。其中矩阵键盘用于输入数字密码和进行各种功能的实现。由用户通过连接单片机的矩阵键盘输入密码,后经过单片机对用户输入的密码与自己保存的密码进行对比,从而判断密码是否正确,然后控制引脚的高低电平传到开锁电路或者报警电路控制开锁还是报警,实际使用时只要将单片机的负载由继电器换成电子密码锁的电磁铁吸合线圈即可。系统整体框图如图1所示。
中央控制芯片 密码保护 AT89C52 键盘输入电路 报警电路
显示电路
电源电路
图1 系统结构框图
各模块功能如下:
矩阵键盘输入模块:分为密码输入按键与功能按键,用于完成密码锁输入功能。 显示模块:用于完成对系统状态显示及操作提示功能。 报警电路:用于完成输错密码时候的警报功能。
密码存储模块:用于完成掉电存储功能,使修改的密码断电后仍能保存。 电源模块:用于对系统电路提供+5V的直流电压。 3.2 单片机最小系统模块电路设计
由STC89C52,复位电路,时钟产生电路组成。STC89C52是美国Atmel公司生产的低电压,高性能CMOS8位单片机,片内含8k bytes的可反复擦写的只读程序存储器(PEROM)和256bytes的随机存取数据存储器(RAM),STC89C52有40个引脚,32个外部双向输入/输出(I/O)端口,同时内含2个外中断口,3个16位可编程定时计数器,2个全双工串行通信口,2个读写口线。
第 3 页
主要功能特性:
·8k可反复擦写(>1000次)Flash ROM,32个双向I/O口,256x8bit内部RAM,时钟频率0-24MHz,可编程UART串行通道。
·3个16位可编程定时/计数器中断,2个串行中断,2个外部中断源,共6个中断源,2个读写中断口线。 引脚功能如下:
·P0口:P0口是一组8位漏极开路型双向I/O口,也即地址/数据总线复用口。作为输出口用时,每位能吸收电流的方式驱动8个TTL逻辑门电路,对端口P0写“1”时,可作为高阻抗输入端用。在访问外部数据存储器或程序存储器时,这组口线分时转换地址(低8位)和数据总线复用,在访问期间激活内部上拉电阻。
·P1口:P1是一个带内部上拉电阻的8位双向I/O口,P1的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口。作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流(IIL)。
·P2口:P2是一个带有内部上拉电阻的8位双向I/O口,P2的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口P2写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口,作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流(IIL)。在访问8位地址的外部数据存储器(如执行MOVX@RI指令)时,P2口输出P2锁存器的内容。 Flash编程或校验时,P2亦接收高位地址和一些控制信号。
·P3口:P3口是一组带有内部上拉电阻的8位双向I/O口。P3口输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对P3口写入“1”时,它们被内部上位电阻拉高并可作为输入端口。此时,被外部拉低的P3口将用上拉电阻输出电流(IIL)。P3口除了作为一般的I/O口线外,更重要的用途是它的第二功能。
·RST:复位输入 。当振荡器工作时,RST引脚出现两个机器周期以上高电平将使单片复位。
·ALE/PROG:当访问外部程序存储器或数据存储器时,ALE(地址锁存允许)输出脉冲用于锁存地址的低8位字节。一般情况下,ALE仍以时钟振荡频率的1/6输出固定的脉冲信号,因此它可对外输出时钟或用于定时目的。要注意的是:每当访问外部数据存储器时将跳过一个ALE脉冲。
·EA/VPP:外部访问允许。欲使CPU仅访问外部程序存储器(地址为0000H-FFFFH),EA端必须保持低电平(接地)。需注意的是:如果加密位LB1被编程,复位时内部会锁存EA端状态。如EA端为高电平(接Vcc端),CPU则执行内部程序存储器中的指令。Flash存储器编程时,该引脚加上+12V的编程允许电源VPP,当然
第 4 页
这必须是该器件是使用12V编程电压VPP。
·XTAL1:振荡器反相放大器的及内部时钟发生器的输入端。 ·XTAL2:振荡器反相放大器的输出端。
引脚XTAL1 和XTAL2 分别是该放大器的输入端和输出端。这个放大器与作为反馈元件的片外石英晶体或陶瓷谐振器一起构成自激振荡器。当单片机的复位引脚RST(全称RESET)出现2个机器周期以上的高电平时,单片机就执行复位操作。如果RST持续为高电平,单片机就处于循环复位状态。根据应用的要求,复位操作通常有两种基本形式:上电复位和开关复位。其原理图如图2所示。
图2 最小系统电路原理图
3.3 电源输入模块电路设计
密码锁主控制部分电源需要用5V直流电源供电,把频率为50Hz、有效值为220V的单相交流电压转换为幅值稳定的5V直流电压。其主要原理是把单相电经过电源变压器、整流电路、滤波电路、稳压电路转换成稳定的直流电压。由于输入电压为电网电压,一般情况下所需直流电压的数值和电网电压的有效值相差较大,因而电源变压器的作用显现出来起到降压作用。降压后还是交流电压,所以需要整流电路把交流电压转换成直流电压。由于经整流电路整流后的电压含有较大的交流分量,会影响到负载电路的正常工作。需通过低通滤波电路滤波,使输出电压平滑。稳压电路的功能是使输出直流电压基本不受电网电压波动和负载电阻变化的影响,从而获得稳定性足够高的直流压。本电路使用充电器解决电源稳压问题。 3.4 键盘输入模块电路设计
本设计就采用行列式键盘,同时也能减少键盘与单片机接口时所占用的I/O线的
第 5 页
数目,在按键比较多的时候,通常采用这样方法。每一条水平(行线)与垂直线(列线)的交叉处不相通,而是通过一个按键来连通,利用这种行列式矩阵结构只需要N条行线和M条列线,即可组成具有N×M个按键的键盘。在这种行列式矩阵键盘非键盘编码的单片机系统中,键盘处理程序首先执行等待按键并确认有无按键按下的程序段。
4×4矩阵键盘的工作原理:
在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式,如图3所示。在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样,一个端口(如P1口)就可以构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。 扫描原理:
把每个键都分成水平和垂直的两端接入,比如说扫描码是从垂直的入,那就代表那一行所接收到的扫描码是同一个bit,而读入扫描码的则是水平,扫描的动作是先输入扫描码,再去读取输入的值,经过比对之后就可知道是哪个键被按下。
比如说扫描码送入01111111,前面的0111是代表此时扫描第一行P1.0列,而后面的1111是让读取的4行接脚先设为VDD,若此时第一行的第三列按键被按下,那读取的结果就会变成01111101(注意1111变成1101),其中LSB的第三个bit会由1变成0,这是因为这个按键被按下之后,会被垂直的扫描码电位short,而把读取的LSB的bit电位拉到0,此即为扫描原理。
由於这种按键是机械式的开关,当按键被按下时,键会震动一小段时间才稳定,为了避免让8051误判为多次输入同一按键,我们必须在侦测到有按键被按下,就Delay一小段时间,使键盘以达稳定状态,再去判读所按下的键,就可以让键盘的输入稳定。键盘整体电路图如图3所示。
h1l4h2h3h4123F456E789DA0BCl1l2l3 图3 键盘整体模框图
第 6 页
3.5 密码存储模块电路设计
用EPROM芯片AT24C02存储密码。AT24C02是美国Atmel公司的低功耗CMOS型EPROM,内含256×8位存储空间,具有工作电压宽(2.5~5.5 V)、擦写次数多(大于10000次)、写入速度快(小于10 ms)、抗干扰能力强、数据不易丢失、体积小等特点。而且他是采用了I2C总线式进行数据读写的串行器件,占用很少的资源和I/O线,并且支持在线编程,进行数据实时的存取十分方便。AT24C02中带有的片内地址寄存器。每写入或读出一个数据字节后,该地址寄存器自动加1,以实现对下一个存储单元的读写。所有字节均以单一操作方式读取。为降低总的写入时间,一次操作可写入多达8个字节的数据。I2C总线是一种用于I2C器件之间连接的二线制总线。他通过SDA(串行数据线)及SCL(串行时钟线)两根线在 连到总线上的器件之间传送信息,并根据地址识别每个器件。 AT24C02正是运用了I2C规程,使用主/从机双向通信,主机(通常为单片机)和从机(AT24C02)均可工作于接收器和发送器状态。主机产生串行时钟信号(通过SCL引脚)并发出控制字,控制总线的传送方向,并产生开始和停止的条件。无论是主机还是从机,接收到一个字节后必须发出一个确认信号ACK。AT24C02的控制字由8位二进制数构成,在开始信号发出以后,主机便会发出控制字,以选择从机并控制总线传送的方向。 管脚功能如下:
SCL 为串行时钟:串行时钟输入管脚用于产生器件所有数据发送或接收的时钟这是一个输入管脚。
SDL 为串行数据/地址:双向串行数据/地址管脚用于器件所有数据的发送或接收SDL,是一个开漏输出管脚可与其它开漏输出或集电极开路输出进行线或。 A0、A1、A2 为器件地址输入端:当使用24C02 时最大可级联8个器件,如果只有一个24C02被总线寻址,这三个地址输入脚A0、A1、A2可悬空或连接到Vss。 WP为写保护:如果WP 管脚连接到Vcc 所有的内容都被写保护只能读当WP, 管脚连接到Vss 或悬空,允许器件进行正常的读/写操作。管脚图如图4所示。
图4 AT24C02引脚图
第 7 页
3.6 显示模块电路设计
为了提高密码锁的密码显示效果能力。本设计的显示部分由液晶显示器LCD1602取代普通的数码管来完成。LCD1602中所谓的1602即是16字符*2行的字符型LCD显示器,它由32个字符点阵块组成,每个字符点阵块由5×7或5×10个点阵组成,可以显示ASCII码表中的所有可视的字符。它内置了字符产生器ROM(CGROM)、字符产生器RAM(CGRAM)和显示数据RAM(DDRAM)。CGROM中内置了192个常用字符的字模,CGRAM包含8个字节的RAM,可存放用户自定义的字符,DDRAM就是用来寄存待显示的字符代码。
1602液晶显示器以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,在袖珍式仪表和低功耗应用系统中得到越来越广泛的应用本系统也将用到。 1602引脚及其具体功能如表1所示。
表1 1602引脚及功能 编号 1 2 3 4 5 6 7 8 符号 VSS VDD VL RS R/W E D0 D1 引脚说明 电源地 电源正极 液晶显示偏压信号 数据/命令选择端(H/L) 读/写选择端(H/L) 使能信号 Data I/O Data I/O 编号 符号 9 10 11 12 13 14 15 16 D2 D3 D4 D5 D6 D7 BLA BLK 引脚说明 Data I/O Data I/O Data I/O Data I/O Data I/O Data I/O 背光源正极 背光源负极 1)读操作时序图如图5所示。
图5 读操作时序图
第 8 页
2)写操作时序图如图6所示。
图6 写操作时序图
3)时序参数表如表2所示。
表2 时序参数表 时序参数 符号 极限值 最小值 典型值 最大值 单位 ns ns ns ns ns ns ns ns ns 测试条件 E信号周期 E脉冲宽度 E上升/下降沿时间 地址建立时间 地址保持时间 数据建立时间(读操作) 数据保持时间(读操作) 数据建立时间(写操作) 数据保持时间(写操作) tc tpw ,tF tR tsp1 tHD1 tD tHD2 tsp2 tHD2 400 150 ---- 30 10 ---- 20 40 10 ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- 25 ---- ---- 100 ---- ---- ---- 引脚E 引脚E、RS、R/W 引脚 DB0~DB7 注意:对控制器每次进行读写操作之前,都必须进行读写检测,确保STA7=0 显示器一直处于初始状态,当需要对密码锁进行开锁时,按下键盘上的开锁按键后利用键盘上的数字键0-9输入密码,每按下一个数字键后在显示器上显示一个*,输入多少位就显示多少个*。当密码输入完成时,按下确认键,如果输入的密码正确的话, LCD子显示“RIGHT”,LCD显示屏会显示“ERROR”,P2.0输出的是低电平,电子密码锁不能被打开。通过LCD显示屏,可以清楚的判断出锁所处状态 。其显示部分引脚接口如图7所示。
第 9 页
图7 显示电路原理图
3.7 报警部分
报警部分由喇叭电路组成,当有键按下时,每按一下,喇叭koi响一次,当密码输入错误时,单片机的P2.1引脚为低电平,喇叭发出噪鸣声报警。如图8所示:
图8 报警电路原理图
3.8 开锁机构
用户通过LCD提示信息,用键盘输入正确密码,从而达到开锁的目的。当用户输入的密码正确并且是在按下确定键的话,单片机便输出开门信号,送到开锁驱动 电路,然后驱动电磁锁,达到开门的目的。电路驱动和开锁两级组成。由D5、R1、T10组成驱动电路,其中T10可以选择普通的小功率三极管如9014、9018都可以满足要求。D5作为开锁的提示;由D6、C24、T11组成。其中D6、C24是为了消除电磁锁可能产生的反向高电压以及可能产生的电磁干扰。T11可选用中功率的三极管如8050,电磁锁的选用要视情况而定,但是吸合力要足够且由一定的余量。
第 10 页
4 软件设计
4.1 软件设计原理
本设计主要由单片机、矩阵键盘、液晶显示器和密码存储等部分组成。其中矩阵键盘用于输入数字密码和进行各种功能的实现。由用户通过连接单片机的矩阵键盘输入密码,后经过单片机对用户输入的密码与自己保存的密码进行对比,从而判断密码是否正确,然后控制引脚的高低电平传到开锁电路或者报警电路控制开锁还是报警,实际使用时只要将单片机的负载由继电器换成电子密码锁的电磁铁吸合线圈即可,当然也可以用继电器的常开触点去控制电磁铁吸合线圈。本系统共有两部分构成,即硬件部分与软件部分。其中硬件部分由电源输入部分、键盘输入部分、密码存储部分、显示部分、报警部分组成,软件部分对应的由主程序、初始化程序、LCD显示程序、键盘扫描程序、启动程序、关闭程序、键功能程序、密码设置程序、EEPROM读写程序和延时程序等组成。流程图如图9所示。
开始 旧密码输初始化 新密码输A 模式选择 B 存入缓存N 再次输入密码 重新输入 识别按键 手动清除 N 密码输入 Y 密码比较 设置完毕返回 开门
图9 主程序的流程图
第 11 页
4.2 LED显示子程序
LED显示流程图如图10所示。
图10 LED显示流程图
4.3 键盘扫描及识别子程序
键盘采用查询的方式,放在主程序中,当没有按键按下的时候,单片机循环主程序,一旦有按键按下,便转向相应的子程序处理,处理结束再返回。其程序流程如图11所示。
图11 键盘扫描程序流程图
第 12 页
4.4 系统模块密码设置子程序
由于设计是分模块化进行,所以子程序是整体软件系统的组成部分,子程序不但可以使程序化整为零,使其复杂简单化,同时也方便阅读,修改等,每个功能模块都有它自己的子程序,在本设计中是用LCD显示数据,所以就要用到显示子程序。
设计中用的是矩阵键盘,所以就用到键盘扫描子程序,例如还有显示初始化子程序、LCD忙检测子程序、关闭状态显示子程序、开锁状态显示子程序、密码输入及修改状态显示子程序、密码输入错误后的提示子程序等。密码修改子程序流程图如下图12所示。
Y 锁定
图12 设置密码子程序
选择模式 旧密码输入 新密码输入 存入缓存 重新输入 再次输入密码 N 是否大于3次 N 比较密码 Y 返回
5 系统制作及调试分析
5.1焊接注意事项
LCD的注意事项
1. 采用焊接方法将金属基PIN安装于LCD时,从玻璃末端到PCB的焊接位置的长度至少5mm,焊接温度必须在260℃以下,且焊接时间必须在10秒以内,以免焊接过程中对装置的损坏,确保焊接性能。在230℃,30秒条件下,90%的焊料须紧密
第 13 页
附着于PIN上。
2. 对LCD基板或基PIN焊接位置的调整必须在安装前完成。严禁猛烈移动基PIN,否则会机械地破坏LCD屏与基PIN之间的连接点。焊接时平放LCD,尽量不让LCD受力。
3. 焊接LCD基板时,将其小心、平衡地插入PCB插槽,以避免损坏基PIN或LCD基板。
4. 焊接时,LCD基板不应长时间置于焊锡蒸汽中,清洗PCB时,必须避免污染LCD基板,否则可能损坏显示器表面的偏光片及封口胶。
5. 显示器表面的保护膜直到焊接完成才可揭掉,禁止手指及其它硬物接触偏光片,禁止水和其他化学物质沾污装置,因为这些物质会污染显示器表面。 单片机焊接注意事项:
80s51单片机与其它单片机,dsp,arm芯片相比较而言是脆弱的,如果焊接时不小心就很可能把芯片损坏!建议用比较好的恒温可调的烙铁,功率在30瓦左右,温度控制在260到300度,建议采用点焊而不用拉焊,焊接时烙铁放在每个引脚的时间不能太长(最好低于3秒)。上边提到的方法还不能确保芯片完好,对芯片有危害的还有带电烙铁的静电感应!烙铁质量不是太好的,焊接时可以把烙铁电源插头拔掉。 其他的电子器件焊接须知:
一般分四步骤进行。①准备焊接:清洁被焊元件处的积尘及油污,再将被焊元器件周围的元器件左右掰一掰,让电烙铁头可以触到被焊元器件的焊锡处,以免烙铁头伸向焊接处时烫坏其他元器件。焊接新的元器件时,应对元器件的引线镀锡。②加热焊接:将沾有少许焊锡和松香的电烙铁头接触被焊元器件约几秒钟。若是要拆下印刷板上的元器件,则待烙铁头加热后,用手或银子轻轻拉动元器件,看是否可以取下。③清理焊接面:若所焊部位焊锡过多,可将烙铁头上的焊锡甩掉(注意不要烫伤皮肤,也不要甩到印刷电路板上!),用光烙锡头\"沾\"些焊锡出来。若焊点焊锡过少、不圆滑时,可以用电烙铁头\"蘸\"些焊锡对焊点进行补焊。④检查焊点:看焊点是否圆润、光亮、牢固,是否有与周围元器件连焊的现象。
电子密码锁的硬件联接原理图按下列顺序依次焊接:
(1)焊接单片机的晶振电路、复位电路等单片机的最小系统的外围电路。 (2)焊接LCD的相应管脚并把LCD的管脚单片机相连接。 (3)焊接键盘的按键电路。
(4)焊接电子密码锁的密码输入错误的报警电路。 (5)焊接密码锁的开锁机构电路。 (6)焊接其他接口及辅助电路。
第 14 页
(7)焊接接地及高电平。 5.2软件调试
在硬件支持的环境下,用proteus设计好的电路,Keil编好的程序编译成芯片可识别的文件,利用PC机写进proteus程序图芯片内进行仿真测试,并对其出现的错误进行修改,由图13~图14可看出最终调试成功。
图13 keil编译程序成功
LCD2 LM016L VSSVDDVEERSRWE123456 图4.7 仿真成功密码正确 w17w28w39w410w511w612w713w814D0D1D2D3D4D5D6D7 第 15 页
5.3 硬件调试
电源、晶振电路和复位电路都无异常。 Lcd焊接时的问题:
(1)接通电源后lcd无反应,各个引脚均属正常。推断可能是初始化程序出现问题。 (2)接通电源开门灯和报警电路就会工作,分析原因是单片机刚开始各个管脚输出高电平。
6 心得体会
课程设计是培养学生综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学技术发展的日新日异,单片机已经成为当今计算机应用中空前活跃的领域, 在生活中可以说得是无处不在。因此作为二十一世纪的大学来说掌握单片机的开发技术是十分重要的。
回顾起此次单片机课程设计,至今我仍感慨颇多,的确,从选题到定稿,从理论到实践,在整整两星期的日子里,可以说得是苦多于甜,但是可以学到很多很多的的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,这毕竟第一次做的,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,对单片机汇编语言掌握得不好,通过这次课程设计之后,一定把以前所学过的知识重新温故。
这次课程设计终于顺利完成了,在设计中遇到了很多编程问题,在同学的帮助下,终于游逆而解。非常感谢!
参考文献
[01] 何宏主编. 单片机原理与接口技术. 北京:国防工业出版社. 2006.07 [02] 杨西明, 朱骐主编 . 单片机编程与应用入门. 北京:机械工业出版社 .2004.06 [03] 先锋工作室编著. 单片机程序设计实例. 北京: 清华大学出版社 .2003.01 [04] 谢宜仁主编 . 单片机实用技术问答. 北京: 人民邮电出版社 . 2003.02
[05] 房小翠,王金凤编著. 单片机实用系统设计技术. 北京: 国防工业出版社 . 1999.06
第 16 页
[06] 各种网络教程及其他
[07] 王宽仁. 可靠安全的智能密码锁. 电子技术应用 , 2001
[18] 董继成. 能防止多次试探密码的单片机密码锁.国外电子元器件 , 2004, 3 [09]赵益丹,徐晓林,周振峰编著.电子密码锁的系统原理、设计程序及流程图.嘉兴学院学报,2003,15
[10] 张培仁. 基于 C语言编程 MCS- 51单片机原理与应用. 北京: 清华大学出版社 , 2002.12
[11] 李朝清. PC机及单片机数据通信技术. 北京:北京航空航天大学出版社 , 1999. [12] 刘文涛.MCS-51单片机培训教程(C51)版.电子工业出版社,2005.8
第 17 页
附录Ⅰ 电子密码锁整体设计图
第 18 页
附录Ⅱ 电子密码锁程序源代码
#include #define uchar unsigned char #define uint unsigned int #define w 6 sbit lcd1602_rs=P2^6; sbit lcd1602_en=P2^7; sbit Scl=P3^4; sbit Sda=P3^5; sbit ALAM = P2^1; sbit KEY = P3^6; sbit YY = P2^4; sbit open_led=P2^2; bit operation=0; bit pass=0; bit ReInputEn=0; bit s3_keydown=0; bit key_disable=0; unsigned char countt0,second; void Delay5Ms(void); unsigned char code a[]={0xFE,0xFD,0xFB,0xF7}; unsigned char code start_line[] = {\"password: \unsigned char code name[] = {\"Coded Management\unsigned char code Correct[] = {\" correct \unsigned char code Error[] = {\" error \unsigned char code codepass[] = {\" pass \unsigned char code LockOpen[] = {\" true \unsigned char code SetNew[] = {\"SetNewWordEnable\unsigned char code Input[] = {\"input: \unsigned char code ResetOK[] = {\"ResetPasswordOK \unsigned char code initword[] = {\"Init password...\unsigned char code Er_try[] = {\"error,try again!\unsigned char code again[] = {\"input again \ unsigned char InputData[6]; unsigned char CurrentPassword[6]={1,3,1,4,2,0}; unsigned char TempPassword[6]; unsigned char N=0; unsigned char ErrorCont; unsigned char CorrectCont; 第 19 页 unsigned char ReInputCont; unsigned char num,flag=0; unsigned char code initpassword[6]={1,2,3,4,5,6}; void Delay5Ms(void) { unsigned int TempCyc = 5552; while(TempCyc--); } void Delay400Ms(void) { unsigned char TempCycA = 5; unsigned int TempCycB; while(TempCycA--) { TempCycB=7269; while(TempCycB--); } } //================================================= void mDelay(uint t) { uchar i; while(t--) { for(i=0;i<125;i++) {;} } } void Nop(void) { _nop_(); _nop_(); _nop_(); _nop_(); } void Start(void) { Sda=1; Scl=1; Nop(); Sda=0; 第 20 页 Nop(); } void Stop(void) { Sda=0; Scl=1; Nop(); Sda=1; Nop(); } void Ack(void) { Sda=0; Nop(); Scl=1; Nop(); Scl=0; } void NoAck(void) { Sda=1; Nop(); Scl=1; Nop(); Scl=0; } void Send(uchar Data) { uchar BitCounter=8; uchar temp; do { temp=Data; Scl=0; Nop(); if((temp&0x80)==0x80) Sda=1; else Sda=0; Scl=1; temp=Data<<1; 第 21 页 Data=temp; BitCounter--; } while(BitCounter); Scl=0; } uchar Read(void) { uchar temp=0; uchar temp1=0; uchar BitCounter=8; Sda=1; do{ Scl=0; Nop(); Scl=1; Nop(); if(Sda) temp=temp|0x01; else temp=temp&0xfe; if(BitCounter-1) { temp1=temp<<1; temp=temp1; } BitCounter--; } while(BitCounter); return(temp); } void WrToROM(uchar Data[],uchar Address,uchar Num) { uchar i; uchar *PData; PData=Data; for(i=0;i Send(Address+i); 第 22 页 Ack(); Send(*(PData+i)); Ack(); Stop(); mDelay(20); } } void RdFromROM(uchar Data[],uchar Address,uchar Num) { uchar i; uchar *PData; PData=Data; for(i=0;i Send(Address+i); Ack(); Start(); Send(0xa1); Ack(); *(PData+i)=Read(); Scl=0; NoAck(); Stop(); } } #define yi 0x80 #define er 0x80+0x40 void delay(uint xms) { uint x,y; for(x=xms;x>0;x--) for(y=110;y>0;y--); } write_1602com(uchar com) { lcd1602_rs=0; P0=com; delay(1); lcd1602_en=1; 第 23 页 delay(1); lcd1602_en=0; } write_1602dat(uchar dat) { lcd1602_rs=1; P0=dat; delay(1); lcd1602_en=1; delay(1); lcd1602_en=0; } void lcd_init(void) { write_1602com(0x38); write_1602com(0x0c); write_1602com(0x06); write_1602com(0x01); } //======================================================================= unsigned char coding(unsigned char m) { unsigned char k; switch(m) { case (0x18): k=1;break; case (0x28): k=2;break; case (0x48): k=3;break; case (0x88): k='A';break; case (0x14): k=4;break; case (0x24): k=5;break; case (0x44): k=6;break; case (0x84): k='B';break; case (0x12): k=7;break; case (0x22): k=8;break; case (0x42): k=9;break; case (0x82): k='C';break; case (0x11): k='*';break; case (0x21): k=0;break; case (0x41): k='#';break; 第 24 页 case (0x81): k='D';break; } return(k); } //================================================== unsigned char keynum(void) { unsigned char row,col,i; P1=0xf0; if((P1&0xf0)!=0xf0) { Delay5Ms(); Delay5Ms(); if((P1&0xf0)!=0xf0) { row=P1^0xf0; i=0; P1=a[i]; while(i<4) { if((P1&0xf0)!=0xf0) { col=~(P1&0xff); break; } else { i++; P1=a[i]; } } } else { return 0; } while((P1&0xf0)!=0xf0); return (row|col); } else return 0; 第 25 页 } //============================================= void OneAlam(void) { ALAM=0; Delay5Ms(); ALAM=1; } void TwoAlam(void) { ALAM=0; Delay5Ms(); ALAM=1; Delay5Ms(); ALAM=0; Delay5Ms(); ALAM=1; } //==================================== void ThreeAlam(void) { ALAM=0; Delay5Ms(); ALAM=1; Delay5Ms(); ALAM=0; Delay5Ms(); ALAM=1; Delay5Ms(); ALAM=0; Delay5Ms(); ALAM=1; } //=========================== void DisplayOne(void) { // DisplayOneChar(9+N,1,'*'); write_1602com(yi+5+N); write_1602dat('*'); } 第 26 页 //===================================== void DisplayChar(void) { unsigned char i; if(pass==1) { //DisplayListChar(0,1,LockOpen); write_1602com(er); for(i=0;i<16;i++) { write_1602dat(LockOpen[i]); } } else { if(N==0) { //DisplayListChar(0,1,Error); write_1602com(er); for(i=0;i<16;i++) { write_1602dat(Error[i]); } } else { //DisplayListChar(0,1,start_line); write_1602com(er); for(i=0;i<16;i++) { write_1602dat(start_line[i]); } } } } void DisplayInput(void) { unsigned char i; if(CorrectCont==1) { //DisplayListChar(0,0,Input); write_1602com(er); 第 27 页 for(i=0;i<16;i++) { write_1602dat(Input[i]); } } } //==================================================================== void ResetPassword(void) { unsigned char i; unsigned char j; if(pass==0) { pass=0; DisplayChar(); ThreeAlam(); } else { if(ReInputEn==1) { if(N==6) { ReInputCont++; if(ReInputCont==2) { for(i=0;i<6;) { if(TempPassword[i]==InputData[i]) i++; else { //DisplayListChar(0,1,Error); write_1602com(er); for(j=0;j<16;j++) { write_1602dat(Error[j]); } ThreeAlam(); pass=0; ReInputEn=0; ReInputCont=0; 第 28 页 DisplayChar(); break; } } if(i==6) { //DisplayListChar(0,1,ResetOK); write_1602com(er); for(j=0;j<16;j++) { write_1602dat(ResetOK[j]); } TwoAlam(); WrToROM(TempPassword,0,6); ReInputEn=0; } ReInputCont=0; CorrectCont=0; } else { OneAlam(); //DisplayListChar(0, 1, again); write_1602com(er); for(j=0;j<16;j++) { write_1602dat(again[j]); } for(i=0;i<6;i++) { TempPassword[i]=InputData[i]; } } N=0; } } } } //======================= void Alam_KeyUnable(void) { 第 29 页 P1=0x00; { ALAM=~ALAM; Delay5Ms(); } } //=========== void Cancel(void) { unsigned char i; unsigned char j; //DisplayListChar(0, 1, start_line); write_1602com(er); for(j=0;j<16;j++) { write_1602dat(start_line[j]); } TwoAlam(); for(i=0;i<6;i++) { InputData[i]=0; } KEY=1; ALAM=1; flag=0; operation=0; pass=0; ReInputEn=0; ErrorCont=0; CorrectCont=0; ReInputCont=0; open_led=1; s3_keydown=0; key_disable=0; N=0; } //=========================== void Ensure(void) { unsigned char i,j; RdFromROM(CurrentPassword,0,6); if(N==6) 第 30 页 { if(ReInputEn==0) { for(i=0;i<6;) { if(CurrentPassword[i]==InputData[i]) { i++; } else { ErrorCont++; if(ErrorCont==3) { write_1602com(er); for(i=0;i<16;i++) { write_1602dat(Error[i]); } do Alam_KeyUnable(); while(1); } else { TR0=1; key_disable=1; pass=0; break; } } } if(i==6) { CorrectCont++; if(CorrectCont==1) { //DisplayListChar(0,1,LockOpen); write_1602com(er); for(j=0;j<16;j++) { write_1602dat(LockOpen[j]); } 第 31 页 TwoAlam(); KEY=0; flag=1; pass=1; TR0=1; open_led=0; for(j=0;j<100;j++) { InputData[i]=0; } } else { //DisplayListChar(0,1,SetNew); write_1602com(er); for(j=0;j<16;j++) { write_1602dat(SetNew[j]); } TwoAlam(); ReInputEn=1; CorrectCont=0; } } else { if((InputData[0]==1)&&(InputData[1]==3)&&(InputData[2]==1)&&(InputData[3]==4)&&(InputData[4]==2)&&(InputData[5]==0)) { WrToROM(initpassword,0,6); //DisplayListChar(0,1,initword); write_1602com(er); for(j=0;j<16;j++) { write_1602dat(initword[j]); } TwoAlam(); Delay400Ms(); TwoAlam(); N=0; } else { 第 32 页 //DisplayListChar(0,1,Error); write_1602com(er); for(j=0;j<16;j++) { write_1602dat(Error[j]); } ThreeAlam(); pass=0; } } } else //DisplayListChar(0,1,Er_try); write_1602com(er); for(j=0;j<16;j++) { write_1602dat(Er_try[j]); } ThreeAlam(); } } else { //DisplayListChar(0,1,Error); write_1602com(er); for(j=0;j<16;j++) { write_1602dat(Error[j]); } ThreeAlam(); pass=0; } N=0; operation=1; } //================================ void main(void) { unsigned char KEY,NUM; unsigned char i,j; / { 第 33 页 P1=0xFF; TMOD=0x11; TL0=0xB0; TH0=0x3C; EA=1; ET0=1; TR0=0; Delay400Ms(); lcd_init(); write_1602com(yi); for(i=0;i<16;i++) { write_1602dat(name[i]); } write_1602com(er); for(i=0;i<16;i++) { write_1602dat(start_line[i]); } write_1602com(er+9); write_1602com(0x0f); Delay5Ms(); N=0; { if(key_disable==1) Alam_KeyUnable(); else ALAM=1; flag=0; if(flag==1){ YY=0; num++; if(num>20){ flag=0; num=0; } } KEY=keynum(); if(KEY!=0) { if(key_disable==1) { second=0; while(1) 第 34 页 } else { NUM=coding(KEY); { switch(NUM) { case ('A'): ; break; case ('B'): ; break; case ('C'): ; break; case ('D'): break; case ('*'): Cancel(); break; case ('#'): Ensure(); break; default: { //DisplayListChar(0,1,Input); write_1602com(er); for(i=0;i<16;i++) { write_1602dat(Input[i]); } operation=0; if(N<6) { OneAlam(); //DisplayOneChar(6+N,1,'*'); for(j=0;j<=N;j++) { write_1602com(er+6+j); write_1602dat('*'); } InputData[N]=NUM; N++; } else { N=6; break; } } } 第 35 页 ResetPassword(); } } } } } void time0_int(void) interrupt 1 { TL0=0xB0; TH0=0x3C; //TR0=1; countt0++; if(countt0==20) { countt0=0; second++; if(pass==1) { if(second==1) { open_led=1; TR0=0; TL0=0xB0; TH0=0x3C; second=0; } } else { if(second==3) { TR0=0; second=0; key_disable=0; s3_keydown=0; TL0=0xB0; TH0=0x3C; } else TR0=1; } } } 第 36 页 因篇幅问题不能全部显示,请点此查看更多更全内容