人们的生活品质不断得到提高,贵重物品也开始渐渐出现在各家庭中,对于普通锁具的安全性能,人们开始担心。虽然,锁具的发明与使用已经拥有悠久的历史了,但是,传统锁具制作简单,内部结构普通单一,使得这些锁具容易被不法分子破坏,给人们的财产安全带来隐患。目前市场的锁具多种多样,人们对于锁具的选择也不再是单一的,传统的类型,一种人性化设计的锁具渐渐受到广大群众的喜爱——指纹密码锁。这类锁与传统的锁具相比最大的优势在于能够根据人的指纹进行开锁,用户可以是一个人,也可以是一家人,只需在指纹密码锁中录入一家人的指纹图像信息,再加上数字密码信息,就可以轻松生成一把属于你自己的智能钥匙,独一无二,让偷窃者无从下手。由此,指纹识别技术与电子密码相结合的锁具渐渐出现在我们生活中,我们自己的手指就是我们打开大门的钥匙,不用担心钥匙弄丢,进不来家门的尴尬现象。该锁只有在指纹身份验证正确和密码输入正确的情况下才执行开锁,超过三次输入不正确会有报警鸣声,以提示我们该用户操作不合法,需要警惕。为我们的生活带来了便捷,提高了我们生活的质量。
为什么会出现这样的问题,指纹电子密码锁与传统的锁具相比有下列的优点与缺点:
第一,在锁具的设计方面上,传统的锁具设计单一,开锁的方式是通过铁质的钥匙,插入锁孔来转动。
第二,对于钥匙管理方面,传统锁具的钥匙经常被不法分子利用,他们通过跟踪钥匙的主人,然后偷窃他们的钥匙,对钥匙进行复制,最后入侵他们的家里进行偷窃。
第三,在锁具的安全性能方面,传统锁具容易被偷窃者破坏,偷窃者只需带上一些小巧精密的工具,就能把锁撬开。
第四,指纹密码锁相对于传统的锁具而言,其最大的优势在于能够利用个人的独一无二的指纹信息和其对应的数字密码进行解锁。能够做到双重保险,让偷窃者无从下手。
经过调查发现,市场上卖的锁大部分都是性能比较低的,人们也为此感到担忧。为了使用更精确,更安全的锁,人们把目光投向了电子密码锁,通过数字的排练方式来开门的锁,这样就解决钥匙丢失和被复制的问题。但是,随着科技的进步,工具的先进发展,有些不法分子开始购买一些专门破解密码的仪器,只要让它连接锁就能快速寻找出开锁的密码。这样的锁还是不够安全,人们又进一步的去探索,在探索过程中,人们发现了一种利用生物指纹识别技术的开锁方式,就是通过检测人的指纹,识别指纹是否是正确指纹,然后进行开门的锁。该锁在数字电子锁的基础上外加了指纹识别的功能,这样就能解决数字密码被破解的风险,起到双重保险的作用。加强了人们财产的安全性,保护了自己的个人财产,减少了不必要的担心。
1.2指纹密码锁课题研究背景历史的火轮在向前,科学技术在更新,锁具的发展也在不停地向前走,从简单的一字型锁、锯齿型锁、摩擦表面锁、到复杂的十字型锁、点阵式的锁、感应芯片式锁、语音开门锁、电子数字密码锁、瞳孔识别锁、指纹识别密码锁等等。其中指纹识别密码锁是人们最喜欢用的一种锁。究其原因如下:第一,指纹识别密码锁相对于语音,感应芯片开锁方式而言,其最大的好处就是不会因为感冒而导致声音发生变化或者芯片不灵敏而导致开不了锁的现象。第二,指纹识别密码锁与十字型锁,点阵式锁的不同之处,在于不用随时携带钥匙,再也不用担心钥匙弄丢,就不了家门,或者被不法分子锁利用对家庭的财产造成损失。第三,指纹识别密码锁与电子数字机密码锁相比,锁具的安全性能更完善,能够起到双重保险的作用。为人们的生产、生活带来便捷,也体现了智能化、人性化的设计理念。因此,指纹识别密码锁具有非常大的发展前景。
锁具的发明也有一段历史了,从古老的商代开始,人们为了保护好自己的家庭财产就去铸铁铺开始研究制作锁具,锁具的出现标志着人们的个人意识开始渐渐萌生,保护私人财产的能力开始渐渐发展。到了我们现代,大家仍然喜欢用锁,锁上我们个人比较隐私的,重要的物品。于是便出现了各种各样的锁具,有锯齿型的、摩擦表面型的、十字型的、点阵式的、语音识别、指纹识别和电子数字密码锁等等。人们开始尝试用各种类型的锁具,对比锁具之间的差异。其中发展得最快的就是指纹识别锁,伴随着第三次工业革命后,计算机的发明和普及,使得计算机对图片的处理能力不断加强,计算机能计算并处理越来越复杂的图片。这就为指纹识别技术奠定了基础,在前期研究算法的过程中,不断编写能够处理图像清晰度的程序,让指纹识别技术能平稳、快速的发展,使之成为最具有发展潜力的一门技术。在1990年之后,全球的指纹识别技术发展趋于成熟化,机密化,当时,只是应用在国家级的刑事案件调查和检察院身份认证的特殊需要中,在一般的民用市场是往往是看不到此类锁具的,只有在个别富豪中才拥有此类锁具。 随着人口的增多,市场的不断扩大化,该类锁具也渐渐开始在民用市场中普及,普通百姓也可以拥有了选择该锁具的权利。很快就在民用的家庭中出现了指纹抽屉锁、指纹笔记本锁、指纹保险柜锁等等,人们渐渐熟悉了指纹识别的开锁方式。
1.3指纹识别技术的介绍指纹识别技术是通过利用人类所特有的指纹来进行对比识别的一项技术。主要是记录下人类指纹的旋转度,条纹差距,条纹波形及指纹的平面受力面积大小,通过计算机进行特殊的算法处理后,能够计算录入指纹与输入指纹之间的相似程度进而判断该指纹是否为正确指纹的过程。
指纹模块一般由感应部分和内部芯片部分组成,感应部分是由红外线闪光的感应斜坡台构成,用户只需在斜坡台上轻轻按下,等待感应模块感应,一般需要录入两次指纹,第一次是初级采集指纹图像,第二次在第一次的基础上继续采集指纹图像,然后两次采集的指纹图像进行合成处理,我们可以在采集的时候设置声音,方便提示我们指纹正在采集,在设计过程中,通过发出滴滴的声音,我们可以清楚的知道指纹已经录入成功了。接下来就是指纹模块的内部芯片开始工作的时候了,内部芯片有自己的工作电路,在单片机的电流输入时通过TTL电平转换,来开启内部芯片的工作电路,工作电路经过放大信号处理后,就可以对指纹图像信息信号进行处理。利用高运算量来提高工作效率,处理之后会把数据存储到特定的地址,方便程序的随时调用。紧接着就可以对我们设置好的指纹进行验证了,转换模式,进入识别模式,将录入指纹的手指放在感应部分的斜坡上就可以看到该模块的感应过程,这时也有声音提示,告诉你识别成功。
当然,如果你想识别更多的指纹的话,在开始工作的时候要设置好指纹的序号,通过排序的方式,依次录入指纹,建立指纹群。同时,也记下自己录入指纹手指的顺序,由于指纹模块可以录入将近1000个指纹,所以不用担心它内存不够,尽可能的多录几组指纹数据,方便开锁使用。
本次设计主要是利用了单片机对指纹模块、按键模块、显示模块、电机开锁模块进行控制的作品设计。是将我们学习过的单片机进行生活运用的设计,本次设计考验了我们学习知识,应用知识的能力。
设计的核心思想是通过单片机与指纹模块、按键模块、电机开锁模块进行串口连接的通信方式,定义单片机与这些模块连接的管脚,通过高低电平的形式来控制各模块的开启与关闭。指纹模块主要负责指纹信息的采集,指纹图像的处理、指纹的存储和指纹模式转换的工作方式;按键模块主要是为用户设置数字密码而提供的,本次设计用了16个按键,有0到9,录入键、删除键、关门键、确定键组成。其中录入键有最高权限密码的设置和清除指纹库的设置,设计中最高权限密码为123456,通过输入最高权限密码可以对指纹及数字密码信息进行更改;清除指纹库的密码为000111,输入后按下确定键就可以对之前所录入的所用指纹、数字机密码信息进行清空处理,还有两个单独的按键是用来设计模式切换和初始化设置。电机开锁模块中用的电机是直流电机,单片机发送高低电平到驱动芯片L298N,直流电机接入L298N芯片的两个管脚,通过设置高低电平的数字排序来控制电机的正反转,假设00为正转,01为反转,这样就能通过程序来控制电机的转动了。显示模块主要是利用LCD12864显示屏来对设计的操作进行显示功能,在单片机中定义头文件,然后编写显示程序,如第一行显示指纹密码系统,第二行显示识别模式或修改模式等等。设计中通过软件来对硬件的操作进行控制,使得设计的各部分内容能够紧密的结合,实现了该技术的应用。
第二章 系统的方案选择和验证 2.1单片机的选择我们在学习过程中所遇到的单片机有51单片机、52单片机、ATmag16单片机、AVR单片机,在这些单片机中,我选择了52单片机来设计本次的设计。
原因如下:
第一,52单片机相对与51单片机来说,拥有更大的内存,其内部数据存储器可以存储256*8字节,比51单片机扩大了一倍。还增加了两个中断源,为程序的中断控制提供了更多的选择;能更好的兼容51单片机。
第二,52单片机相对与ATmag16单片机在编写程序上,52单片机的程序编写比较通俗易懂,容易应用。使用者只要熟悉一下单片机的基本编程过程就能快速的学会编程。
第三,52单片机与ATmag16单片机和51单片机独特的地方就是有2个串行中断接口,可以利用UART通道进行编程。
接下来通过52单片机的管脚图来介绍各管脚在本次设计中所表示的功能,如下图:
图2.1 52单片机引脚图
在本次设计中1引脚至7引脚接数字密码4*4矩阵按键部分,通过高低电平来判断是哪个键被按下,8引脚接切换模式的按键,9引脚接初始化模式的按键。
10引脚与指纹模块的TXD接口相接,11引脚与指纹模块的RXD接口相接,12引脚为外部中断零,通过设置中断来对指纹的识别和修改模式进行切换。13引脚和14引脚接电机开锁模块的L298N芯片的,15引脚接三极管2N3906部分,做为整体电路的报警提示模块。16引脚接入一个红色的发光二极管作为指纹模块的识别模式灯;17引脚接入一个绿色的发光二极管作为指纹模块的录入模式灯。18、19引脚与晶振电容组成晶振电路,本次设计中所用的晶振为11.0592Hz,波特率为9600,不加倍。20引脚为整个电路提供公共的地线;21引脚、22引脚分别接存储模块中存储芯片24C02的SDA、SCL的接口,负责存储数据的通信传送;40引脚为整个电路的电压引脚。
2.2指纹模块的选择与论证目前,市场上出现了多种多样的指纹识别模块,他们的类别大概分为三种:射频指纹模块、半导体指纹模块、光学指纹模块。我在设计的时候选择了光学指纹模块,该模块主要是利用光学的折射和反射原理,当光线从底部射向三棱镜,再从三棱镜射出时,该光线会在手指的表面形成凹凸不平的线条,线条在经过折射后再反射回去,就把指纹的凹凸纹状显示出来了。在经过内部CMOS芯片对图片进行不同程度的处理,就能实现指纹的采集。与半导体指纹模块相比,能够有效的减少了因为传感器感应电容(电感)的差异而造成指纹的采集失败。射频指纹识别与指纹识别相比性能更优,它能通过传感器发射出微量射频信号,然后穿透手指的表层去检测指纹里层的纹路,从而获取指纹的信息图像。防伪指纹能力强,但是由于其模块的造价太贵,所以本次设计没有选择该模块,而是选择了一个功能比较完善的,总体性能偏中等的指纹识别模块。
我在网上几家店进行了对比,最终选择了购买PS1802指纹模块,该模块的组成图片如下:
图2-2 PS1802集成模块实物图
从图中我们可以知道,该模块有四根线伸出来,它们还有颜色的差别,红色的是VCC线,绿色的是指纹模块发送信息的接线,白色的是指纹模块接收信息的接线,黑色的是接入GND的接线。该模块与单片机进行串口通信,单片机发送一个字符字节指令到指纹模块,然后在指纹模块的内部电路中进行寻找字符字节,找到后再发回给单片机,进而它们之间能够完成通信。指纹模块中有数据包识别码,通过单片机的发送中断和接收中断进行数九包识别码的寻址,完成后开始录入用户的个人信息指纹,把指纹信息存储在FIFO中,方便用户的使用。如果你想识别更多的指纹的话,在开始工作的时候要设置好指纹的序号,通过排序的方式,依次录入指纹,建立指纹群。同时,也记下自己录入指纹手指的顺序,由于指纹模块可以录入将近1000个指纹,所以不用担心它内存不够,尽可能的多录几组指纹数据,方便开锁使用。在录入指纹的过程中,有最高权限密码的设置和清除指纹库的设置,设计中最高权限密码为123456,通过输入最高权限密码可以对指纹及数字密码信息进行更改;清除指纹库的密码为000111,输入后按下确定键就可以对之前所录入的所用指纹、数字机密码信息进行清空处理,还有两个单独的按键是用来设计模式切换和初始化设置。
2.3显示模块的选择与论证在平时的课程设计中,我接触了一些显示模块,如VGS12864E、ICL7106、LCD1602、LCD12864。这些显示模块各有各的优点,根据本次设计的需要我选择了LCD12864显示模块。该模块锁具有的优势如下:
第一,VGS12864E与LCD12864相比都能显示128*64行的点阵,但VGS12864E特有OLED图形字符的显示模块,该模块采用了有机发光技术,与LCD12864相比在太阳光直射下,不需要背光源,依然能呈现出清晰的图像和数据。通过低电压来驱动,能在-20℃~70℃的温度下工作,但是由于近年来科技的发展,VGS12864E的生产渐渐减少,现在很难在市场上看到该类显示模块。
第二,ICL7106与LCD12864相比,因为其内部有3个1/2位A/D转换器,因此,能够直接驱动LED数码管。然而,在本次的设计中,显示模块只是应用于屏幕的汉字显示,方便对用户的操作进行提示,没有用到LED数码管,因此,没有选择ICL7106显示模块。
第三,LCD12864是128*64分辨率的点阵,能显示8*4个汉字,也能显示图像效果,与LCD1602相比,显示的汉字多一些,能够显示四行汉字。12864接口有串行和并行两种方式,而1602只有并行的接口方式,不能满足设计者的需求。
经过对比分析考虑后,本次设计最终采用LCD12864液晶显示模块。该模块与单片机的26、27、28、32、33、34、35、36、37、38、39引脚相连接,通过并行的接口方式与单片机进行通信控制,在单片机中定义头文件,然后设置每行显示的文字,以提示用户的操作。在设计中,让第一行的文字显示为指纹密码系统,第二行为识别模式或修改模式,用户可以通过按键进行切换;第三行根据程序的顺序依次显示请录入指纹、请输入密码、密码正确和最右边的密码序号;第四行显示为密码加冒号。这样,用户就能直观的通过屏幕显示来完成指纹密码锁的指纹录入和指纹开锁的过程。
2.4 数字按键部分介绍在作品的设计中,当输入的指纹正确时还需要通过数字密码来解锁,因此就需要一个数字按键模块。在单片机的学习中,我们学习矩阵键盘的应用,为本次设计提供了灵感。本次设计采用了4*4个数的矩阵键盘,有0到9的数字按键和录入键、删除键、关门键、确定键几部分组成。通过设置行线与列线的端口接入点,来定义数字按键的行线与列线,经过编写程序对行、列线进行电平高低的设置,通过高低电平的变化来确定按下的按键,最后在LCD12864液晶显示屏上显示后变成*号,以保护用户的密码不被泄露。
2.5报警部分芯片的选择当用户输入的信息不正确时,输入指纹出错超过三次的情况下或者输入数字密码的次数也超过三次时,系统便会发出警报声,以提示用户输入的信息不正确。同时也警示不法分子,你不是合法用户,没有开门的权利。警报电路由2N3906三极管、电阻和蜂鸣器构成,三极管2N3906是该电路主要芯片。三极管2N3906是分离式半导体类三级管,属于PNP型,低电平导通,正好与蜂鸣器的电压导通性质一样,当低电平通过时,电路开始导通,驱动蜂鸣器发出响声。本次设计的报警电路如下所示:
图2.3警报电路设计图
2.6存储电路模块的介绍存储模块主要应用E平方PROM通信协议进行存储的操作,在仪器仪表及工业自动化控制中得到大量的应用。现在市场上有多种多样的存储芯片,经过方案对比发现24C02芯片是最符合本设计的设计思路,其引脚图如下图2-4所示:
图2-4 24C02引脚图
在设计中,存储模块的5引脚(SCL)与单片机的22引脚相连接,6引脚(SDA)与单片机的21引脚相连接,1引脚、2引脚、3引脚、4引脚都接上GND,让芯片进行读写操作。7引脚、8引脚接VCC,给这个电路提供电源。
第三章 各模块电路的介绍设计中一共有七个电路模块,它们分别是52单片机模块、数字按键模块、指纹识别模块、LCD12864液晶显示模块、存储模块、电机模拟开锁模块和总体电源模块。我们在本章中将对以上内容进行详细介绍。
3.1数字按键模块电路的介绍在作品的设计中,当输入的指纹正确时还需要通过数字密码来解锁,因此就需要一个数字按键模块。作品中有16个按键,它们分别是0到9数字按键和录入键、删除键、关门键、确定键。在单片机中进行编写程序,设置好行线与列线的端口接入点,来定义数字按键的行线与列线,经过编写程序对行、列线进行电平高低的设置,通过高低电平的变化来确定按下的按键。数字按键模块的电路如下所示:
图 3.1数字按键模块电路
3.2 指纹识别模块电路的介绍设计中的指纹模块内部有一个高度集成的芯片,该芯片有自己的工作电压,当单片机的电压经过芯片时会在内部电路中进行转换,形成芯片的工作电压。指纹模块有存储指纹的存储空间,一般能存储1000枚指纹,因此,不用担心指纹模块不够存。本次设计所选用的是光学指纹模块,在修改模式下,可以对指纹模块录入指纹信息,用户把手指放在指纹模块的斜坡上,光线会在手指的表面形成凹凸不平的线条,线条在经过折射后再反射回去,就把指纹的凹凸纹状显示出来了。然后通过听滴滴声来判断指纹是否录入成功;在模块进入识别模式时,指纹模块会发出红色的光,当用户的指纹放在指纹模块的斜坡上时,通过看显示屏幕或者听声音就能知道指纹是否识别。指纹识别模块电路图如下:
图3.2指纹模块电路图
指纹模块在修改模式下的工作过程:
- 等待指纹模块的红色光不再闪烁时,表示顺利进入修改模式;
- 进入修改模式后,按照屏幕提示进行指纹录入操作;
- 尽量选择大拇指和食指进行录入,这两个手指录入比较能够容易录入进去;
- 在听蜂鸣器发出滴滴声时,表示录入成功。
指纹模块在识别模式下的工作过程:
- 按下切换按键,把修改模式切换成识别模式;
- 识别模式切换后,指纹模块会发出红色的闪光;
- 按下之前已录入的手指的指纹;
- 等待指纹识别,当听到滴滴两声时,指纹识别成功。
3.3LCD12864显示模块电路介绍本次设计中使用的是LCD12864液晶显示模块,该模块能显示128*64字符的汉字,屏幕比较大,可以显示四行的汉字,与单片机通过并行的接口方式进行通信,定义每一行所代表的语句,来对操作者进行提示。具体电路图如下:
图3.3 LCD12864显示模块电路
该模块与单片机的26、27、28、32、33、34、35、36、37、38、39引脚相连接,通过并行的接口方式与单片机进行通信控制,在单片机中定义头文件,然后设置每行显示的文字,以提示用户的操作。在设计中,让第一行的文字显示为指纹密码系统,第二行为识别模式或修改模式,用户可以通过按键进行切换;第三行根据程序的顺序依次显示请录入指纹、请输入密码、密码正确和最右边的密码序号;第四行显示为密码加冒号。这样,用户就能直观的通过屏幕显示来完成指纹密码锁的指纹录入和指纹开锁的过程。
3.4存储模块电路的介绍经过比较发现24C02芯片最符合本设计的设计思路,因为24C02有256字节,能存储40组数字密码,当系统因为一些不可预计的原因导致断电,存储模块电路能把掉电前的数据保存下来,等到下次上电的时候,能继续工作。芯片的工作电压为1.8V到5.5V,串行接口,兼容I2C总线;能对硬件进行写保护,具有高度的可靠性,擦写寿命达到100万次,是现代智能仪表的首选芯片之一。
存储模块电路图如下:
图 3.4 存储模块电路图
3.5电机模拟开锁模块电路的介绍本次设计应用了L298N芯片作为电路的核心芯片,该芯片的工作电压为4.5V至46V,考虑到稳定性,本电路的工作电压为12V,一共有15个管脚。有四个输入口与输出口,一般情况下,能驱动一台两相的步进电机或者四相的步进电机,两台直流电机。此次设计采用了直流电机,通过输出的高低电平来控制电机的正反转,如假设OUT1、OUT2=00代表电机正转,OUT1、OUT2=01代表电机反转。电机模块开锁电路图如下:
图 3.5电机模拟开锁电路图
从电路图中,我们可以看到八个IN4007二极管构成“H桥”,这些二极管在电路中起到续流的作用,还有两个电容,C1、C2在电路中作为两个滤波电容,以防止一些电流的不稳定所造成的干扰,C1是用来吸收低频干扰的,C2是用来吸收高频脉冲干扰的。电路中要想控制电机转动的速度,取决于控制脉冲,给直流电电机一个控制脉冲时,电机就转动一步,再发一个脉冲,会再转一步,当两个脉冲的时间间隔越短时,电机就转动得越快。在本模块中的电源电压为12V,该电压能够使L298N芯片正常驱动电机,让电机转动,成功实现模拟开锁的过程。
3.6 总体电源模块电路的介绍电路的正常运转需要电源,因此,本设计还需要一个稳定的,实用的电源模块对整个设计提供电源。因为各电路需要的电压不同,所以设置正负5V、正负12V、正负15V的电压源。下图3.6是总体电源电路:
图3.6 总体电源模块电路图
从电路图中,可以看到该电路设计提供了正负5V、正负12V、正负15V的电压,在图的最右边有一个红色的发光二极管,当电路正常运行时,就会亮起,提示操作者该电路没有障碍,能够正常使用。电路的工作原理:当220V交流电经过桥式二极管整流后,再通过C1、C2、C3、C4电容进行滤波处理,之后得到300V直流电压,该电压经过LM7815、LM7915稳压管后变成正的15V电压和负的15V电压,在电路傍边接两个端口作为正负15V电压的输出;这两个电压经过C5、C6、C7、C8电容的高频滤波,进入LM7812、LM7912稳压管,就得到了正负12V的电压,外接两个端子作为正负12V的输出端;通过同样的方式,继续把电压进行滤波处理后,流向LM7805、LM7905使得输出的电压达到正负5V。设计中,单片机的电源电压为5V,一般来说,5V电压能够让电路正常运行;在电机模拟开锁驱动电路中的电源电压为12V,该电压能够使L298N芯片正常驱动电机,让电机转动,成功实现模拟开锁的过程。
第四章 系统的软件调试
4.1开锁电路调试及流程图设计以上介绍了设计的硬件电路部分,现在开始介绍设计中的软件设计与调试过程,程序设计中,用了C语言来进行编程,C语言是我们之前开设的一门课程之一,我们能够运用C语言来编写程序,能够比较熟练地应用C语言去解决课程所要完成的课程设计要求。设计中本着程序语言简洁、能实现功能为前提,尽可能的使用一些我们所学过的知识去编写,以达到学以致用的效果。接下来,可以通过下面的流程图来展示。
第一步,调整模式,将当前的识别模式通过模式切换按键切换成修改模式,在该模式下进行指纹图像信息的采集与录入;第二步输入最高权限密码,本设计的最高权限密码为123456,输入完成后就可以进入下一步;第三步指纹信息图像录入,定义单片机中连接指纹模块的引脚,设置好连接方式后,在程序中编写指纹录入程序,要录入两次指纹,进行指纹图像的对比和采集;第四步指纹信息图像处理,程序对所搜集到的指纹图像信息进行合成、加工,让图像更加清晰,然后把该指纹信息存储指定的地址(Carch)中;第五步设置数字密码,指纹图像信息录入正确后,开始数字密码的录入,用户设置自己的用户密码,该密码存储在24C02芯片中,24C02能够存储40组数字密码;第五步切换为识别模式,在识别模式下进行开锁的演示操作;第六步识别指纹,将用户之前录入过指纹的手指放在指纹模块的斜坡上,程序中设计了这两次指纹信息图像的相似程度和对比度,通过数据计算能够知道录入的指纹与识别的指纹是否匹配,从而判断出该指纹的用户是否是本人,识别指纹的过程中应用了C语言的for循环语句,当用户的指纹没有识别出时,可以继续跳转到识别模式下的程序,继续进行指纹识别的操作,循环六次后,如果还不能识别指纹时,系统便会发出警报,提示该用户的指纹不正确,或者已经有非用户者入侵了;第七步数字密码的输入,当指纹识别成功时,开始进入数字密码输入步骤,程序中应用了for循环语句,用CC来表示,输入密码错误时,可以继续跳回输入密码,当密码输入错误三次时,系统的警报会响起,警报该用户所输入的数字密码不正确,这时,用户就要小心了,可能有不法分子侵入了。第八步开锁过程,当指纹识别成功,数字密码输入正确时,程序会执行开锁的操作,单片机的电压通过25管脚传输到L298N芯片上,芯片内部经过电平转换把输出的电压送到OUT1、OUT2管脚以驱动电机转动,实现开锁过程的模拟。整个设计流畅地体现了指纹密码锁设计的解锁的过程。
4.2 设计中的特殊开锁方式生活中,有时候我们的手指受伤了,导致不能正常的开锁,这个时候就需要更改录入的手指,或者直接用最高权限密码去设置开锁环节。我们可以在录入指纹的时候,多录入几个手指的指纹,以备不时之需,当我们录入的手指中的一个手指的指纹受损了,我们还可以用其他的手指指纹进行开锁,避免了用户自己进不了家门的尴尬局面。不过,我们也可以输入最高权限密码,输入完成后,再选择一个指纹完全的手指,重新录入,录入后就直接开锁。这样就能够有效的避免了用户忘记是用哪个手指的指纹录入或者是忘记了数字密码后不能正常开锁的情况发生。该最高权限密码一般只有用户自己知道,而且该密码已经写在程序中,如果用户想要更改,也可以找到编写该密码的部分自己进行修改,但是用户一定要记得自己设置的最高权限密码,不要轻易的与不熟悉的人说这个密码,以防止不法分子利用它来破解开锁,对人们的生产、生活造成影响。当指纹信息存储过多时,我们要怎么删除我们之前存储的指纹呢?在设计中也考虑了清除指纹的操作,在修改模式下,按下输入键,输入000111后,按下确定键,就能把之前存储过的指纹图像信息全部删除;同时,数字密码也能删除。这样用户就又可以重新设置指纹信息图像和数字密码了。
第五章 作品总结
5.1作品设计过程在作品的设计过程中,遇到了很多问题,如最开始的单片机、指纹模的选择、电路的整体设计思路。在一个多月的摸索中,最后确定用哪个方案进行系统设计。设计完成后便开始画电路图,选择元器件的封装,连线画图。弄好之后就把电路图转印到铜板上,检查电路是否有断线的,不清楚的,做好补漏的工作。之后就开始焊接电路,把元器件按照电路的排放依次焊接到电路图上,测试电路是否能正常运行。最后在把已经编写好的程序下载到单片机中,运行程序,看各模块的功能是否能实现,然后再根据各模块的情况进行修改。
设计中有显示屏可以对用户的操作进行提示,按键模块的设计也是按照人们的思维从左到右的数字增加方式,而且确定按键、输入按键、删除按键都标有文字说明。存储部分能够考虑到整体电路断电时,数据信息还能存储到芯片中,当系统上电后,还能调出存储的数据信息继续进行工作;通过设置最高权限密码可以对锁进行重新设置,开锁过程的设计也是比较人性化的,当用户的指纹识别正确和数字密码输入无误时,按下确定键锁会转动,以实现开锁功能,开锁之后用户只需按下关门键,就会看到锁具朝着相反的方向转动,从而达到关门的效果。
附录一系统整体电路图:
附录二主程序:
- #include
- #include
- #define uchar unsigned char
- #define uint unsigned int
- #include " LCD12864.h "//里面定义了12864液晶的端口接法以及 12864程序声名
- #include "24c02.h"
- sbit buzzer=P3^5; //蜂鸣器引脚
- sbit A1 =P2^2;
- sbit B1 =P2^3 ;
- sbit anjian=P2^4;
- sbit red=P3^7;//录入模式指示灯 在板子靠近单片机处
- sbit green= P3^6;//识别模式指示灯 在板子远离单片机处
- sbit key=P3^2; //中断
- #define FALSE 0
- #define TURE 1
- #define MAX_NUMBER 30
- #define _Nop() _nop_()
- unsigned char SaveNumber=0,searchnum=0;
- unsigned int SearchNumber=0,clk0=0;
- bit modeflag= 0 , clearallflag=0, changeflag=0;
- //默认为识别模式
- //如果为1为录入指纹模式,每录入一次SaveNumber++
- unsigned char FifoNumber=0;
- unsigned char idata FIFO[MAX_NUMBER+1]={0};
-
- void TxdByte(unsigned char dat)//串口发送信息,通过查询方式发送一个字符
- {
- TI = 0; //让TI=0
- SBUF = dat; //读入数据
- while(!TI); //等待发送完毕
- TI = 0; //清零
- }
- uchar Command(unsigned char *p,unsigned char MaxTime) //命令解析,给模块发送一个命令 *p 数组 MaxTime*17ms 循环时间
- {
- unsigned char count=0,tmpdat=0,temp=0,i=0,package=0,flag=0,checksum=0;
- uchar result=0, start=0,stop=0;
- TxdByte(0xef);//数据包包头识别码
- TxdByte(0x01);//数据包包头识别码
- i=*p;//数组的第"0"个元素、里面存放了本数组的长度,把这个长度给变量i,方便进行操作
- p++;
- p++;
- for (count=i-1; count!=1;count--) //Sent command String
- {
- temp=*p++;//取第个"1"个元素的内容,然后发送
- TxdByte(temp);//将数据发送出去
- }
- //以上完成了对数组的全部发送
- result=TURE;//发送完成,结果为真 (真为1)
- FifoNumber=0;
- for (count=MAX_NUMBER+1; count!=0; count--)//清空所有FIFO[]数组里面的内容,写入0X00
- {
- FIFO[count-1]=0x00;
- } //用于存贮所有接收到的数据
- if (result) //如果result=TURE成立
- {
- result=FALSE; //result清零
- start =FALSE;
- stop =FALSE;
- count=0;
- clk0=0; //清零CL0计数
-
- /////////////////////////do的内容////////////////////////////////
- {
- restart0:
- if (RI==1)//如果接收到数据
- {
- tmpdat=SBUF;//先把接收到的数据放到tmpdat中
- RI=0;
- if ((tmpdat==0xef)&&(start==FALSE))//这个数据为第一个传回来的数据,也就是"指令应答"的第一个字节
- {
- count=0;
- FIFO[0]=tmpdat;//读入第一个应答字节(0XEF),存在第"0"个元素中
- flag=1;
- goto
- restart0;//可以用中断方式进行
- }
- if(flag==1)//第一个字节已经回来,所以flag==1成立
-
- ///////////////////////do的内容结束//////////////////////////////
- while ((clk0<=MaxTime)&&(count<=MAX_NUMBER) && ( changeflag == 0 ));
- //由定时器以及最大接收数据来控制,保证不会在此一直循环
- FifoNumber=count; //保存接收到的数据个数
- }
- return (result);
- }
- bit VefPSW(void)//验证设备握手口令,成功返回1
- {
- unsigned char count=0;
- while (1)
- {
- if(Command(VPWD,20) && (FifoNumber==11) && (FIFO[9]==0x00))
- {
- return (1) ;
- }
- count++;
- if (count>=2)//如果不成功,再验证一次,如果两次不成功,返回失败
- {
- return(0);
- }
- }
- }
- void Clear_All(void) //清空指纹库
- {
- delay1ms(200);
- Command(DELE_all,50); //清空指纹库
- }
- unsigned char ImgProcess(unsigned char BUFID) //发获取图像并生成特征文件,存入BUFID中//输入参数为缓冲区号
- {
- if(Command(GIMG,89) && (FifoNumber==11) && (FIFO[9]==0x00))
- {
- if(BUFID==1)
- {
- if(Command(GENT1,60) && (FifoNumber==11) && (FIFO[9]==0x00))
- {
- return 1;
- }
- }
- else if(BUFID==2)
- {
- if(Command(GENT2,60) && (FifoNumber==11) && (FIFO[9]==0x00))
-
- return 255; //由于只有162个指纹,如果返回255,表示这个指纹识别失败
- }
- }
- i++;
- }
- return 0;
- }
-
- bit savefingure(unsigned char ID)//保存指纹
- {
- unsigned char i=0;
- //现在开始进行存储指纹模板的操作
- for (i=0;i<16;i++) //保存指纹信息
- {
- FIFO[i]=STOR[i];
- }
- FIFO[12]=ID; //把指纹模板存放的PAGE_ID也就是FLASH的位置
- FIFO[14]=FIFO[14]+ID; //校验和
- if (Command(FIFO,70)==1)//不成功返回0 //此处进行存放指纹模板的命
- {
- return(1);
- }
-
- return (0) ; //不成功返回0
- }
- unsigned char enroll(void) //采集两次指纹,生成1个 指纹模板
- {
- unsigned char temp=0,count=0;
- delay1ms(30);
- while(1)
- {
- temp=ImgProcess(1); //生成特征1
- if ( temp == 1 )//生成特征文件成功
- {
- break;
- }
- else
- {
- if ( temp == 0 )//采集指纹没有成功
- {
- count++;
- if (count>=40)//如果采集了40次,还不成功,直接采集失败,直接退出enroll函数----返回0
- return(0);
- }
- }
- }
- count=0;
- buzzer=0;
- delay1ms(100);
- buzzer=1;
- delay1ms(2000);//延时2S开始采集下一个特征
- //开始采集第二个特征
- while(1)
- {
- temp=ImgProcess(2); //生成特征2
- if (temp==1)//生成特征文件2成功
- {
- if ( (Command(MERG,40)&& (FifoNumber==11) && (FIFO[9]==0x00))==0 ) //合并不成功返回0,成功返回1
- {
- return(0);
- }
- else//特征文件合并生成模板,结果存于ModelBuffer
- {
- buzzer=0;
- delay1ms(100);
- buzzer=1;
- delay1ms(100);
- buzzer=0;
- delay1ms(100); //响两声,表示生成一个模板成功
- buzzer=1;
- return 1;
- }
- }
- else //采集指纹没有成功
- {
- count++;
- if (count>=25)
- {
- return(0);
- }
- }
- }
- }
- void modecheck(void)
- {
- if(modeflag==0)
- {
- green=0;
- red=1;
- display(1); //识别模式
- }
- else if(modeflag==1)
- {
- red=0;
- green=1;
- display(2); //录入模式
- }
- numshow(0);
- }
- void init_sys() //端口初始化
- {
- ET0=1; //定时器0开中断
- TL0=0x97;
- TH0=0xBD; //17ms的初值
- //串口初始化
- SCON=0x50; //UART方式1:8位UART; REN=1:允许接收
- PCON=0x00; //SMOD=0:波特率不加倍
- TMOD=0x21; //T1方式2,用于UART波特率
- TH1=0xFD;
- TL1=0xFD; //UART波特率设置:9600
- TR1=1;
- TR0=1;// 开定时器0
- EX0=1; //开外中断
- IT0=1;
- IT1=1;
- EA=1; //开全局中断
- }
- void woshou()
- {
- unsigned char i=0;
- for(i=0;i<6;i++)//开始握手6次,如果没有一次成功,表示模块通信不正常。只要成功就跳出此循环
- {
- if(VefPSW())//与模块握手通过,绿灯亮起。进入识别模式
- {
- display(3); //握手成功
- red=0;
- buzzer=0;
- delay_1ms(1000);
- buzzer=1;
- delay_1ms(1000); //显示3秒握手状态
- modecheck(); //显示当前是什么状态
- break;
- }
- else
- {
- display(4); //握手失败
- break;
- }
- }
- }
- unsigned char key_sm()
- {
- unsigned char i,temp;
- P1=0xf0;
- temp=P1;
- if(temp!=0xf0)
- {
- delay1ms(10);
- if(temp!=0xf0)
- {
- /////////////////////第一行扫描/////////////////////
- P1=0xfe; //1111 1110
- temp=P1;
- switch(temp)
- {
- case(0xee):buzzer=0;delay1ms(200);buzzer=1;n++;if(n>7){n=7;} //输入0
- write_12864dat(num[10]);delay1ms(1);write_12864dat(num[10]);
- break;
- case 3:passwd[2]=2;write_12864com(0x98+4); delay1ms(1);write_12864dat(num[2]);delay1ms(100);
- write_12864com(0x98+4); delay1ms(1);write_12864dat(num[10]);
- break;
- case 4:passwd[3]=2;write_12864com(0x98+4); delay1ms(1);write_12864dat(num[10]);delay1ms(1);
- write_12864dat(num[2]);delay1ms(100);write_12864com(0x98+4);delay1ms(1);
- write_12864dat(num[10]);delay1ms(1);write_12864dat(num[10]);
- break;
- case 5:passwd[4]=2;write_12864com(0x98+5); delay1ms(1);write_12864dat(num[2]);delay1ms(100);
- write_12864com(0x98+5); write_12864dat(num[3]);delay1ms(100);write_12864com(0x98+4);delay1ms(1);
- write_12864dat(num[10]);delay1ms(1);write_12864dat(num[10]);
- break;
- }
- break;
- }
- ////////////////////第二行扫描/////////////////////
- P1=0xfd; //1111 1101
- temp=P1;
- switch(temp)
- {
- case(0xed):buzzer=0;delay1ms(200);buzzer=1;n++;if(n>7){n=7;} //输入4
- switch(n)
- {
- ); delay1ms(1);write_12864dat(num[10]);delay1ms(1);
- write_12864dat(num[4]);delay1ms(100);write_12864com(0x98+4);delay1ms(1);
- switch(n)
- {
- case 1:passwd[0]=5;write_12864com(0x98+3); delay1ms(1);write_12864dat(num[5]);delay1ms(100);
- write_12864com(0x98+3);
- break;
- case 4:passwd[3]=5;write_12864com(0x98+4); delay1ms(1);write_12864dat(num[10]);delay1ms(1);
- write_12864dat(num[5]);delay1ms(100);write_12864com(0x98+4);delay1ms(1); write_12864dat(num[10]);delay1ms(1);write_12864dat(num[10]);
- break;
- case 5:passwd[4]=5;write_12864com(0x98+5); delay1ms(1);write_12864dat(num[5]);delay1ms(100);
- write_12864com(0x98+5); delay1ms(1);write_12864dat(num[10]);
- break;
-
- write_12864com(0x98+4); delay1ms(1);write_12864dat(num[10]);
- break;
- case 4:passwd[3]=7;write_12864com(0x98+4); delay1ms(1);write_12864dat(num[10]);delay1ms(1);
- write_12864dat(num[7]);delay1ms(100);write_12864com(0x98+4);delay1ms(1); write_12864dat(num[10]);delay1ms(1);write_12864dat(num[10]);
- break;
- }
- ////////////////////////第三行扫描/////////////////////
- P1=0xfb; //1111 1011
- temp=P1;
- switch(temp)
- {
- case(0xeb):buzzer=0;delay1ms(200);buzzer=1;n++;if(n>7){n=7;} ///输入8
- switch(n)
- {
- case 1:passwd[0]=8;write_12864com(0x98+3); delay1ms(1);write_12864dat(num[8]);delay1ms(100);
- write_12864com(0x98+3); delay1ms(1);write_12864dat(num[10]);
- break;
- case 2:passwd[1]=8;write_12864com(0x98+3); delay1ms(1);write_12864dat(num[8]);delay1ms(100);
- write_12864com(0x98+5); delay1ms(1);write_12864dat(num[10]);
- break;
- case 6:passwd[5]=8;write_12864com(0x98+5); delay1ms(1);write_12864dat(num[10]);delay1ms(1);
-
- write_12864com(0x98+3); delay1ms(1);write_12864dat(num[10]);
- break;
- case 2:passwd[1]=9;write_12864com(0x98+3); delay1ms(1);write_12864dat(num[10]);delay1ms(1); write_12864dat(num[9]);delay1ms(100);write_12864com(0x98+3);delay1ms(1); write_12864dat(num[10]);delay1ms(1);write_12864dat(num[10]);
- break;
- case 3:passwd[2]=9;write_12864com(0x98+4); delay1ms(1);write_12864dat(num[10]);delay1ms(1);
- write_12864dat(num[9]);delay1ms(100);write_12864com(0x98+5);delay1ms(1); write_12864dat(num[10]);delay1ms(1);write_12864dat(num[10]);
- break;
- }break;
- case(0xbb):break;
- case(0x7b):break;
- }
- ////////////////////////第四行扫描/////////////////////
- P1=0xf7; //1111 0111
- temp=P1;
- switch(temp)
- {
- case(0xe7):buzzer=0;delay1ms(200);buzzer=1;aa=0;break;//录入一个指纹 case(0xd7):buzzer=0;delay1ms(200);buzzer=1;n=0;write_12864com(0x98+3); delay1ms(1);
- for(i=0;i<6;i++){ passwd[i]=0;write_12864dat(' ');delay1ms(1);}
- break; //更正
- case(0xb7):buzzer=0;delay1ms(200);buzzer=1;n=0;break; //退出
- case(0x77):buzzer=0;delay1ms(200);buzzer=1;n=0;bb=1;; break; //确认摁键
- }
- }
- }
- }
- void main(void)
- {
- //unsigned int ;
- unsigned char cc=1,t,ii=0,addra=0,c,flag_1=0; //CC为密码错误次数,ii为密码个数
- initdisplay(); //显示初始化
- init_sys(); //开启定时和中断
- woshou(); //握手状态
- init_24C02();//24C02初始化
-
- while(1)
- {
- if( modeflag==0 )//识别模式
- {
- searchnum=search(); //识别指纹号
- if(searchnum>=1 && searchnum <= 162 )
- {
- display(7); //识别成功
- numshow(searchnum);//显示搜索到的指纹号
- buzzer=0;
- delay1ms(100);
- buzzer=1;//蜂鸣器响
- //read_num(5); //指纹识别成功
- delay1ms(500);
- display(12);//输入密码
- aa=1;
- c=1;
- cc=0;
- while(aa)
- {
- key_sm();
- if(bb==1) //等待密码输完摁下确定键
- {
- bb=0;
- for(t=0;t<6;t++)
- {
- passwd1[t]=read_add((searchnum-1)*6+1+t); //从24C02中读出原密码
- delay1ms(10);
- }
- if((passwd[0]==passwd1[0])&&(passwd[1]==passwd1[1])&&(passwd[2]==passwd1[2])&&(passwd[3]==passwd1[3])&&(passwd[4]==passwd1[4])&&(passwd[5]==passwd1[5])) //比较密码
- {
- display(15);
- for(ii=0;ii<6;ii++)
- {
- passwd[ii]=0;
- passwd1[ii]=0; //密码归零
- }
- //read_num(5);
- dianji=0; //电机转动
- cc=0;
- red=0;
- //relay=0;
- delay1ms(2000);
- delay1ms(2000);
- delay1ms(1000);
- //relay=1;
- red=1; //关灯
- buzzer=0; //蜂鸣器响起
- delay1ms(10000);
- buzzer=1; //蜂鸣器关闭
- dianji=1; //电机关闭
- }
- else
- {
- write_12864com(0x98+3); //调用12864写命令
- for(ii=0;ii<6;ii++) //清6个密码
- {
- write_12864dat(' '); //调用12864写数据
- delay1ms(1);
- passwd[ii]=0; // 清零密码
- }
- cc++;
- if(cc>=3) //密码输入错误3次的话
- {
- cc=0;
- aa=0;
- c=0;
- buzzer=0;
- delay1ms(1000);
-
- buzzer=1;
- }
- buzzer=0;
- delay1ms(500);
- buzzer=1; //密码错误
- }
- }
- }
- }
- if(searchnum==255)//指纹识别失败
- {
- //蜂鸣器响三声
- //read_num(6); //指纹识别失败
- display(8);//指纹识别失败
- numshow(0);
- buzzer=0;
- delay1ms(100);
- buzzer=1;
- delay1ms(100);
- buzzer=0;
- delay1ms(100);
- buzzer=1;
- }
- }
- if(modeflag==1)
- {
- while(aa==1)
- key_sm();//输入密码模式
- while(aa==0) // 等待摁下录入一个指纹键
- {
- display(12);//输入密码
- key_sm();//
- if(bb==1)//输完6位且已经摁下确认键
- { if((passwd[0]==passwd3[0])&&(passwd[1]==passwd3[1])&&(passwd[2]==passwd3[2])&&(passwd[3]==passwd3[3])&&(passwd[4]==passwd3[4])&&(passwd[5]==passwd3[5]))//核对的是最高权限密码passwd3密,清除指纹库和密码
- {
- Clear_All();//清除指纹库
- write_add(0x00,0x00);//把24c02里面的指纹号也清零
- display(17);//清空指纹库
- delay1ms(5000);
- display(16); //" 号"
- display(15); //
- for(ii=0;ii<6;ii++)
- {
- passwd[ii]=0; //密码保存成功
- }
- aa=1;
- } if((passwd[0]==passwd2[0])&&(passwd[1]==passwd2[1])&&(passwd[2]==passwd2[2])&&(passwd[3]==passwd2[3])&&(passwd[4]==passwd2[4])&&(passwd[5]==passwd2[5]))//核对的是最高权限密码passwd2密码
- { SaveNumber=read_add(0x00); //把上一次的指纹号读出来
- display(10);//请录入指纹,在第三行显示
- if(savefingure(SaveNumber+1)==1) if( SaveNumber<162 )//模块握手成功
- {
- if(enroll()==1)// 采集两次生成一个指纹模板
- {
- SaveNumber=read_add(0x00); //把上一次的指纹号读出来,
- if(savefingure(SaveNumber+1)==1)//保存也成功
- //if(flag_1 {
- display(14);//录入成功
- SaveNumber=read_add(0x00); //把上一次的指纹号读出来,
- SaveNumber++;//指纹个数加1
- zhiwen++; //指纹个数加1
- delay1ms(1000);
- numshow(SaveNumber);//显示录入指纹号
- write_add(0x00,SaveNumber);
- bb=0;
- display(9);//请设置密码,在第三
- delay1ms(1000);
- display( 15);//请输入密码,在第三行显示
- while(bb==0)//等待密码再次输入完,摁下确认键
- key_sm(); //输入密码
- for(ii=0;ii<6;ii++)
- { write_add((SaveNumber-1)*6+1+ii,passwd[ii]);//把数据密码存到24c02里面去
- delay1ms(10);
- passwd[ii]=0; //密码保存成功 }
- display(13); //密码设置成功
- delay1ms(3000);
- display(15); //
- display(16); //" 号"
- aa=1;
- bb=0;
- flag_1=0;
- }
- }
- else
- {
- display(6);//录入失败
- delay1ms(1000);
- display(11);//请复位
- aa=1;
- bb=0;
- }
- }
- else
- {
- display(6);//录入失败
- delay1ms(1000);
- display(11);//请复位
- aa=1;
- bb=0;
-
- }
- }
- }
- }
- }
- }
- }
- ////////////////////////////中断////////////////////////////////
- void Timer0(void) interrupt 1//定时器
- {
- TL0=0x97; //17ms
- TH0=0xBD;
- clk0++; //
- }
- void int0 () interrupt 0
- {
- if(key==0)
- { delay_1ms(10); //消抖
- if(key==0)
- { while(key==0);
- buzzer=0;
- delay1ms(300);
- buzzer=1;
- modeflag=~modeflag; //通过摁键切换模式
- modecheck();
- //if(modeflag==0)
- // woshou();
- }
- }
-
-
-
-
复制代码
以上内容word文档下载: