基于单片机的指纹采集识别系统设计

目 录

摘 要 I

Abstract II

引 言 3

1 硬件选择与设计 5

1.1 总体设计及方案选择 5

1.1.1主控单片机选择 5

1.1.2传感器模块选择 6

1.1.3显示器模块选择 6

1.2 系统总体设计 7

2 系统硬件电路设计 8

2.1 系统主电路设计 8

2.1.1 主体电路设计 8

2.1.2 单片机最小系统设计 8

2.2 单元电路设计 10

2.2.1 传感器单元 10

2.2.2 显示屏单元 11

2.2.3 数据储存器单元 13

2.2.4 蜂鸣器单元 15

2.2.5 矩形键盘单元 15

2.3 驱动电路设计 16

3 系统软件设计 17

3.1 软件开发环境介绍 17

3.2 系统函数介绍 17

3.2.1 主函数设计 17

3.2.2 AS608传感器子函数设计 18

3.2.3 显示屏函数设计 19

3.2.4 矩形键盘函数函数设计 19

4 项目组装与调试 20

4.1 系统硬件调试 20

4.2 软硬件联调 21

4.3 调试遇到的问题及解决 22

参考文献 24

附录 源程序清单 26

致 谢 38

摘 要

为了探索现代锁具的发展,提高指纹锁的安全性。本课题将基于单片机开发一款低成本,低功耗的指纹识别系统。

随着科学技术的不断提高和发展,越来越多的高科技产品走入日常生活中,给人们带来了很多生活上的便利,在人们心中的地位也越来越高,它们可以应用于家庭生活的各个领域。这些技术的发展,有效的带动了人民生活水平提高,满足了人们更多的需求,逐渐替代了一些传统的生活必需品。

在日常生活中,锁具无处不在。相对于传统的机械锁具构造较为简单,容易破解,电子锁程序复杂,安全系数高,更加智能化,广泛应用于防盗门、保险柜,颇受国内外家庭喜欢。根据目前市场调查,民众表示指纹锁的价格有些偏高,一款普通指纹锁售价大概在一千元左右,如果是带有指纹识别的防盗门普遍价格在四千元到八千元,品牌高质量的指纹锁或防盗门价格会更高,而且民众对性能方面不希望过于花哨,具备指纹和密码开锁功能就足够了,类似手机遥控等功能越多相反可能会造成门锁更不安全。本课题根据大众提供的建议计划利用STC89C52单片机为本系统的主要控制核心,通过液晶显示屏显示AS608指纹传感器识别的结果信息,并且具备密码功能,双重保障。从一定程度上可以更加保证安全性。通过多次测试结果表明,本套系统预想的各种功能可以实现,达到本课题的全部要求。

关键词:52单片机;指纹识别;电子锁;矩形键盘

Abstract

In order to explore the development of modern locks, improve the security of fingerprint locks. This project will develop a low-cost, low-power fingerprint identification system based on single-chip microcomputer.

With the continuous improvement and development of science and technology, more and more high-tech into daily life.In the hearts of people more and more high status. they can be applied to all fields of domestic life. The development of these technologies has effectively led to the improvement of people's living standards, It met people's various needs, and gradually became the necessities of life.

In life, we can see locks everywhere. Compared with the traditional mechanical locks, they are relatively simple construction, and electronic locks complex procedures, high safety factor, widely used in security doors, safes, quite popular with domestic and foreign families.According to the current market survey, people said that the price of a fingerprint lock is a bit high, the price of an ordinary fingerprint lock is about one thousand.if the general price of a security door with fingerprint identification is between four thousands and eight thousands, the price of a brand high-quality fingerprint lock or security door will be higher, and people do not want too much performance. It is enough to have a fingerprint and password unlock function, the more functions such as mobile phone remote control more fancy, on the contrary may cause the door lock more unsafe.Using STC89C52 single chip microcomputer as the main control core of the system, the result information of fingerprint sensor identification can be displayed AS608 LCD screen, and has the function of password, double guarantee. to some extent, it can be more secure. The results of many tests show that the various functions of this system can be realized .All the requirements of this project can be achieved.

Keywords: Singlechip; Fingerprint Identification;Electronic Lock; Rectangular keyboard

引 言

进入21世纪,伴随着现代科学技术的迅速发展,人们研究的领域一步步的扩大,同时很多科技产品走入家家户户,电子产品充斥着人们的生活,社会的和谐富足也使人们对安全提出了更高的要求,在科技国防领域,为了保证国家的机密数据安全,科学家们一般采用多种高端加密技术来确保安全。其中最早应用的指纹识别技术,如今已经不再是尖端科技,逐渐进入生活的方方面面,银行和智能手机普遍都安装了指纹识别系统。

指纹是人的手指皮肤上出现的不同图案,这种圈型纹线起点、分点、终点统称为指纹的细节特征点。而指纹识别技术恰恰就是指通过比较这些不同的细节特征点来进行身份确认。因为我们每个人的指纹都是不同的,而且一生都不会改变,所以通过查看指纹几乎就可以判断这个人是谁,公安机关的数据库中拥有全国公民的指纹数据,所以一旦在犯罪现场采集到指纹,那么犯人可以说在劫难逃。整个指纹识别步骤复杂,包括了图像获取增强,分割细化最后提取出特征点再与库中的指纹匹配,就可以得出结果。

在许多生物特征识别的技术中,指纹识别被人们广泛接受,原因就在于它安全、准确、采集起来方便,由于具有这些优点,所以在现代市场有着光明的的前景,我们平常可以在很多领域中使用到指纹识别,例如:门禁系统、考勤系统、智能手机电脑等人们日常生活息息相关的应用领域。

这类技术统称为生物识别技术,在全世界科学家的研究下,这项科技技术已经得到了飞速的发展,在理论方面已经完全成熟。各种应用产品大量衍生,指纹识别就是其中发展最为迅速的技术。国内国外的高校、企业、研究院都纷纷加入这块领域,研制出了各种基于指纹识别的生物技术产品。但是想要真正普及还要有很长一段路要走,因为指纹技术虽然发展迅速并且前景光明,但是成本不低,对于很多家庭来说在购买时还是不会优先考虑。所以如何降低指纹模式识别系统的开发成本使得人人可以接受,就是现在乃至未来研究人员的努力方向。

在日常生活中,锁具无处不在。有独立的也有与其他设备结合在一起的,指纹锁就是一种新兴的锁具,它结合了多种技术于一身。随着我们国家经济的迅速发展,人们对门锁的安全性提出了更高的要求。经过近几年的宣传和发展,国内指纹锁的市场已经打开,大批科技,家居公司开始生产制作指纹锁。中国的民用市场指纹锁占有率已经接近10%,这对于一个新兴产品来讲,已经是很快的发展了,但对比发达国家的占有率来讲,只有他们的六分之一,因此国内市场仍然有很大的发展空间有待提高和发掘。

一项2019年的研究数据表明,中国市场对指纹锁的需求占全世界总需求量的百分之二十,这是一个非常庞大的数字,表明我国未开发的市场远远多于世界任何一个国家。一些业内人士甚至分析称,在2025年,世界指纹锁的市场总值将达到50亿美元,其中我国是这块市场最大的潜力股,由此我们不难看出目前中国指纹锁的发展前景可谓是一片光明。

目前国内外都在力求指纹系统的:

(1)功能多样:在单一的指纹识别采集基础上应该添加一些其他功能,例如报警、监控等,这样使得使用者可以对外来人员随时监控,提高了安全性,也非常实用。

(2)外观小巧:通常可以使用嵌入式的方式,方便安装,节省空间也更加美观。

(3)个性需求:需要针对不同行业或使用地点的指纹锁设计不同的功能,满足使用者的更多需求。

(4)网络化:网络如今已经全面普及,指纹锁应该与无线传输技术进行结合,使得数据可以上传到网络上,方便查看调用。

本课题主要是针对小型指纹机在安全防护领域的作用。指纹的安全隐患主要有:第一,指纹易被获取;第二,指纹无法改变。人的指纹从出生就已确定,一生都不会改变,一旦被他人获取,后果将非常可怕,难以补救。

未来指纹识别技术还会应用在很多其他领域,因此,一旦我们的指纹信息泄露给他人,那就很可能同时泄漏出自己的其他身份信息,如果使用我们的的指纹做一些违法乱纪的事情,这对社会都会造成不良的影响。因此,在还没有有效避免指纹泄漏的技术出现时,我们想要实现安全就必须采用指纹和其他安全措施相结合的方式来实现更高的安全性。比如,指纹+密码,通过这种高安全性的技术减轻危害的发生。

本课题主要将应用于家庭,企业的室内安全防护,以及一些需要重点安全保护的设施。目前市场的一些指纹锁存在功能单一,识别不准确等问题,本课题主要针对这两个问题给予解决,融入一些新的功能,比如识别错误后的报警等等。实现这些功能能够加快带动传统锁具向科技发展进步的进程,让安全防护进入家家户户。

1 硬件选择与设计

1.1 总体设计及方案选择

本课题设计的指纹识别系统主要由单片机;指纹传感器;液晶显示屏;矩形键盘;蜂鸣器;存储器几大部分组成。为了发挥各个硬件的最大功效,明确设计理念,在电路搭建之前进行了多次对比试验,选择出最适合本课题的硬件来操作。

1.1.1主控单片机选择

方案一:

STC89C52单片机,采用这款作为主控芯片的优势比较明显。它具有开发简单,容易快速掌握,可以在线编辑程序下载,调试起来比较方便,成本也相对低,52单片机是宏晶科技公司在C51单片机的基础上做出的新一代产品,更新了许多新的功能,当需要存储数据的时候自己芯片的内部就可以直接存储,不需要再外接存储芯片[1]。而且速度是51单片机的8~12倍,这个处理速度可以大大满足本课题的需求。

方案二:

MSP430单片机也经常作为很多系统使用的主控芯片。由美国TI公司生产也被称为混合信号处理器,因为它混合了多种功能不同的的微处理器,模拟电路,数字电路,将这些同时集合在芯片上,这款产品基本都是在电池供电的设备中使用。本项目采用的是外接电源,而且这个系列单片机的开发也比STC系列要难,价格较为昂贵。通过比较本项目不准备使用这款单片机。

方案三:

PIC16F877A单片机,PIC系列单片机非常频繁的被应用于工业控制领域[2]。由Microchip公司所生产开发的新产品,优点在于它的系统稳定性高,抗干扰性能比较强,内部资源比较丰富。但是开发成本高,难度相对大,本课题不需要太高的的稳定性要求,其他的可能性价比会更高一些。

综上所述,最终考虑决定采用STC89C52单片机作为本课题的主控芯片,

从优缺点,价位和开发难度几项比较而言都更加具有优势。

1.1.2传感器模块选择

方案一:

AS608指纹识别传感器,这款传感器是由杭州晟元芯片技术有限公司的 AS608 指纹识别芯片制成[3],各家公司将芯片买来后根据芯片研发生产了相应的外围电路,集成了一个可以供大家2次开发的指纹传感器;因此市面上所有的AS608芯片的指纹传感器,其内部的控制电路大多数都是完全相同的,只是性能和生产厂商不同而已。

AS608指传感器的内部含有高速DSP处理,可以实现对指纹的采集和识别功能,单片机与传感器之间通常使用串口通讯,这样的设计使得开发变得简单方便。通过串口就可以采集,识别,添加,消除指纹,非常适合本课题使用。

方案二:

FM-70是一种高级DSP指纹传感器,以高速DSP处理器为核心,但这种指纹传感器没有待机或者休眠的情况,只有工作和不工作两种状态[4],在不工作不进行指纹对比的时候,为了降低功耗节约电量,关闭电源,模块进入不工作状态;当再次进行指纹识别比对时,开启电源,指纹模块继续工作,每一次都这样比较麻烦,不方便操作。

其他一些型号传感器由于价位过高,不利于大规模推广,不做考虑,综上所述,本课题计划使用AS608指纹传感器。

1.1.3显示器模块选择

方案一:

LED彩色数码管,颜色比较好看艳丽,光线也比较明亮,可以显示出来很多种颜色,即使站的比较远也可以很清晰的观察到显示屏上显示的文字而且价格也适中。对于显示数字或者简单的字母会比较合适。但是在焊接难度上比较大,因为它与单片机连接时占用CPU的I/O口比较多,容易出现焊接错误。程序编程更加复杂,而且如果单片机输出电流不够的情况下,还需要连接一个驱动电路,外观上来看也比较厚。

方案二:

LCD1602液晶显示屏,液晶显示屏比数码管的优点在于外观较薄,显示功能强大,可以同时显示32个字符,数字,符号字母都可以显示出来。但外观颜色来讲没有数码管那么鲜艳,颜色比较单一,但对于本课题指纹识别都是近距离观看,已经足够了,而且不用占据单片机过多的引脚,耗电更低。

方案三:

LCD12864液晶显示屏,12864是点阵数简称,因为它是一款128*64点阵液晶模块。接口方式灵活简单,方便的操作指令,成本低。不仅可以进行多种图象的显示,还可以显示8×4行16×16点阵的汉字[5],完全构成一个全面的人机交互界面,适用于各种小型仪器或设备的显示。另一个显著特点是它低电压低功耗。虽然LCD1602液晶显示的功能更强大,但是显示的内容偏大造成了显示空间的浪费,本课题属于小型仪器,更适合12864的发挥。

综合上述的描述,所以选用LCD12864液晶显示屏。

1.2 系统总体设计

通过比较选择,决定了本课题所使用的全部核心元器件,STC89C52作为本设计的主控单片机;LCD12864液晶显示屏完成所需要的人机交互;采用AS608指纹传感器进行指纹识别,除此之外还加入了矩形键盘,能够通过管理密码进行添加和删除指纹信息,数据的保存采用AT24C02进行存储,整个系统框图如图1.1所示。

图1.1 系统功能框图

2 系统硬件电路设计

2.1 系统主电路设计

2.1.1 主体电路设计

本课题由单片机作为系统的控制核心,系统总体电路图如图2.1所示。另外主要的模块有指纹识别模块、按键模块、液晶显示模块。指纹采集模块包括了DSP处理器和AS608指纹传感器采集头,负责完成指纹特征的采集,键盘模块由一个 4*4 的矩阵键盘构成,对整套系统下达指令操作。液晶显示模块用于方便用户直观查看操作页面,以及返回的提示信息,起到人机交互的作用。其他还有一些小的模块,存储信息的存储器模块和蜂鸣器报警模块。

图2.1 系统总体电路图

2.1.2 单片机最小系统设计

构建一个单片机的最小系统,那么必须满足一些要求:第一必须要有电源、时钟电路和复位电路,这三项是单片机最小系统的核心电路,其次要有单片机的主芯片、程序下载电路和I/O口负载电路用于数据输入和输出。这样一套系统才能够满足使用者使用,下载,调试的要求。

图2.2 STC89C52引脚图

如图2.2所示,52单片一共有40个管脚,其中32个端口可供使用,P0口在本课题中与数据存储单元相连FLASH编辑时,P0口需要接收指令,所以连接一个排阻做上拉电阻,P1、P2口连接矩形键盘和显示屏,做输入口使用,P3口在52单片机中拥有很多重要的第二功能。

表2.1 52单片机P3口说明

端口名称 第二功能

P3.0 串行数据输入口

P3.1 串行数据输出口

P3.2 外部中断0

P3.3 外部中断1

P3.4 定时器0输入

P3.5 定时器0输出

P3.6 外部存储器写功能

P3.7 外部存储器读功能

电源电路:这对于一个电子产品是必不可少,维持整个系统运转。在本课题中由于52单片机的工作电压在4.5~5.5V之间,在接通电源后,构成一个接口电源的简单滤波电路。因为开关电源的输出电压波纹相对较大,因此需要先完成滤波[6]。

图2.3 晶振电路电路图

晶振电路:如图2.3所示,C2和C3是负载电容和晶振构成单片机的晶振电路,电容是用来改变晶振的频率和幅度。52单片机要求负载电容在20pf到40pf之间才可以,如果能达到30pf,那将是电容的最佳取值。晶振的取值大约在1.2~12MHz 之间,但可以更高,要求并不是特别严格,最高达到24MHz也没有问题,只是耗能也会相应地增多。由于AS608指纹识别模块与52单片机采用的是串口方式进行通讯,选用11.0592MHz晶振可以产生9600波特率,误差可以忽略不计[7],所以本课题就采用的是11.0592MHz 的石英晶振。焊接时这三个元件应尽量靠近单片机的管脚,可以有效减少线路上寄生电容对晶振产生影响。

复位电路:电路图中和电容并联的按键就是复位按键,52单片机是高电平复位,没被摁下之前需要上电复位,正常工作后摁下按键,使单片机的第九个管脚(RST)出现高电平达到手动复位的效果,这需要持续两个机器周期以上的高电平,才可以实现。当上电的瞬间,电容开始充电,电阻会产生压降,RST管脚检测到电阻上端变成高电平,这时单片机各个系统复位。

2.2 单元电路设计

2.2.1 传感器单元

AS608是光学指纹传感器,由高性能的 DSP 处理器和 FLASH等芯片构成,具有指纹图像处理、模板提取、模板匹配、指纹搜索和模板存储等项功能。一般是由8 部分组成:传感器阵列、偏置、ADC、DAC、振荡器、系统时钟产生器、芯片接口与控制、控制器。

图2.4 传感器实物

传感器阵列由许多采集单元组成,作用就是把芯片采集到的指纹转化为电信号。经过 ADC 转化器进入单片机,单片机系统会根据收到的图像是否清晰而对传感器阵列进行一定调节,系统通过下达不同指令让该模块完成所需要的功能。系统数据传输、发送指令以及应答都必须按照严格规定的数据包格式来实施。

操作可分为三类:数据包、命令包和结束包。系统必须按照这样的格式封装好发送的指令数据,才能使传感器正常工作。

图2.5 AS608电路原理图

如图2.5所示,TXD数据发送端口与单片机P3.0相连,RXD数据接收端口与单片机P3.1相连,AS608不再需连接任何外围部件,本身已经是完整的指纹识别模块。

2.2.2 显示屏单元

LCD12864是一款带有中文字库的的点阵图形液晶显示模块,其内部含有国标一级、二级简体中文字库,显示分辨率为128×64,内置8192个1616点汉字,和128个16 8的字符集[8]。一共有20脚的接口,显示出的字符其实就是将对应数据写入显示屏内部的DDRAM模块上的过程。利用这种简单、方便、灵活的接口方式和的操作指令,既可以显示点阵的汉字,也可以图形显示。在显示屏设计过程中和其他系列的液晶屏比较,这款不论硬件电路结构或显示程序都要简洁得多,只需占用单片机一个端口就可以完成。

表2.2 LCD12864接口说明

编号 名称 引脚说明 编号 名称 引脚说明

1 VSS 电源地 11 DB4 三态数据线

2 VDD 电源正极 12 DB5 三态数据线

3 V0 对比度调整 13 DB6 三态数据线

4 RS(CS) 显示数据 14 DB7 三态数据线

5 R\W 读\写选择端 15 PSB 传输方式

6 E 使能信号 16 NC 悬空

7 DB0 三态数据线 17 RESET 复位端,低电平有效

8 DB1 三态数据线 18 VOUT 驱动电压输出端

9 DB2 三态数据线 19 A 背光源正极

10 DB3 三态数据线 20 K 背光源负极

数字电路中,数据全部都的是用0和1表示的,显示过程中中文要比英文显示难的多,因为英文字母只有26个,每个只需要8位的一字节就可以完成显示。但是常用的汉字有几千个,显示起来比较复杂,英文字符只要占用1个字节,中文字符需要占用2个字节[9]。所以要设计好显示点在液晶屏上的位置与其在存储器中的地址之间的关系,这样对应的汉字将相应的点阵信息写入到对应的存储单元中,才可以完成汉字的显示。

图2.6 LCD12864与单片机接口图

单片机与显示屏的接口电路如图2.6所示,LCD12864显示屏的三态数据端口D0~D7和单片机的P2.0~P2.7连接,读写端口与单片机P3.4口相连,显示数据的端口与单片机P3.5口相连,都是通过产生高低电平控制数据,控制系统的数据显示,当高电平时读取数据,低电平时候写数据,LCD_EN 使能端与单片机的 P3.3相连,用来控制显示屏的亮度。VDD 接+5V电源,VSS 接地,19 脚为液晶接+5V背光电源正端,20 脚接电源负端。

2.2.3 数据储存器单元

AT24C02是一个2K位串行CMOS E2PROM,内部含有256个8位字节[10]。

表2.3AT24C02管口说明

管脚名称 功能

A0,A1,A2 器件地址选择

SDA 串行数据/地址

SCL 串行时钟

WP 写保护

Vcc +1.8V~6.0V工作电压

Vss 接地

AT24C02的芯片固定部分的地址为1010,A0~A2引脚在接通电平后会得到确定的3位编码,与1010相结合所组成的7位编码就是这个器件的地址码[11]。

当单片机开始写操作的时候,会先发送该器件的7位地址码和写方向位"0",一共八位,发送完成后在SCL线上产生第9个时钟信号;被选中的存储器器件在确认是自己的地址后,在SDA线上产生一一个应答信号作为相应,单片机收到应答后就可以传送数据了。

在开始工作的时候,单片机会先发出一个字节,存储器存储区的首地址写入,在字节地址后自动加1[12],随后存储器发出应答信号后,单片机开始发送下一个字节,但每发送一个字节后都要等待应答,收到应答信号后再发送下一个。如图2.7所示,单片机先发送7位地址码和写方向位"O",通过释放存储器串行数据端口在SCL线上产生信号[13],在确认了信号是传给自己的后,发出回复信号。这款存储器的写次数可以达到一百万次,当输入的字节数量过大时,远远超过了芯片的承载数时,数据地址将会上卷覆盖掉之前的数据,直到数据全部写完,单片机会终止写入。

图2.7 AT24C02读写时序图

图2.8 AT24C02电路原理图

如图2.8所示,AT24C02共有八个管脚,SCL串行时钟和SDA双向串行数据地址两个管脚用于输入和输出数据,A0~A2用于设置器件地址,必须接到VSS上。WP管脚用于写保护与VCC相连。

2.2.4蜂鸣器单元

本课题的蜂鸣器选用5V电磁式有源蜂鸣器和一个PNP型8550三极管连接到单片机的P3.7口,三极管的发射极与蜂鸣器的负极相连,三极管的基级通过电阻与单片机相连[14],蜂鸣器发声原理是电流通过电磁线圈,所以蜂鸣器工作的时候所需要的电流一般都比较大,如果连接的电流过小,可能蜂鸣器无法发出报警信号,本设计用的电流就无法带动蜂鸣器线圈震动I/O口无法直接驱动,这时候就需要引入一个三极管开关电路来驱动。当I/O口输出高电平时,三极管不导通,没有电流流过,蜂鸣器不发声,当输出的是低电平时,三极管导通,蜂鸣器鸣叫[15]。

2.2.5 矩形键盘单元

本课题需要使用到一个44的正方形矩阵键盘,本课题采取了这种做法虽然比直接连接要复杂一些,焊接起来也要更加小心,但因为操作中要使用较多的按键,出于节省空间和单片机I/O口使用数量来考虑,采用矩阵法来作键盘是合理的,使用一个单片机端口就完成该模块设计。
表2.4矩形键盘指令说明
键值 第一列 第二列 第三列 第四列
第一行 0
11 012 0 14 018
第二行 0
21 022 0 24 028
第三行 0
41 042 0 44 048
第四行 0
81 082 0 84 0*88

图2.9 矩形键盘接口图

如图2.9所示,键盘的每条线在交叉处不直接连通,而是使用一个按键加以连接。产生的16位按键与单片机的P1.0~P1.7接口。使用一个端口就可以构成,比直接与单片机端口连接节省了很大的空间和端口使用,行线所接的单片机的I/O口作为输出端,而列线所接的I/O口则作为输入。

2.3 驱动电路设计

继电器驱动电路在系统中主要起着保护电路以及调节转换电路的作用,继电器是一种可以传递信号的电器,一个自动控制的系统电路中必须有能够对系统的各种参数状态进行逻辑判断的电器元件,这就是继电器在本课题出现的原因。它可以通过输入较小的电流来控制过大电流的输出,一旦异常可以继电器可以吸合保护电路。在本课题中继电器在运行时的吸合电流可能最高要达到40mA左右,而单片机输出电流一般只有4~20mA范围内,这个时候直接控制无法驱动,我们增加一个可以使电流放大电路。本课题选用PNP型三极管进行电流放大,当单片机I/O口输出的是高电平时,三极管不导通,没有电流流过,继电器断开,反之如果是低电平,三极管导通,继电器吸合[16]。

图2.10 继电器驱动电路图

3 系统软件设计

3.1 软件开发环境介绍

本课题采用 Keil uVision5软件进行编程。它的编译和调试工具与大多数器件都完美匹配。提供了包括C编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案[18],一直到目前它依旧是最流行的应用于开发51,52单片机的编程软件。同时支持c语言和汇编语言。相比较而言,C语言在功能上可读性、可维护性强于其他语言,上手比较快更加简单易学。

3.2 系统函数介绍

3.2.1 主函数设计

void main()开始是程序的主函数,一切程序都必须要有的入口函数[19]。先对单片机和其他元器件进行初始化,保证可以正常使用,初始化并且重新赋予变量,初始化完成后,进行循环设定,将程序设定为一个死循环,否则一次后就会退出,不断进行循环才可以达到实时检测识别的目的。具体功能的代码使用其他函数进行封装然后在主函数进行调用。

如图3.1所示,系统开机初始化后,单片机首先判断是否接收到了识别指纹的命令或者是增加删除指纹的命令,检测到信号后进行相应的后续操作。

图3.1 系统流程图

3.2.2 AS608传感器子函数设计

传感器与单片机通讯使用的是串口通讯协议,工作时只需发送命令相对应的数据包就可以控制指纹模块完成所要完成的功能。控制采集指纹的时候先发送采集指纹信息,之后等待采集完成后再发送指纹识别的指令,如果匹配成功则会返回成功信息,否则返回失败,系统重新下达命令再次采集识别。

图3.2 指纹传感器程序流程图

3.2.3 显示屏函数设计

在设计LCD12864显示屏显示的时候没有进行过多的设计和编写,这款显示屏的时序厂家已经严格定义好了[20],我们使用时按要求定义他的引脚和显示位置就可以了。首先需要将需要显示地方的地址通过命令写入,然后将数据按顺序的进行写入即可。在写入地址后显示第一个内容后地址会自动加1。

将函数名定义为LCD12864_display_string,使用的参数为x,y,*s,x,y表示的是液晶显示屏上的位置坐标,*s是需要显示的字符数组[21]。软件根据需要显示的位置,将坐标计算出来进行显示。

#define LCD P2 //并行数据口D0~D7

sbit E =P3^3; //使能信号引脚

sbit RW =P3^4; //读写选择引脚

sbit RS =P3^5; //命令选择引脚

void LCD12864_delay(uint x); //延时

void write_com(uchar com); //写命令

void write_data(uchar dat); //写数据

void LCD12864_display_char(uchar x,uchar y,uchar dat);

void LCD12864_display_string(uchar x,uchar y,uchar *s); //显示字符位置

void LCD12864_init(void);//系统初始化

3.2.4 矩形键盘函数函数设计

首先将全部的行线P3.0~P3.3置于低电平,然后查看列线P3.5~P3.7是否出现低电平,如果出现一列低电平,就证明那一列有按键按下,若反之没有出现就说明那一列没有键被按下。

当有按键被按下,就要确定是哪一个按键被按下。方法类似,需要将行线P3.0~P3.3置于低电平,当某一根行线出现低电平时,检查他是否与之前的列线相交,如果是的那么被按下的按键就是相交点的那个按键。

图3.3 矩形键盘程序流程图

4 项目组装与调试

4.1 系统硬件调试

首先进行硬件电路焊接,过程中注意与原理图仔细对照,因为本设计的布线较密,元器件放置的顺序需格外注意,不然焊锡容易连接到其它元器件的引脚,可能导致元件损坏。

焊接完成后先检查STC89C52单片机及其晶振、复位等外围电路,必须保证这一部分的系统核心电路可以正常工作,才能保证系统正常运行,功能得以实现。先断开单片机电路与电源、液晶、指纹识别的连接检查 I/O 口是否连接正常,确保无短路、开路故障。检测时根据万用表在二极管档位时,使用红黑表笔相碰,出现报警这个原理进行对短路、断路、虚焊这些情况的检查。

报警电路主要检测蜂鸣器发出声音是否正常、三极管与单片机的接口连接,先使用万用表二极管档位检测一下三极管是否正常。之后可在电路中将三极管的集电极C和发射极E短接,听蜂鸣器是否可以发出声音来判断其好坏,同时声音大小是否合适,如果声音小就查看电压是否正常。

键盘单元为连接在P0端口的一组矩阵键盘,列线、行线分别连接单片机的 P1端口的八个管脚。用万用表检一下和单片机之间接口连接,并且逐个检测16个按键开关是否正常,检查是否存在按键本身不好使或者由于焊接这部分较为复杂,出现内部短路问题。

4.2 软硬件联调

图4.1 keil5编译界面

在软件调试完成后,点击编译,当文件正常运行,会在底部显示无错误,但如果显示的是"error",还会显示有几处错误,就要根据提示找到错误的地方并改正,直到运行无问题。

图4.2 项目实物图

把编写好的单片机程序下载进去,将系各个元器件部分与单片机相连,打开电源开关,进行调试。通过调试,密码3次输入错误可以启动蜂鸣器进行报警,当密码正确输入,需要进行下一步的指纹的比对,同样指纹不匹配也不能显示,错误三次进行报警。通过多次调试可以得出结果,该系统受密码和指纹的双重保护,各项测试全部合格,符合预期的全部功能,完成了基于单片机指纹识别系统的设计。

4.3 调试遇到的问题及解决

在整个系统调试过程中,采集指纹这一块可能会受到一些外部因素影响,比如手指接触的力度、干湿情况、指纹的接触面积不同都会导致识别失败,在第一次没有成功的情况下,不能马上判断是程序代码有问题,还需进行第二次的尝试。

液晶显示屏出现花屏现象,在前几次调试过程中每次执行下一个口令时,液晶屏都会出现花屏乱码现象,无法按正常出现应有的字符。在检查了连线没有问题后,翻看了液晶手册,重新检查了一遍程序代码后发现,造成这种情况的原因是因为字库显示和绘图显示两种显示方式有一些不同,找到相关的程序进行了修改,当每次操作字库显示或者绘图显示时先将另一种显示方式清除,这样就解决了这个问题,开机后没有再出现花屏。

结 论

指纹、密码锁慢慢兴起,具有非常广阔的市场,很多家庭开始接受高科技带来的便利。因此,本课题采用52单片机和AS608指纹传感器模拟出一个小型指纹识别系统,从价位、功能、安全性上都可以满足人们对家庭防盗安全的需求。

本课题研究的主要工作有:

(1)研究指纹系统基本原理和发展近况以及前景,通过调查了解目前市场所需要的产品功能。

(2)完成指纹识别整体构建建设,进行硬件的选择购买,软件编写调试。

(3)研究识别系统基本流程和步骤,设计硬件各个单元的电路布置,进行硬件电路的焊接。

(4)确定软件开发环境,梳理采集识别流程,将想要实现的功能编写进单片机程序。

(5)完成系统最终的软硬件联调,分析在调试中遇到的一些问题,改正后给出最终的测试结果。

总体来说,本次课题基于单片机指纹采集识别系统的设计还是比较成功的,基本完成了全部的预定功能。为了完成本课题阅读了大量资料并且对身边亲戚朋友进行了一些调查工作,在此过程中本人也对指纹识别加密技术产生了浓厚的兴趣,对相关技术有了一些认识和了解。同时我在本次课题中也认识到了自己身上还有许多的缺点和不足需要改正,在以后的工作和生活中,我一定努力改变完善自己,提高实践能力和专业知识。

参考文献

[1] 张学斌.基于指纹识别的安全密码锁设计[D].湖南大学,2017:13-53

[2] 余波.基于数字指纹识别技术的门禁系统设计[D].电子科技大学,2009:30-63

[3] 侯江.指纹识别传感器电路系统设计[D].电子科技大学,2016:10-13

[4] 王彬彬.基于STM32的指纹锁控制系统设计与实现[D].西北师范大学,2018:10-20

[5] 秦强.指纹识别技术的研究与实现[D].山东科技大学,2017:14-17

[6] 王崧.基于嵌入式系统的指纹识别与存储技术[D].长春理工大学,2013:10-19

[7] 李金铎.基于图像处理的指纹识别算法研究[D].哈尔滨工程大学,2016:7-11

[8] 陈武.基于指纹识别技术的电力调度自动化系统[D].天津大学,2016:13-15

[9] 徐笑.安全设备的终端实现与远程监控技术的研究[D].电子科技大学,2016:1-9

[10] 高伟.基于STM32F103的指纹识别安防系统的设计[D].武汉轻工大学,2018:8-43

[11] 林峰,刘林伟,冯陈伟.基于STM32和FPC1011C2的指纹采集系统[J].中国新通信,2014,84(12):2-4

[12] 陈静.数字图像处理中指纹识别技术的分析[J].电子测试,2019,37(18):1-3

[13] 张云佐,焦静浩.基于指纹识别的信息采集与验证系统设计[J].新一代信息技术,2019,37(16):3-4

[14] 操权利,孟志华,唐辉,田祯,占侣情.基于51单片机的远程指纹采集终端设计[J].中国科技信息,2010,39(23):12-15

[15] 张萍,马树军,史可福.基于51单片机的指纹电子密码锁的设计与实现[J].实验室研究与探索,2018,33(8):2-11

[16] 刘延吉. 自动识别技术的发展和应用[J]. 中小企业管理与科技(下旬刊), 2013(07):277-278

[17] 管超,邵小桃. 基于ZigBee的振动报警系统的设计与实现[J]. 软件,2015(06):152-157

[18] 陈晓东,邓鹏. 基于WIFI的室内空气质量检测系统设计[J]. 仪器仪表用户,2018(3):3-3

[19] 马华玲. 仿真软件在高校电子类课程设计中的应用[J]. 教育教学论坛, 2013(32):173-174

[20] 张晓钢,裘凯翔,皮雪平,戴增强. 基于以太网的景观灯群远程控制系统[J]. 科技信息,2011(36):46-47

[21] 张红,刘泽,黄宏. 基于STC12C5A60S2单片机的脉搏温度探测仪的设计[J]. 吉林工程技术师范学院学报,2013(07):96-99

附录 源程序清单

#include<reg52.h> //头文件

#include<LCD12864.h>

#include<AT24C02.h>

#include<KEY.h>

#include<AS608.h>

#include<T2.h>

#define uchar unsigned char //宏定义

#define uint unsigned int

#define ulong unsigned long

sbit buzz=P3^7; //蜂鸣器

sbit led=P0^0; //LED灯

#define MAX 5 //指纹的最大数量

#define ID_MAX 3//ID的最大位数

uchar mode=0; //选项

uchar mode_num=0;/管理界面选择

uint ID=0; //输入存储ID

uchar n=0; //ID位数

bit zhiwen_f=0; //进入指纹选项

uchar a;

uchar num; //存储记录密码

bit in_f; //输入密码

bit reset_f; //重设密码

bit input_f; //输入完成

uchar reset_num; //

ulong low_mima=0;//系统原密码

ulong in_mima=0; //存储输入的密码

ulong new_mima=0;//存储输入的新密码

uchar temp[5]=" \0";//存储显示的内容

void delayms(uint ms) //延时函数

{

unsigned char i=100,j;

for(;ms;ms--)

{

while(--i)

{

j=10;

while(--j);

}

}

}

void didi(uchar i)//蜂鸣器,i为蜂鸣器鸣叫次数

{

uchar j;

for(j=0;j<i;j++)//

{

led=0; /开启蜂鸣器和LED灯

buzz=0;

delayms(20);

led=1; //关闭蜂鸣器和LED灯

buzz=1;

delayms(15);

}

}

void xunzhiwen() //查找指纹

{

searchnum=search(); //搜索指纹

if((searchnum>=1&&searchnum<=MAX)||searchnum==255)//最多容纳指纹数

{

if(searchnum>=1&&searchnum<=MAX) //识别成功

{

temp[0]=searchnum%1000/100+0x30;

temp[1]=searchnum%100/10+0x30;

temp[2]=searchnum%10+0x30;

temp[3]=' ';

LCD12864_display_string(3,2,temp);

LCD12864_display_string(3,3,"指纹解锁");

LCD12864_display_string(1,4," ");

in_mima=0; //清除输入的密码

num=0; //清除输入的位数

input_f=0; //

jdq=0; //

T2_num=0; //

TR2=1;

}

else //指纹不正确

{

LCD12864_display_string(3,3,"无效指纹");

didi(3); //三次报警

}

delay1ms(500); //延时后清除显示内容

LCD12864_display_string(3,2," ");

LCD12864_display_string(3,3," ");

}

}

void cunchu() //存储指纹

{

LCD12864_display_string(0,3,"状态 ");

if(ID>0&&ID<=MAX)  //输入的指纹正确
{
	if(enroll()==1)//生成模板成功
	{
		if(savefingure(ID)==1)//保存指纹成功
		{
			LCD12864_display_string(3,3,"录入成功");
		} 
		else				  //保存指纹
			LCD12864_display_string(3,3,"保存成功");	
	}
	else		              //保存指纹失败
		LCD12864_display_string(3,3,"采集失败");	
}
else			              //输入指纹错误
	LCD12864_display_string(3,3,"编号错误");

n=0;	   //清除编号位数
ID=0;	   //清除输入编号
zhiwen_f=0;//关闭指纹采集

}

void shanchu()//删除指纹

{

LCD12864_display_string(0,3,"状态 ");

if(ID>0&&ID<=MAX) //输入存储指纹位置正确

{

if(dellfingure(ID)1)//删除成功
{
LCD12864_display_string(3,3,"删除成功");
}
else //删除失败
LCD12864_display_string(3,3,"删除失败");
}
else
{
if(ID999) //如果输入999表示清空指纹

{

if(Clear_All()==1)//清空成功

LCD12864_display_string(3,3,"清空成功");

else //清空失败

LCD12864_display_string(3,3,"清空失败");

}

else //输入编号错误

LCD12864_display_string(3,3,"编号错误");

}

n=0;	   //清除编号位数
ID=0;	   //清除编号
zhiwen_f=0;//关闭指纹采集					  		

}

void display_guanli()//显示管理界面

{

LCD12864_display_string(0,1," 管理系统界面 ");

LCD12864_display_string(0,2," 录入指纹 ");

LCD12864_display_string(0,3," 删除指纹 ");

LCD12864_display_string(0,4," 修改密码 ");

switch(mode_num)

{

case 0: LCD12864_display_string(0,2," >> "); break;

case 1: LCD12864_display_string(0,3," >> "); break;

case 2: LCD12864_display_string(0,4," >> "); break;

default: break;

}

}

void chuli()//按键处理

{

if(key_f1) //判断是否有键按下
{
if(a11&&mode0&&in_f0)

{

shu++;

if(shu>=4)

{

AT24C02_write_date(200,0);

AT24C02_write_date(201,0);

AT24C02_write_date(202,0);

low_mima=0;

shu=0;

}

}

else

shu=0;

	if((mode==2||mode==3)&&a<10)  //输入ID,按下的是数字键
	{
		if(n<ID_MAX)//判断是否为输入状态,是的话才可以继续输入
		{
			if(n==0)   //判断为第1位		    
			{	
				LCD12864_display_string(3,2,"        ");
				LCD12864_display_string(0,3,"              ");				
			} 
			LCD12864_display_char(3+n,2,a+0x30);//显示出输入的数字  ASCII[a]

			ID=ID*10+a;//编号计算
			n++;	   //编号输入位数+1
		}					   					
	}

	if((mode==0||mode==4)&&input_f==0&&a<10)//如果在输入密码状态,并且按下的是数字键
	{			
		if(in_f==1||mode==4)
		{	
			if(num==0)                  //清除显示后、显示输入新密码
				LCD12864_display_string(1,3,"           ");	
			if(reset_f==1&&reset_num>1)
			    LCD12864_display_char(num+1,2,a+0x30);//ASCII[a]
			else
				LCD12864_display_char(num+1,2,'*');//显示"*"
		}
		else
			LCD12864_display_char(num+1,4,'*');//显示"*"
		in_mima=in_mima*10+a;//读入密码	
		num++;			//密码输入次数加一			
		if(num==6)		//六位密码输入完成								   	   				   							
			input_f=1;	//标记六位密码输入完成	   					
	}

	if(a==10)
	{
		if(mode==0&&in_f==0)//输入密码
		{
			num=0;
			in_f=1;
			in_mima=0;
			input_f=0;  //清除确定标志
			write_com(0x01);
			LCD12864_display_string(0,1,"请输入管理密码: ");//显示输入密码
		}
	}
	if(a==15) //返回上一级
	{
		if(mode>1)			  //管理界面操作中
		{	 
			write_com(0x01);
			LCD12864_clear12864(); 
			mode=1;		//回到管理选择界面
		}
		else
		{
			if(mode!=0||in_f==1)
			{
				write_com(0x01);
				mode=0;
				diaplay_mode0();
				in_f=0;
				num=0;
				input_f=0;	
			}
		}
		
		if(jdq==0)
		{
			jdq=1;
			T0_num=0;
		}			   
	}
			
	if(a==11)//选择上一项
	{
		if(mode==1)//选择上一项管理	   
		{
			if(mode_num==0)
				mode_num=2;	
			else
				mode_num--;	
		}
	}
	if(a==12)//选择下一项
	{
		if(mode==1)//选择下一项管理
		{
			if(mode_num>=2)
				mode_num=0;	
			else
				mode_num++;		
		}	
	}
	if(a==13) //退格
	{					 					 
		 if(mode==0||mode==4)//在输入密码状态
		 {
			if(num!=0)
			{			 //输入密码个数减1
				num--;
				if(in_f==1||mode==4)
					LCD12864_display_char(num+1,2,' ');	
				else
					LCD12864_display_char(num+1,4,' ');	
			
				in_mima=in_mima/10;
				input_f=0;
			}
		 }
		 if(mode==2||mode==3)//在ID编号输入状态
		 {
		 	if(n!=0)
			{
				LCD12864_display_char(2+n,2,' ');
				n--;
				ID=ID/10;
				zhiwen_f=0;
			}
		 }
	}

	if(a==14)//确定
	{
		if(mode==1)		    //确定选择管理操作
		{	
			write_com(0x01);
			mode=mode_num+2;
			n=0;
			ID=0;
			zhiwen_f=0; 
			input_f=0;   //清除确定标志
			num=0;
			in_mima=0;
			new_mima=0;
			switch(mode_num)		
			{
			   case 0:  	
							LCD12864_display_string(0,1,">>  录入指纹");
							LCD12864_display_string(0,2,"编号: ");
							break;
			   case 1:  	
							LCD12864_display_string(0,1,">>  删除指纹");
							LCD12864_display_string(0,2,"编号: ");
							break;
			   case 2:  	
							reset_f=1;
							reset_num=1;
							LCD12864_display_string(0,1,"请输入旧密码: "); 
							break;	 
			   default: break;
			}	
		}
		else 
		{
			if(input_f==1)//密码输入完成确定
			{
				if(reset_f==1/*&&num==6*/) //修改密码区间
				{
					if(reset_num==3)
					{	
						if(new_mima==in_mima)
						{	
							low_mima=new_mima;
							AT24C02_write_date(200,low_mima/10000);
							AT24C02_write_date(201,low_mima%10000/100);
							AT24C02_write_date(202,low_mima%100);
							write_com(0x01);
							LCD12864_display_string(1,1,"密码修改成功");
							LCD12864_display_string(1,3,"请妥善保管好");
						}
						else
						{
							LCD12864_display_string(1,3,"密码修改失败");
						}
						reset_num=0;
						reset_f=0;	
					} 
					if(reset_num==2)
					{	
						write_com(0x01);
						LCD12864_display_string(0,1,"请再次输入新密码");		
						new_mima=in_mima;
						reset_num++;	
					} 
					if(reset_num==1)
					{
						if(low_mima==in_mima)
						{	
							write_com(0x01);
							reset_num++;
							LCD12864_display_string(0,1,"请输入新密码: ");//显示输入新密码
						}
						else
						{
							LCD12864_display_string(2,3,"密码错误");	//显示密码错误
							reset_num=1;
							LCD12864_display_string(1,2,"            ");	
						}
					}
				}
				if(in_f==1)		   //进入管理输入密码时候
				{
					if(low_mima==in_mima)
					{						
						mode=1;
						write_com(0x01);
						in_f=0;
					}
					else
					{
						LCD12864_display_string(2,3,"密码错误");	//显示密码错误
						LCD12864_display_string(1,2,"            ");	
					}
				} 

				if(mode==0&&in_f==0)
				{
					if(low_mima==in_mima)
					{					
						LCD12864_display_string(3,3,"解锁成功");
						jdq=0;
						T0_num=0;
					}
					else
					{
						LCD12864_display_string(3,3,"密码错误");	//显示密码错误
						didi(3);
					}

					LCD12864_display_string(1,4,"            ");
					delay1ms(500);
					LCD12864_display_string(3,3,"        ");	
				}
				in_mima=0;
				num=0;		//清除密码计数。重新计算输入的密码个数
				input_f=0;  //清除确定标志
			}

			if((mode==2||mode==3)&&n==ID_MAX)
			{
				zhiwen_f=1;		
			}
		}			
	}						
	key_f=0;        //清除按键标志	
}

}

void main()//主函数

{

uchar i;

LCD12864_init(); //初始化

UartInit();

low_mima=AT24C02_read_date(200);	
low_mima=low_mima*100+AT24C02_read_date(201);
low_mima=low_mima*100+AT24C02_read_date(202);

diaplay_mode0();

/* for(i=0;i<6;i++)//开始连接6次,如果不成功,表示通信不正常。成功就会跳出此循环

{

if(VefPSW())//与模块连接通过,绿灯亮。开始识别模式

break;

else

break;

} */

while(1)

{

i++;

a=keycan(); //矩阵键盘检测

chuli(); //矩阵键盘处理

	if(mode==1)
		display_guanli();
	else
		if(mode==2)				   //注册指纹
		{
			if(zhiwen_f==1)
				cunchu();		  //寻找指纹
		}
		else
			if(mode==3)			  //注销指纹
			{
				if(zhiwen_f==1)
					shanchu();	  //寻找指纹		
			}
			else				
				if(mode==0&&in_f==0)//正常解锁界面
				{
					if(i>=150)
					{
						i=0;
						xunzhiwen();	//寻找指纹
					}	
				}
	
	if(jdq==0)
	{
		T0_num++;
		if(T0_num>=16500)  //10秒关闭继电器
		{
			T0_num=0;
			jdq=1;	
		}
	}
		
}

}#ifndef AS608_H

#define AS608_H

#include<reg52.h>

#include <intrins.h>

#define uchar unsigned char

#define uint unsigned int

致 谢

在这次毕业设计中,毕业论文从选题到完成论文花了一年的时间,到现在,终于定稿完成了。回忆起大学四年来在沈阳城市学院的求学之路,心中百感交集,今年非常遗憾因为疫情原因,不能在大四最后的几个月里重新回到校园,当面对这四年来一路陪伴我的所有老师、同学和朋友们表示感谢。

首先感谢我的两位导师胡海龙和于宏波老师这一年来的尽心指导,开始在老师的帮助下我确定了选题和设计方案,胡老师对我的毕业设计有很多非常独到的见解,给我提出了很多宝贵的意见,并且为我收集了很多相关资料,在我懈怠时鼓励鞭策我,百忙之中多次帮助我审阅全文,对细节进行修改,并为本文的撰写提供了许多宝贵的意见,才得以顺利的完成了毕业设计工作。您渊博的知识、严谨的治学态度令我深受感染和终身受益。在此,谨向您致以最诚挚的敬意和衷心的感谢。

感谢我的母校沈阳城市学院对我的教育栽培,受"三自教育"的鼓舞让我能够更加优秀、独立。在这里我的理想得以插上翅膀,我的未来充满希望;感谢我大学以来所有的任课教师、辅导员、班主任、导师、园区老师,是您们的出现把我带进了知识的殿堂,让我身在学校却感受到了家的温暖,我的思想、学业、生活每个方面都做到了无微不至的关怀,再次感谢所有帮助过我的人、所有陪伴我走过这段岁月的人,我将用最努力的方式和最虔诚的善意回报你们!

相关推荐
黑胡子大叔的小屋34 分钟前
基于springboot的海洋知识服务平台的设计与实现
java·spring boot·毕业设计
ThisIsClark37 分钟前
【后端面试总结】深入解析进程和线程的区别
java·jvm·面试
雷神乐乐1 小时前
Spring学习(一)——Sping-XML
java·学习·spring
小林coding2 小时前
阿里云 Java 后端一面,什么难度?
java·后端·mysql·spring·阿里云
V+zmm101342 小时前
基于小程序宿舍报修系统的设计与实现ssm+论文源码调试讲解
java·小程序·毕业设计·mvc·ssm
文大。2 小时前
2024年广西职工职业技能大赛-Spring
java·spring·网络安全
一只小小翠3 小时前
EasyExcel 模板+公式填充
java·easyexcel
m0_748256343 小时前
QWebChannel实现与JS的交互
java·javascript·交互
Jelena技术达人4 小时前
Java爬虫获取1688关键字 item_search接口返回值详细解析
java·开发语言·爬虫
u0107735144 小时前
【字符串】-Lc5-最长回文子串(中心扩展法)
java·算法