标题: 基于单片机的密码锁设计论文 附源码 [打印本页]

作者: 通天的昵称    时间: 2018-5-3 11:11
标题: 基于单片机的密码锁设计论文 附源码
论文题目  基于单片机的密码锁设计
姓    名    学    号 09531013
  院    系  经济技术学院  专   业    电子信息工程
        指导教师       李*    职   称     副教授     





安徽农业大学经济技术学院学士学位论文(设计)开题报告
课题名称
基于单片机的密码锁设计
课题来源
导师指定
学生姓名

专业
电子信息工程
学号
09531013
指导教师姓名

职称
副教授
研究内容
本系统由STC89C52单片机系统(主要是STC89C52单片机最小系统)、4×4矩阵键盘、LCD1602显示和报警系统等组成,具有设置、修改六位用户密码、超次报警、超次锁定、密码错误报警等功能(本设计由P0口控制LCD显示,密码正确显示OPEN! 密码错误显示error!超过三次输入错误自动锁定。由P1口控制矩阵键盘含有0-9数字键和A-F功能键。)。除上述基本的密码锁功能外,依据实际的情况还可以添加遥控功能。
研究计划
3月中3月底   调研、查资料。
4月初4月中   确定系统架构、分析并划分各功能模块的接口。
4月底5月中   各功能模块软、硬件的设计与开发。
5月下5月底   各功能模块及整个系统的调试与运行。撰写毕业设计论文。

特色与创新
   1.按键设置6位密码,输入密码若密码正确,则锁打开。显示open!
2.密码可以自己修改(6位密码),必须是锁打开时才能改密。为防止误操作,修改密码得输入两次。
3.若密码输入错误次数超过3次,蜂鸣器报警并且锁定键盘。
4.液晶屏亮度会随光线自动调整。
计较方便,易懂


指导教师意见
同意开题。
教研室意见
  同意开题。
学院意见
同意开题。

目 录
第一章 绪论1

11、课题背景和意义1

12、电子密码锁发展趋势2
第二章 设计思想3
第三章 系统硬件设计              4
31硬件支持4
    311STC89C52RC 单片机介绍4
    312液晶显示LCD1602的介绍5
    313自锁开关说明5
    314上拉电阻介绍5
    315三极管介绍6
    316继电器介绍8
    317供电方式9
   318轻触按键9
32功能单元模块设计10
    321 开锁机构10
    322 矩阵键盘设计电路11
    323 声音提示电路设计11
    324 AT24C02掉电存储单元的设计12
第四章 程序设计与系统仿真13
41 模块介绍 13
   411 主程序模块 14
   412 密码比较判断模块15
   413 键盘扫描模块15
  414 修改密码模块16
42 电子密码锁原理图18
   421总店路图18
  422控制电路18
   423实物图19
   424仿真图19第五章 系统功能19
第六章 设计总结19
致谢20
参考文献20
附录 21
a 电子密码锁元件清单21
b 源程序22




摘 要本设计提出了一种电子密码锁的设计方法。本系统由STC89C52单片机系统、4×4矩阵键盘、LCD1602显示和报警系统等组成,具有设置、修改六位用户密码、超次报警、超次锁定、密码错误报警等功能。本系统成本低廉,功能实用。


第一章 绪论
1.1 课题
背景和意义

随着电子技术和计算机技术的飞速发展,单片机性能不断完善,性能价格比显著提高,技术日趋完善。由于单片机具有体积小、重量轻、价格便宜、功耗低、控制功能强及运算速度快等特点,因而在国民经济建设、军事及家用电器等各个领域均得到了广泛的应用。本设计利用单片机及附加电子元器件实现数据采集和控制算法,来完成某一实际功能。

随着人们生活水平的提高和安全意识的加强,对安全的要求也就越来越高。锁自古以来就是把守护门的铁将军,人们对它要求甚高,既要安全可靠的防盗,又要使用方便,这也是制锁者长期以来研制的主题。随着电子技术的发展,各类电子产品应运而生,电子密码锁就是其中之一。电子锁是通过键盘输入一组密码完成开锁过程。研究这种锁的初衷,就是为提高锁的安全性。由于电子锁的密钥量(密码量)极大,可以与机械锁配合使用,并且可以避免因钥匙被仿制而留下安全隐患。电子锁只需记住一组密码,无需携带金属钥匙,免除了人们携带金属钥匙的烦恼,而被越来越多的人所欣赏。电子锁的种类繁多,例如数码锁,指纹锁,磁卡锁,IC卡锁,生物锁等。但较实用的还是按键式电子密码锁。

20世纪80年代后,随着电子锁专用集成电路的出现,电子锁的体积缩小,可靠性提高,成本较高,是适合使用在安全性要求较高的场合,且需要有电源提供能量,使用还局限在一定范围,难以普及,所以对它的研究一直没有明显进展。

目前,在西方发达国家,电子密码锁技术相对先进,种类齐全,电子密码锁已被广泛应用于智能门禁系统中,通过多种更加安全,更加可靠的技术实现大门的管理。国内的不少企业也引进了世界上先进的技术,发展前景非常可观。希望通过不断的努力,使电子密码锁在我国也能得到广泛应用。

1.2 电子密码锁发展趋势

电子密码锁应用于金融业,其根本的作用是“授权”,即被“授权”的人才可以存取钱、物。广义上讲,金融业的“授权”主要包括以下三种层次的内容:1、授予保管权,如使用保管箱、保险箱和保险柜;2、授予出入权,如出入金库、运钞车和保管室;3、授予流通权,如自动存取款。目前,金融行业电子密码锁的应用主要集中在前两个层面上。下面将介绍几种在金融行业中使用较多的电子密码锁以及它们的技术发展方向。当然,以上所说的授权技术再高超,都必须由精良的“锁具”担当承载结构部件,实现开启、闭锁的功能,而且承担实体防护作用,抵抗住或尽量延迟破坏行为,让电子密码锁“软、硬不吃”。一般情况下,锁具防盗的关键是锁身外壳、闭锁的部件的强度、锁止型式、配合间隙和布局。提高电子密码锁之防护能力的必然途径是报警,在金融业的许多场所有人值守、有电视监控,具有报警功能,可以综合物理防范和人力防范两种作用。报警的前提是具备探测功能,根据电子密码锁的使用场所和防护要求,可选择多种多样的探测手段。在中国的城市金融业中,实现联网报警已经成为对各金融网点的基本要求。根据国内外的实践经验,金融业实行安全防范风险等级很有必要,即依据使用的防盗报警器材的性能、安装布局和人员值守状况等,可以评估被防护物或区域的防护能力,得出风险等级,其中,电子密码锁的性能至关重要。

由于数字、字符、图形图像、人体生物特征和时间等要素均可成为钥匙的电子信息,组合使用这些信息能够使电子密码锁获得高度的保密性,如防范森严的金库,需要使用复合信息密码的电子密码锁,这样对盗贼而言是“道高一尺、魔高一丈”。组合使用信息也能够使电子密码锁获得无穷扩展的可能,使产品多样化,对用户而言是“千挑百选、自得其所”。



               图1.1 总体框图

工作过程

第二章 设计思想

(1)本设计为了防止密码被窃取要求在输入密码时在LCD屏幕上显示*号。

(2)设计开锁密码位六位密码的电子密码锁。

(3)能够LCD显示在密码正确时显示open!,密码错误时显示ERROR,输入密码时显示initpassword。

(4)实现输入密码错误超过限定的三次电子密码锁定。

(5)4×4的矩阵键盘其中包括0-9的数字键和A-D的功能键

(6)本产品具备报警功能,当输入密码错误时蜂鸣器响并且LED灯亮。



第三章 系统的硬件设计

3.1硬件支持

3.1.1 STC89C52RC 单片机介绍

STC89C52是一种低功耗、高性能CMOS8位微控制器,具有 8K 在系统可编程Flash 存储器。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C51为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。 具有以下标准功能: 8k字节Flash,512字节RAM, 32 位I/O 口线,看门狗定时器,内置8KB EEPROM,MAX810复位电路,三个16 位 定时器/计数器,一个6向量2级中断结构,全双工串行口。另外 STC89X51 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU 停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。最高运作频率35Mhz,6T/12T可选。

图3-1 STC89C52单片机引脚图

     主要特性如下:

(1) 增强型 8051 单片机,6 时钟/机器周期和 12 时钟/机器周期可以任 意选择,指令代码完全兼容传统 8051.

(2)工作电压:5.5V~3.3V(5V 单片机)/3.8V~2.0V(3V 单片机)

(3) 工作频率范围:0~40MHz,相当于普通 8051 的 0~80MHz,实际工 作频率可达 48MHz

(4) 用户应用程序空间为 8K 字节

(5) 片上集成 512 字节 RAM

(6) 通用 I/O 口 (32 个) 复位后为: , P1/P2/P3/P4 是准双向口/弱上拉, P0 口是漏极开路输出,作为总线扩展用时,不用加上拉电阻,作为 I/O 口用时,需加上拉电阻。

(7)ISP(在系统可编程)/IAP(在应用可编程) ,无需专用编程器,无 需专用仿真器,可通过串口(RxD/P3.0,TxD/P3.1)直接下载用户程 序,数秒即可完成一片

(8)具有 EEPROM 功能

(9)具有看门狗功能

(10)共 3 个 16 位定时器/计数器。即定时器 T0、T1、T2

(11)外部中断 4 路,下降沿中断或低电平触发电路,Power Down 模式可 由外部中断低电平触发中断方式唤醒

(12)通用异步串行口(UART) ,还可用定时器软件实现多个 UART

(13) 工作温度范围:-40~+85℃(工业级)/0~75℃(商业级)

(14) PDIP 封装

3.1.2液晶显示LCD1602的介绍(1)LM1602字符型模块的性能
重量轻:<100g;

体积小:<11mm 厚;

功耗低:10—15mW;

显示内容:192 种字符(5×7 点字型);

32 种字符(5×10 点字型);

可自编8(5×7)或许(5×10)种字符;

指令功能强:可组合成各种输入、显示、移位方式以满足不同的要求;

接口简单方便:可与8 位微处理器或微控制器相联;

工作温度宽:0—50oC

可靠性高:寿命为50,000 小时(25oC)

图3-2 液晶原理图

  3.1.3自锁开关说明

自锁开关电路中起到电源的开关作用,常开的其中一脚接DC电源插口电源脚,常开的另一脚接电路的VCC

                        

  3-3自锁开关原理图                   3-4自锁开关硬件图

3.1.4上拉电阻介绍

     其实排阻就是由8个电阻组成的,其中一端全部接在一起,103为8个10K电阻,

102为8个1K电阻,他们在电路中起到“上拉”的作用,又称上拉电阻。

上拉就是将不确定的信号通过一个电阻嵌位在高电平,电阻同时起限流作用,下拉同理.

上拉是对器件注入电流,下拉是输出电流,弱强只是上拉电阻的阻值不同,没有什么严格区分,对于非集电极(或漏极)开路输出型电路(如普通门电路)提升电流和电压的能力是有限的,上拉电阻的功能主要是为集电极开路输出型电路输出电流通道。

上拉,就是把电位拉高,比如拉到VCC

下拉,就是把电压拉低,拉到GND

一般就是刚上电的时候,端口电压不稳定,为了让他稳定为高或低,就会用到上拉或下拉电阻。

有些芯片内部集成了上拉电阻(如单片机的P1、2、3口),所以外部就不用上拉电阻了。但是有一些开漏的(如单片机的P0口),外部必须加上拉电阻。

图3-5 排组上拉电阻原理图

3.1.5三极管介绍

  常见的三极管为9012、s8550、9013、s8050.单片机应用电路中三极管主要的作用就是开关作用。

其中9012与8550为pnp型三极管,可以通用。

其中9013与8050为npn型三极管,可以通用。

区别引脚:三极管向着自己,引脚从左到右分别为ebc,原理图中有箭头的一端为e,与电阻相连的为b,另一个为c。箭头向里指为PNP(9012或8550),箭头向外指为NPN(9013或8050)。

三极管的工作原理

   三极管是电流放大器件,有三个极,分别叫做集电极C,基极B,发射极E。分成NPN和PNP两种。我们仅以NPN三极管的共发射极放大电路为例来说明一下三极管放大电路的基本原理。

(1)电流放大

    下面的分析仅对于NPN型硅三极管。如上图所示,我们把从基极B流至发射极E的电流叫做基极电流Ib;把从集电极C流至发射极E的电流叫做集电极电流 Ic。这两个电流的方向都是流出发射极的,所以发射极E上就用了一个箭头来表示电流的方向。三极管的放大作用就是:集电极电流受基极电流的控制(假设电源 能够提供给集电极足够大的电流的话),并且基极电流很小的变化,会引起集电极电流很大的变化,且变化满足一定的比例关系:集电极电流的变化量是基极电流变 化量的β倍,即电流变化被放大了β倍,所以我们把β叫做三极管的放大倍数(β一般远大于1,例如几十,几百)。如果我们将一个变化的小信号加到基极跟发射 极之间,这就会引起基极电流Ib的变化,Ib的变化被放大后,导致了Ic很大的变化。如果集电极电流Ic是流过一个电阻R的,那么根据电压计算公式 U=R*I 可以算得,这电阻上电压就会发生很大的变化。我们将这个电阻上的电压取出来,就得到了放大后的电压信号了。

(2)偏置电路

    三极管在实际的放大电路中使用时,还需要加合适的偏置电路。这有几个原因。首先是由于三极管BE结的非线性(相当于一个二极管),基极电流必须在输入电压 大到一定程度后才能产生(对于硅管,常取0.7V)。当基极与发射极之间的电压小于0.7V时,基极电流就可以认为是0。但实际中要放大的信号往往远比 0.7V要小,如果不加偏置的话,这么小的信号就不足以引起基极电流的改变(因为小于0.7V时,基极电流都是0)。如果我们事先在三极管的基极上加上一 个合适的电流(叫做偏置电流,上图中那个电阻Rb就是用来提供这个电流的,所以它被叫做基极偏置电阻),那么当一个小信号跟这个偏置电流叠加在一起时,小 信号就会导致基极电流的变化,而基极电流的变化,就会被放大并在集电极上输出。另一个原因就是输出信号范围的要求,如果没有加偏置,那么只有对那些增加的 信号放大,而对减小的信号无效(因为没有偏置时集电极电流为0,不能再减小了)。而加上偏置,事先让集电极有一定的电流,当输入的基极电流变小时,集电极 电流就可以减小;当输入的基极电流增大时,集电极电流就增大。这样减小的信号和增大的信号都可以被放大了。

(3)开关作用

    下面说说三极管的饱和情况。像上面那样的图,因为受到电阻 Rc的限制(Rc是固定值,那么最大电流为U/Rc,其中U为电源电压),集电极电流是不能无限增加下去的。当基极电流的增大,不能使集电极电流继续增大 时,三极管就进入了饱和状态。一般判断三极管是否饱和的准则是:Ib*β〉Ic。进入饱和状态之后,三极管的集电极跟发射极之间的电压将很小,可以理解为 一个开关闭合了。这样我们就可以拿三极管来当作开关使用:当基极电流为0时,三极管集电极电流为0(这叫做三极管截止),相当于开关断开;当基极电流很 大,以至于三极管饱和时,相当于开关闭合。如果三极管主要工作在截止和饱和状态,那么这样的三极管我们一般把它叫做开关管。

(4)工作状态

    如果我们在上面这个图中,将电阻Rc换成一个灯泡,那么当基极电流为0时,集电极电流为0,灯泡灭。如果基极电流比较大时(大于流过灯泡的电流除以三极管 的放大倍数 β),三极管就饱和,相当于开关闭合,灯泡就亮了。由于控制电流只需要比灯泡电流的β分之一大一点就行了,所以就可以用一个小电流来控制一个大电流的通 断。如果基极电流从0慢慢增加,那么灯泡的亮度也会随着增加(在三极管未饱和之前)。

                                          

    3-6  三极管引脚介绍          图3-7  PNP型原理图         图3-8  NPN型原理图



3.1.6继电器介绍

    电磁继电器一般由铁芯、线圈、衔铁、触点簧片等组成的。只要在线圈两端加上一定的电压,线圈中就会流过一定的电流,从而产生电磁效应,衔铁就会在电磁力吸引的作用下克服返回弹簧的拉力吸向铁芯,从而带动衔铁的动触点与静触点(常开触点)吸合。当线圈断电后,电磁的吸力也随之消失,衔铁就会在弹簧的反作用力返回原来的位置,使动触点与原来的静触点(常闭触点)释放。这样吸合、释放,从而达到了在电路中的导通、切断的目的。对于继电器的“常开、常闭”触点,可以这样来区分:继电器线圈未通电时处于断开状态的静触点,称为“常开触点”;处于接通状态的静触点称为“常闭触点”。继电器一般有两股电路,为低压控制电路和高压工作电路。

继电器的线圈和接线端子是分立的,互补影响的~~~~继电器的触点只相当于开关


            

      3-9  继电器硬件图                  3-10 继电器原理图

3.1.7供电方式

                          

             图3-11  DC插头                         图3-12  USB电源线


3.1.8轻触按键

               

       图3-13 实物图                  图3-14 按键原理图

   

            图3-15  按键解析图相赠                       图3-16  按键解析图


3.2功能单元模块设计

   3.2.1 开锁机构

    通过单片机送给开锁执行机构,电路驱动电磁锁吸合,从而达到开锁的目的。如下图所示,为密码锁开锁电路原理图。

当用户输入的密码正确时,单片机便输出开门信号,送到开锁驱动电路,然后驱动电磁锁,达到开门的目的。本次设计中,基于节省成本考虑,用发光二极管代替电磁锁,信息通过LCD显示,并利用蜂鸣器和二极管声光指示。其中,绿发光二极管亮,表示开锁;否则,表示密码输入错误并开启报警电路。


               图3-17  密码锁开锁电路原理图





3.2.2 矩阵键盘设计电路

     每一条水平(行线)与垂直线(列线)的交叉处不相通,而是通过一个按键来连通,利用这种行列式矩阵结构只需要M条行线和N条列线,即可组成具有M×N个按键的键盘。由于本设计中要求使用16个按键输入,为减少键盘与单片机接口时所占用的I/O线的数目,故使用矩阵键盘。本设计中,矩阵键盘行线和单片机P1.0-P1.3相连,列线与单片机P1.4-P1.7相连。矩阵键盘设计电路图,如图4所示。

键盘扫描采用行扫描法,即依次置行线中的每一行为低电平,其余均为高电平,扫描列线电平状态,为低电平即表示该键按下。



                           图3-18   矩阵键盘设计电路


3.2.3 声音提示电路设计

声音提示电路采用小蜂鸣器提示。蜂鸣器能够根据脉冲信号,以及信号的频率发出各种不同的声音,这样可以根据系统要求在密码出入正确和密码输入错误时发出不同的声音提示,已达到报警的要求。蜂鸣器电路,如下图所示。

图3-19  蜂鸣器电路


3.2.4 AT24C02掉电存储单元的设计

本设计中掉电存储单元采用AT24C02外部存储器[8-9],其作用是在系统电源断开的时候,存储当前设定的密码数据。

AT24C02是一个2K位串行CMOS E2PROM,内部含有256个8位字节, 含一个16字节页写缓冲器,具有写保护功能。其采用两线串行的总线和单片机通讯,电压最低可以到2.5V,额定电流为1mA,静态电流10Ua(5.5V),芯片内的资料可以在断电的情况下保存40年以上,而且采用8脚的DIP封装,使用方便。如下所示,下图为AT24C02管脚示意图,下表为AT24C02管脚说明。

                      图3-20  AT24C02管脚示意图

管脚名称
功能
管脚名称
功能
A0 A1 A2
器件地址选择
SDA
串行数据/地址
SCL
串行时钟信号
WP
写保护
VCC
1.8V-6.0V工作电压
VSS
接地


            

                                     表1  AT24C02管脚说明

本设计中,AT24C02的SCL和SDA引脚接上拉电阻后与单片机的P3.4(T0)和P3.5(T1)脚相连,其电路下图所示。

                 



                                图3-22  AT24C02掉电存储单元设计图


第四章 系统模块与程序设计
4.1 模块介绍

     与硬件电路相关联,本系统软件包括主程序模块、密码比较判断模块、键盘扫描模块、修改密码模块、1602A液晶显示模块等[10]。系统程序流程下图所示。

                             图4-1  系统程序流程图


4.1.1 主程序模块

主程序主要用于定义全局变量,给全局变量赋初值,初始化E2PROM,启动定时器以及   从AT24C02中读取密码,为整个程序提供数据;检测按键;调用显示等功能。


4.1.2 密码比较判断模块

该模块的功能是将键盘输入的密码利用if语句与设定的密码进行逐个比较,若密码完全正确则开锁;若不正确,则开启报警电路,复位后重新输入密码。其密码输入和比较判决流程图下图所示。

                        图4-2  密码输入和比较判决流程图

4.1.3 键盘扫描模块

     键盘使用矩阵式键盘,由行和列组成,CPU对所有键盘进行监视,从而实现逐列扫描键盘确定被按键的具体位置、判断键盘上有无键按下、消除去抖动、判断闭合的键是否释放等功能。如下图所示,为键盘扫描流程图                        

     

                       图4-3  键盘扫描流程图

4.1.4 修改密码模块

在密码输入正确情况下,可以按下“重置密码”对密码进行重新设置,每设定一位就将密码送给AT24C02存储起来,当设置6位密码完毕后,系统将自动跳到程序开始,调用新设置的密码。下图为修改密码流程图。

                         图4-4  修改密码流程图



4.2电子密码锁原理图
  4.2.1 总电路图
                  
                            图4-5   总电路图


4.2.2控制电路

                                    图4-6  控制电路图




4.2.3实物图
   
                                      图4-7实物图
4.2.4仿真图
五 系统功能

本设计中系统可实现功能如下:

(1)对输入的6位密码进行隐藏;

(2)通过发光二极管和蜂鸣器,对解密正确或者错误进行声光报警;

(3)6位密码修改;

(4)在密码遗失情况下,通过初始密码进行密码再设置;

(5)采用AT24C02外部存储器,完成断电密码保护功能;

六 设计总结

从基本方案的制定,到硬件电路的选择,再到电路的焊接,最后进行程序调试——在此期间我们遇到很多困难,但经过不懈努力,终于击破了各个难点,达到的所需要的效果。在这次设计中,我深刻认识到自身的不足——缺少实战经验。与此同时,也因为这次设计,我得到一定的锻炼,体会到理论与实践相结合的重要意义。

由于本次设计时间有限,一些设想没有完全实现,比如说:电子密码锁的网络通信扩展,人机界面智能化等。期待以后有机会对以上设想进行进一步研究实践。







致谢

非常感谢**老师,老师在我大学的最后学习阶段——毕业设计阶段给自己的指导,从最初的定题,到资料收集,到写作、修改,到论文定稿,她们给了我耐心的指导和无私的帮助。为了指导我们的毕业论文,他甚至放弃了自己的休息时间,他的这种无私奉献的敬业精神令人钦佩,在此我向他表示我诚挚的谢意。同时,感谢所有任课老师和所有同学在这四年来给自己的指导和帮助,是他们教会了我专业知识,教会了我如何学习,教会了我如何做人。正是由于他们,我才能在各方面取得显著的进步,在此向他们表示我由衷的谢意,并祝所有的老师培养出越来越多的优秀人才,桃李满天下


单片机源程序如下:



  1. <font style="background-color:rgb(255, 255, 255)">#include <REG51.h>
  2. #include<intrins.h>
  3. #define LCM_Data  P0
  4. #define uchar unsigned char
  5. #define uint  unsigned int
  6. #define w 6                                                        //定义密码位数
  7. sbit lcd1602_rs=P2^7;
  8. sbit lcd1602_rw=P2^6;
  9. sbit lcd1602_en=P2^5;

  10. sbit Scl=P3^4;                                          //24C02串行时钟
  11. sbit Sda=P3^5;                                          //24C02串行数据

  12. sbit ALAM = P2^1;                            //报警            
  13. sbit KEY = P3^6;                            //开锁

  14. sbit open_led=P2^2;                            //开锁指示灯

  15. bit  operation=0;                            //操作标志位
  16. bit  pass=0;                                          //密码正确标志
  17. bit  ReInputEn=0;                            //重置输入充许标志            
  18. bit  s3_keydown=0;                            //3秒按键标志位
  19. bit  key_disable=0;                            //锁定键盘标志

  20. unsigned char countt0,second;              //t0中断计数器,秒计数器

  21. void Delay5Ms(void);

  22. unsigned char code a[]={0xFE,0xFD,0xFB,0xF7};                                                                                                                                                           //控盘扫描控制表

  23. unsigned char code start_line[]              = {"password:       "};
  24. unsigned char code name[]                             = {"===Coded Lock==="};                                                                                                                                                                        //显示名称
  25. unsigned char code Correct[]               = {"     correct    "};                                                                                                                                                          //输入正确
  26. unsigned char code Error[]                 = {"      error     "};                                                                                                                                                            //输入错误
  27. unsigned char code codepass[]              = {"      pass      "};
  28. unsigned char code LockOpen[]              = {"      open      "};                                                                                                                                                                        //OPEN
  29. unsigned char code SetNew[]               = {"SetNewWordEnable"};
  30. unsigned char code Input[]                 = {"input:          "};                                                                                                                                                                        //INPUT
  31. unsigned char code ResetOK[]               = {"ResetPasswordOK "};
  32. unsigned char code initword[]              = {"Init password..."};
  33. unsigned char code Er_try[]                            = {"error,try again!"};
  34. unsigned char code again[]                            = {"input again     "};

  35. unsigned char InputData[6];                                                                                                                                                                                                                                //输入密码暂存区
  36. unsigned char CurrentPassword[6]={1,3,1,4,2,0};                                                                                                                                                                                                     //当前密码值
  37. unsigned char TempPassword[6];
  38. unsigned char N=0;                                                        //密码输入位数记数
  39. unsigned char ErrorCont;                                          //错误次数计数
  40. unsigned char CorrectCont;                                          //正确输入计数
  41. unsigned char ReInputCont;                                           //重新输入计数
  42. unsigned char code initpassword[6]={0,0,0,0,0,0};

  43. //=====================5ms延时==============================
  44. void Delay5Ms(void)
  45. {
  46.               unsigned int TempCyc = 5552;
  47.               while(TempCyc--);
  48. }

  49. //===================400ms延时==============================
  50. void Delay400Ms(void)
  51. {
  52. unsigned char TempCycA = 5;
  53. unsigned int TempCycB;
  54. while(TempCycA--)
  55. {
  56.   TempCycB=7269;
  57.   while(TempCycB--);
  58. }
  59. }

  60. //=============================================================================================
  61. //================================24C02========================================================
  62. //=============================================================================================

  63. void mDelay(uint t) //延时
  64. {
  65.               uchar i;
  66.                  while(t--)
  67.                  {
  68.                                for(i=0;i<125;i++)
  69.                                {;}
  70.                  }
  71. }
  72.    void Nop(void)                              //空操作
  73. {
  74.               _nop_();
  75.               _nop_();
  76.               _nop_();
  77.               _nop_();
  78. }


  79. /*起始条件*/

  80. void Start(void)
  81. {
  82.               Sda=1;
  83.               Scl=1;
  84.               Nop();
  85.               Sda=0;
  86.               Nop();
  87. }


  88. /*停止条件*/
  89. void Stop(void)
  90. {
  91.               Sda=0;
  92.               Scl=1;
  93.               Nop();
  94.               Sda=1;
  95.               Nop();
  96. }

  97. /*应答位*/
  98. void Ack(void)
  99. {
  100.               Sda=0;
  101.               Nop();
  102.               Scl=1;
  103.               Nop();
  104.               Scl=0;
  105. }

  106. /*反向应答位*/
  107. void NoAck(void)
  108. {
  109.               Sda=1;
  110.               Nop();
  111.               Scl=1;
  112.               Nop();
  113.               Scl=0;
  114. }

  115. /*发送数据子程序,Data为要求发送的数据*/
  116. void Send(uchar Data)
  117. {
  118.                  uchar BitCounter=8;
  119.                  uchar temp;
  120.                  do
  121.                  {
  122.                                temp=Data;
  123.                                Scl=0;
  124.                                Nop();
  125.                                if((temp&0x80)==0x80)
  126.                                Sda=1;
  127.                                else
  128.                                Sda=0;
  129.                                Scl=1;
  130.                                temp=Data<<1;
  131.                                Data=temp;
  132.                                BitCounter--;
  133.                  }
  134.                  while(BitCounter);
  135.                  Scl=0;
  136. }

  137. /*读一字节的数据,并返回该字节值*/
  138. uchar Read(void)
  139. {
  140.     uchar temp=0;
  141.               uchar temp1=0;
  142.               uchar BitCounter=8;
  143.               Sda=1;
  144.               do{
  145.               Scl=0;
  146.               Nop();
  147.               Scl=1;
  148.               Nop();
  149.               if(Sda)
  150.               temp=temp|0x01;
  151.               else
  152.               temp=temp&0xfe;
  153.               if(BitCounter-1)
  154.               {
  155.               temp1=temp<<1;
  156.               temp=temp1;
  157.               }
  158.               BitCounter--;
  159.               }
  160.               while(BitCounter);
  161.               return(temp);
  162.               }

  163. void WrToROM(uchar Data[],uchar Address,uchar Num)
  164. {
  165.   uchar i;
  166.   uchar *PData;
  167.   PData=Data;
  168.   for(i=0;i<Num;i++)
  169.   {
  170.   Start();
  171.   Send(0xa0);
  172.   Ack();
  173.   Send(Address+i);
  174.   Ack();
  175.   Send(*(PData+i));
  176.   Ack();
  177.   Stop();
  178.   mDelay(20);
  179.   }
  180. }

  181. void RdFromROM(uchar Data[],uchar Address,uchar Num)
  182. {
  183.   uchar i;
  184.   uchar *PData;
  185.   PData=Data;
  186.   for(i=0;i<Num;i++)
  187.   {
  188.   Start();
  189.   Send(0xa0);
  190.   Ack();
  191.   Send(Address+i);
  192.   Ack();
  193.   Start();
  194.   Send(0xa1);
  195.   Ack();
  196.   *(PData+i)=Read();
  197.   Scl=0;
  198.   NoAck();
  199.   Stop();
  200.   }
  201. }
  202. //==================================================================================================
  203. //=======================================LCD1602====================================================
  204. //==================================================================================================

  205. #define yi 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)
  206. #define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)


  207. //----------------延时函数,后面经常调用----------------------
  208. void delay(uint xms)//延时函数,有参函数
  209. {
  210.               uint x,y;
  211.               for(x=xms;x>0;x--)
  212.               for(y=110;y>0;y--);
  213. }

  214. //--------------------------写指令---------------------------
  215. write_1602com(uchar com)//****液晶写入指令函数****
  216. {
  217.               lcd1602_rs=0;//数据/指令选择置为指令
  218.               lcd1602_rw=0; //读写选择置为写
  219.               P0=com;//送入数据
  220.               delay(1);
  221.               lcd1602_en=1;//拉高使能端,为制造有效的下降沿做准备
  222.               delay(1);
  223.               lcd1602_en=0;//en由高变低,产生下降沿,液晶执行命令
  224. }

  225. //-------------------------写数据-----------------------------
  226. write_1602dat(uchar dat)//***液晶写入数据函数****
  227. {
  228.               lcd1602_rs=1;//数据/指令选择置为数据
  229.               lcd1602_rw=0; //读写选择置为写
  230.               P0=dat;//送入数据
  231.               delay(1);
  232.               lcd1602_en=1; //en置高电平,为制造下降沿做准备
  233.               delay(1);
  234.               lcd1602_en=0; //en由高变低,产生下降沿,液晶执行命令
  235. }

  236. //-------------------------初始化-------------------------
  237. void lcd_init(void)
  238. {
  239.               write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据
  240.               write_1602com(0x0c);//开显示不显示光标
  241.               write_1602com(0x06);//整屏不移动,光标自动右移
  242.               write_1602com(0x01);//清显示
  243. }
  244. //========================================================================================
  245. //=========================================================================================

  246. //==============将按键值编码为数值=========================
  247. unsigned char coding(unsigned char m)            
  248. {
  249.               unsigned char k;
  250.             
  251.               switch(m)
  252.               {
  253.                             case (0x11): k=1;break;
  254.                             case (0x21): k=2;break;
  255.                             case (0x41): k=3;break;
  256.                             case (0x81): k='A';break;
  257.                             case (0x12): k=4;break;
  258.                             case (0x22): k=5;break;
  259.                             case (0x42): k=6;break;
  260.                             case (0x82): k='B';break;
  261.                             case (0x14): k=7;break;
  262.                             case (0x24): k=8;break;
  263.                             case (0x44): k=9;break;
  264.                             case (0x84): k='C';break;
  265.                             case (0x18): k='*';break;
  266.                             case (0x28): k=0;break;
  267.                             case (0x48): k='#';break;
  268.                             case (0x88): k='D';break;
  269.               }
  270.               return(k);
  271. }


  272. //=====================按键检测并返回按键值===============================
  273. unsigned char keynum(void)
  274. {
  275.               unsigned char row,col,i;
  276.               P1=0xf0;
  277.               if((P1&0xf0)!=0xf0)
  278.               {
  279.                                Delay5Ms();
  280.         Delay5Ms();
  281.                                if((P1&0xf0)!=0xf0)
  282.                             {
  283.                                 row=P1^0xf0;          //确定行线
  284.                                           i=0;
  285.                                           P1=a[i];                        //精确定位
  286.                                           while(i<4)
  287.                                           {
  288.                                                         if((P1&0xf0)!=0xf0)
  289.                                                           {
  290.                                                                          col=~(P1&0xff);                //确定列线
  291.                                                                          break;            //已定位后提前退出  
  292.                                                           }
  293.                                                         else
  294.                                                           {
  295.                                                                          i++;
  296.                                                                          P1=a[i];
  297.                                                           }
  298.                                           }
  299.                             }
  300.                             else
  301.                             {
  302.                                           return 0;
  303.                             }
  304.             
  305.                             while((P1&0xf0)!=0xf0);
  306.        return (row|col);                                          //行线与列线组合后返回
  307.               }
  308.               else return 0;                                                   //无键按下时返回0
  309. }
  310. //=======================一声提示音,表示有效输入========================
  311. void OneAlam(void)
  312. {
  313.               ALAM=0;
  314.               Delay5Ms();
  315.     ALAM=1;
  316. }
  317. //========================二声提示音,表示操作成功========================
  318. void TwoAlam(void)
  319. {
  320.               ALAM=0;
  321.               Delay5Ms();
  322.     ALAM=1;
  323.     Delay5Ms();
  324.               ALAM=0;
  325.               Delay5Ms();
  326.     ALAM=1;
  327. }
  328. //========================三声提示音,表示错误========================
  329. void ThreeAlam(void)
  330. {
  331.               ALAM=0;
  332.               Delay5Ms();
  333.     ALAM=1;
  334.     Delay5Ms();
  335.               ALAM=0;
  336.               Delay5Ms();
  337.     ALAM=1;
  338.     Delay5Ms();
  339.               ALAM=0;
  340.               Delay5Ms();
  341.     ALAM=1;

  342. }
  343. //=====================显示输入的N个数字,用H代替以便隐藏============================
  344. void DisplayOne(void)
  345. {
  346. //              DisplayOneChar(9+N,1,'*');
  347.               write_1602com(yi+5+N);
  348.               write_1602dat('*');
  349. }
  350. //=======================显示提示输入=========================
  351. void DisplayChar(void)
  352. {
  353.               unsigned char i;
  354.               if(pass==1)
  355.               {
  356.                             //DisplayListChar(0,1,LockOpen);
  357.                             write_1602com(er);
  358.                             for(i=0;i<16;i++)
  359.                             {
  360.                                           write_1602dat(LockOpen[i]);            
  361.                             }
  362.               }
  363.               else
  364.               {
  365.                             if(N==0)
  366.                             {
  367.                                           //DisplayListChar(0,1,Error);
  368.                                           write_1602com(er);
  369.                                           for(i=0;i<16;i++)
  370.                                           {
  371.                                                         write_1602dat(Error[i]);            
  372.                                           }
  373.                             }
  374.                             else
  375.                             {
  376.                                           //DisplayListChar(0,1,start_line);            
  377.                                           write_1602com(er);
  378.                                           for(i=0;i<16;i++)
  379.                                           {
  380.                                                         write_1602dat(start_line[i]);            
  381.                                           }
  382.                             }
  383.               }
  384. }

  385. void DisplayInput(void)
  386. {
  387.               unsigned char i;
  388.               if(CorrectCont==1)
  389.               {
  390.                             //DisplayListChar(0,0,Input);
  391.                             write_1602com(er);
  392.                             for(i=0;i<16;i++)
  393.                             {
  394.                                           write_1602dat(Input[i]);            
  395.                             }
  396.               }
  397. }


  398. //========================重置密码==================================================
  399. //==================================================================================
  400. void ResetPassword(void)
  401. {
  402.               unsigned char i;            
  403.               unsigned char j;
  404.               if(pass==0)
  405.               {
  406.                             pass=0;
  407.                             DisplayChar();
  408.                             ThreeAlam();
  409.               }
  410.               else
  411.               {
  412.                   if(ReInputEn==1)
  413.                             {
  414.                                           if(N==6)
  415.                                           {
  416.                                                         ReInputCont++;                                                      
  417.                                                         if(ReInputCont==2)
  418.                                                         {
  419.                                                                       for(i=0;i<6;)
  420.                                                                       {
  421.                                                                                     if(TempPassword[i]==InputData[i])              //将两次输入的新密码作对比
  422.                                                                                                   i++;
  423.                                                                                     else
  424.                                                                                     {
  425.                                                                                                   //DisplayListChar(0,1,Error);
  426.                                                                                                   write_1602com(er);
  427.                                                                                                   for(j=0;j<16;j++)
  428.                                                                                                   {
  429.                                                                                                                 write_1602dat(Error[j]);            
  430.                                                                                                   }
  431.                                                                                                   ThreeAlam();                                          //错误提示            
  432.                                                                                                   pass=0;
  433.                                                                                                   ReInputEn=0;                                          //关闭重置功能,
  434.                                                                                                   ReInputCont=0;
  435.                                                                                                   DisplayChar();
  436.                                                                                                   break;
  437.                                                                                     }
  438.                                                                       }
  439.                                                                       if(i==6)
  440.                                                                       {
  441.                                                                                     //DisplayListChar(0,1,ResetOK);
  442.                                                                                     write_1602com(er);
  443.                                                                                     for(j=0;j<16;j++)
  444.                                                                                     {
  445.                                                                                                   write_1602dat(ResetOK[j]);            
  446.                                                                                     }

  447.                                                                                     TwoAlam();                                                        //操作成功提示
  448.                                                                                     WrToROM(TempPassword,0,6);                            //将新密码写入24C02存储
  449.                                                                                     ReInputEn=0;
  450.                                                                       }
  451.                                                                       ReInputCont=0;
  452.                                                                       CorrectCont=0;
  453.                                                         }
  454.                                                         else
  455.                                                         {
  456.                                                                       OneAlam();
  457.                                                                       //DisplayListChar(0, 1, again);                             //显示再次输入一次
  458.                                                                       write_1602com(er);
  459.                                                                       for(j=0;j<16;j++)
  460.                                                                       {
  461.                                                                                     write_1602dat(again[j]);            
  462.                                                                       }                                                                     
  463.                                                                       for(i=0;i<6;i++)
  464.                                                                       {
  465.                                                                                     TempPassword[i]=InputData[i];                            //将第一次输入的数据暂存起来                                                                                   
  466.                                                                       }
  467.                                                         }

  468.                                           N=0;                                                                                    //输入数据位数计数器清零
  469.                                }
  470.                   }
  471.               }

  472. }



  473. //=======================输入密码错误超过三过,报警并锁死键盘======================
  474. void Alam_KeyUnable(void)
  475. {
  476.               P1=0x00;
  477.               {
  478.                             ALAM=~ALAM;
  479.                             Delay5Ms();
  480.               }
  481. }


  482. //=======================取消所有操作============================================
  483. void Cancel(void)
  484. {            
  485.               unsigned char i;
  486.               unsigned char j;
  487.               //DisplayListChar(0, 1, start_line);
  488.               write_1602com(er);
  489.               for(j=0;j<16;j++)
  490.               {
  491.                             write_1602dat(start_line[j]);            
  492.               }
  493.               TwoAlam();                                                        //提示音
  494.               for(i=0;i<6;i++)
  495.               {
  496.                             InputData[i]=0;
  497.               }
  498.               KEY=1;                                                                      //关闭锁
  499.               ALAM=1;                                                                      //报警关
  500.               operation=0;                                          //操作标志位清零
  501.               pass=0;                                                                      //密码正确标志清零
  502.               ReInputEn=0;                                          //重置输入充许标志清零
  503.               ErrorCont=0;                                          //密码错误输入次数清零
  504.               CorrectCont=0;                                          //密码正确输入次数清零
  505.               ReInputCont=0;                                          //重置密码输入次数清零
  506.               open_led=1;
  507.               s3_keydown=0;
  508.               key_disable=0;
  509.               N=0;                                                                      //输入位数计数器清零
  510. }


  511. //==========================确认键,并通过相应标志位执行相应功能===============================
  512. void Ensure(void)
  513. {            
  514.               unsigned char i,j;
  515.               RdFromROM(CurrentPassword,0,6);                                                                       //从24C02里读出存储密码
  516.     if(N==6)
  517.               {
  518.                   if(ReInputEn==0)                                                                                                  //重置密码功能未开启
  519.                             {
  520.                                           for(i=0;i<6;)
  521.                                              {                                                                     
  522.                                                         if(CurrentPassword[i]==InputData[i])
  523.                                                         {
  524.                                                                       i++;
  525.                                                         }
  526.                                                         else
  527.                                                         {                                         
  528.                                                                       ErrorCont++;
  529.                                                                       if(ErrorCont==3)                                          //错误输入计数达三次时,报警并锁定键盘
  530.                                                                       {
  531.                                                                                     write_1602com(er);
  532.                                                                                     for(i=0;i<16;i++)
  533.                                                                                     {
  534.                                                                                                   write_1602dat(Error[i]);            
  535.                                                                                     }
  536.                                                                                     do
  537.                                                                                     Alam_KeyUnable();
  538.                                                                                     while(1);
  539.                                                                       }
  540.                                                                       else
  541.                                                                       {
  542.                                                                                     TR0=1;                                                        //开启定时
  543.                                                                                     key_disable=1;                                          //锁定键盘
  544.                                                                                     pass=0;
  545.                                                                                     break;
  546.                                                                       }
  547.                                                         }
  548.                                           }

  549.                                           if(i==6)
  550.                                           {
  551.                                                         CorrectCont++;
  552.                                                         if(CorrectCont==1)                                                        //正确输入计数,当只有一次正确输入时,开锁,
  553.                                                         {
  554.                                                                       //DisplayListChar(0,1,LockOpen);
  555.                                                                       write_1602com(er);
  556.                                                                       for(j=0;j<16;j++)
  557.                                                                       {
  558.                                                                                     write_1602dat(LockOpen[j]);            
  559.                                                                       }
  560.                                                                       TwoAlam();                                          //操作成功提示音
  561.                                                                       KEY=0;                                                                                                                                                          //开锁
  562.                                                                       pass=1;                                                                                                                                                          //置正确标志位
  563.                                                                       TR0=1;                                                                                                                                                          //开启定时
  564.                                                                       open_led=0;                                                                                                                                            //开锁指示灯亮
  565.                                                                       for(j=0;j<6;j++)                                                                                                                //将输入清除
  566.                                                                       {
  567.                                                                                     InputData[i]=0;
  568.                                                                       }
  569.                                                         }            
  570.                                                         else                                                                                                                                                                        //当两次正确输入时,开启重置密码功能
  571.                                                         {
  572.                                                                       //DisplayListChar(0,1,SetNew);
  573.                                                                       write_1602com(er);
  574.                                                                       for(j=0;j<16;j++)
  575.                                                                       {
  576.                                                                                     write_1602dat(SetNew[j]);            
  577.                                                                       }
  578.                                                                       TwoAlam();                                                                                                                                  //操作成功提示
  579.                                                                       ReInputEn=1;                                                                                                                              //允许重置密码输入
  580.                                                                       CorrectCont=0;                                                                                                                              //正确计数器清零
  581.                                                         }
  582.                                             }
  583.             
  584.                                           else                                          //=========================当第一次使用或忘记密码时可以用131420对其密码初始化============
  585.                                           {
  586.                                                         if((InputData[0]==1)&&(InputData[1]==3)&&(InputData[2]==1)&&(InputData[3]==4)&&(InputData[4]==2)&&(InputData[5]==0))
  587.                                                           {
  588.                                                                       WrToROM(initpassword,0,6);                                                         //强制将初始密码写入24C02存储
  589.                                                                       //DisplayListChar(0,1,initword);                                          //显示初始化密码
  590.                                                                       write_1602com(er);
  591.                                                                       for(j=0;j<16;j++)
  592.                                                                       {
  593.                                                                                     write_1602dat(initword[j]);            
  594.                                                                       }
  595.                                                                       TwoAlam();
  596.                                                                       Delay400Ms();
  597.                                                                       TwoAlam();
  598.                                                                       N=0;
  599.                                                         }
  600.                                                         else
  601.                                                         {
  602.                                                                       //DisplayListChar(0,1,Error);
  603.                                                                       write_1602com(er);
  604.                                                                       for(j=0;j<16;j++)
  605.                                                                       {
  606.                                                                                     write_1602dat(Error[j]);            
  607.                                                                       }
  608.                                                                       ThreeAlam();                                                                                                                                            //错误提示音
  609.                                                                       pass=0;            
  610.                                                         }
  611.                                           }
  612.                             }

  613.                             else                                                                                                                                                          //当已经开启重置密码功能时,而按下开锁键,
  614.                             {
  615.                                           //DisplayListChar(0,1,Er_try);
  616.                                           write_1602com(er);
  617.                                           for(j=0;j<16;j++)
  618.                                           {
  619.                                                         write_1602dat(Er_try[j]);            
  620.                                           }
  621.                                           ThreeAlam();
  622.                             }
  623.               }

  624.               else
  625.               {
  626.                             //DisplayListChar(0,1,Error);
  627.                             write_1602com(er);
  628.                             for(j=0;j<16;j++)
  629.                             {
  630.                                           write_1602dat(Error[j]);            
  631.                             }

  632.                             ThreeAlam();                                                                                                                                            //错误提示音
  633.                             pass=0;            
  634.               }
  635.               N=0;                                                                                                                                                                                      //将输入数据计数器清零,为下一次输入作准备
  636.   operation=1;
  637. }
  638. //==============================主函数===============================
  639. void main(void)
  640. {
  641.               unsigned char KEY,NUM;
  642.               unsigned char i,j;
  643.               P1=0xFF;
  644.               TMOD=0x11;
  645.               TL0=0xB0;
  646.               TH0=0x3C;
  647.               EA=1;
  648.               ET0=1;            
  649.               TR0=0;
  650.               Delay400Ms();               //启动等待,等LCM讲入工作状态
  651.               lcd_init();               //LCD初始化
  652.               write_1602com(yi);//日历显示固定符号从第一行第0个位置之后开始显示
  653.               for(i=0;i<16;i++)
  654.               {
  655.                             write_1602dat(name[i]);//向液晶屏写日历显示的固定符号部分
  656.               }
  657.               write_1602com(er);//时间显示固定符号写入位置,从第2个位置后开始显示
  658.               for(i=0;i<16;i++)
  659.               {
  660.                             write_1602dat(start_line[i]);//写显示时间固定符号,两个冒号
  661.               }
  662.               write_1602com(er+9);              //设置光标位置
  663.               write_1602com(0x0f);              //设置光标为闪烁
  664.               Delay5Ms(); //延时片刻(可不要)
  665. ……………………

  666. …………限于本文篇幅 余下代码请从51黑下载附件…………
  667. </font>
复制代码

所有资料51hei提供下载:

4-密码锁毕业论文.doc (5.75 MB, 下载次数: 122)





作者: zhuangjkl2010    时间: 2018-12-17 17:45
强烈支持
作者: Hsocrates    时间: 2019-3-25 13:19
仿真出来按键两边都是高电平,用不了
作者: 小小小张    时间: 2020-2-12 13:58
怎么改密码呢

作者: ljl8970    时间: 2020-3-11 17:00
本密码锁的设计论文思路比较清晰,且值得借鉴,望能发我借鉴  ljl943253633@gmail.com
作者: murenxin0911    时间: 2020-3-13 16:48
很喜欢,有空一定要做一个玩玩!




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1