基于STM32F103——AS608指纹模块+串口打印


最近用STM32F103做一个智能门锁小玩意,其中用到指纹模块,我这里也单独的写一下笔记,不过我只是了解了基本的,就是我做门禁卡要用到的几个东西,其它还没了解。为了方便,做一下记录。我这里没有用到按键和显示屏,所以还是串口输出输入来控制了 哈哈哈哈

一: 基本介绍

这里就写一下我这次用到的而且觉得是重点的东西吧 毕竟手册还是内容很多的

AS608引脚描述

这里就留意前6个 其中WAK这个引脚 是可以检测手指是否按下的 当有手指按下 WAK引脚是输出高电平 没有手指则维持低电平
在这里插入图片描述

AS608模块地址

默认是 0XFFFFFFFF(共4个字节)
我这里就不改了,按默认的了。修改的话请看手册

AS608波特率

默认是57600
我这里也懒得改了,按默认了。修改的话请看手册

AS608指令格式

模块指令格式分为三种,命令包、数据包、结束包。如下图
在这里插入图片描述

AS608应答格式

在这里插入图片描述
正常是通过检测确认码来确定数据的反馈
比如:
0X00: OK
0X01: 数据包接收错误
0X02: 传感器没有手指

手册都有说。这里也就不细发了。

二: 指令集

指令集很多,很多,但是我这里就写一下我这次做门禁卡系统用到的一些指令集。最终能实现 增加指纹、删除指纹、验证指纹。

1.读取图像-PS_GetImage

功能:	 	读取指纹图像,然后把图像存放于ImageBuffer中。
参数: 	 	无
返回: 	 	确认字
指令代码: 	01H

简述:
首先我们通过指令码包给AS608指纹模块让它读取图像,然后指纹模块会返回应答包给我们。我们通过应答包的确认字去判断这次的结果。

指令包格式:
在这里插入图片描述

首先我们是我们给指纹模块发送的内容 可以结合上图指令包格式

1、发送包头:		0XEF01 		(2个字节)
2、发送芯片地址:	0XFFFFFFFF	(4个字节)
3、发送包标识:	0X01		(1个字节)
4、发送包长度:	0X0003		(2个字节)
5、发送指令码:	0X01		(1个字节)
6、发送校验和:	0X0005		(2个字节)

包长度如何计算的?
我们可以看出来嘛 包长度这个表格是说3个。那么我看后面确实还剩3个字节。1字节的指令码+2字节的校验和 = 3字节。
结论: 包长度: 提示了后面还有多少个字节数据

校验和如何计算的?
我们同样也可以看出来 它的校验和是说是5。那么我们很容易发现,校验和其实是 从 包标识 0x01 + 包长度 0x0003 + 指令码 0x01 = 5。
结论: 校验和 = 包标识开始 + … 到校验和 但不含校验和。
应答包格式
在这里插入图片描述

发送完指令包给指纹模块 我们则会收到它发的应答包 可以结合上图应答包格式

1、接收到包头:	0XEF01 		(2个字节)
2、接收到芯片地址	0XFFFFFFFF	(4个字节)
3、接收到包标识:	0X07		(1个字节)
4、接收到包长度:	0X0003		(2个字节)
5、接收到确认码:	xxH			(1个字节)
6、接收到校验和:	SUM			(2个字节)

xxH(确认码):
00H:		录入成功
01H:		收包有误
02H:		没有检测到手指
03H:		录入不成功

SUM(校验和)

2.生成特征-PS_GenChar

功能:	 	将ImageBuffer中的原始图像生成指纹特征存放CharBuffer1 或者 CharBuffer2。
参数: 	 	BufferID(特征缓冲区号) CharBuffer1:01H     CharBuffer2:02H
返回: 	 	确认字
指令代码: 	02H

简述:
首先我们通过指令码包给AS608指纹模块让它读取图像后如果读取到图像,然后我们发送生成特征指令包,然后指纹模块会返回应答包给我们。我们通过应答包的确认字去判断这次的结果。
指令包格式:
在这里插入图片描述

首先我们是我们给指纹模块发送的内容 可以结合上图指令包格式

1、发送包头:		0XEF01 		(2个字节)
2、发送芯片地址:	0XFFFFFFFF	(4个字节)
3、发送包标识:	0X01		(1个字节)
4、发送包长度:	0X0004		(2个字节)
5、发送指令码:	0X02		(1个字节)
6、发送缓冲区号:	0x01/0X02	(1个字节)
7、发送校验和:	SUM			(2个字节)

SUM(校验和的计算):
校验和 = 包标识 + 包长度 + 指令码 + 缓冲区号(BufferID)1:当你发送的缓冲区号是0x01: 校验和 = 0x08
0x01 + 0x0004 + 0x02 + 0x01 = 0x08

2:当你发送的缓冲区号是0x02: 校验和 = 0x09
0x01 + 0x0004 + 0x02 + 0x02 = 0x09

包长度如何计算的?
我们可以看出来嘛 包长度这个表格是说3个。那么我看后面确实还剩3个字节。1字节的指令码+2字节的校验和 = 3字节。
结论: 包长度: 提示了后面还有多少个字节数据
应答包格式
在这里插入图片描述

发送完指令包给指纹模块 我们则会收到它发的应答包 可以结合上图应答包格式

1、接收到包头:	0XEF01 		(2个字节)
2、接收到芯片地址	0XFFFFFFFF	(4个字节)
3、接收到包标识:	0X07		(1个字节)
4、接收到包长度:	0X0003		(2个字节)
5、接收到确认码:	xxH			(1个字节)
6、接收到校验和:	SUM			(2个字节)

xxH(确认码):
00H:		生成特征成功
01H:		收包有误
06H:		指纹太乱
07H:		特征点太少
15H:		没有图像生成

SUM(校验和)

3.比对特征-PS_Match

功能:	 	将CharBuffer1 和 CharBuffer2 的特征文件比对。
参数: 	 	无
返回: 	 	确认字,对比得分
指令代码: 	03H

简述:
首先我们通过指令码包给AS608指纹模块让它对比然后CharBuffer1 和 CharBuffer2 的特征文件,指纹模块会返回应答包给我们。我们通过应答包的确认字去判断这次的结果。
指令包格式:
在这里插入图片描述

首先我们是我们给指纹模块发送的内容 可以结合上图指令包格式

1、发送包头:		0XEF01 		(2个字节)
2、发送芯片地址:	0XFFFFFFFF	(4个字节)
3、发送包标识:	0X01		(1个字节)
4、发送包长度:	0X0003		(2个字节)
5、发送指令码:	0X03		(1个字节)
6、发送校验和:	0X07		(2个字节)

应答包格式
在这里插入图片描述
发送完指令包给指纹模块 我们则会收到它发的应答包 可以结合上图应答包格式

1、接收到包头:	0XEF01 		(2个字节)
2、接收到芯片地址	0XFFFFFFFF	(4个字节)
3、接收到包标识:	0X07		(1个字节)
4、接收到包长度:	0X0003		(2个字节)
5、接收到确认码:	xxH			(1个字节)
6、接收到校验和:	SUM			(2个字节)

xxH(确认码):
00H:		指纹匹配成功
01H:		收包有误
08H:		指纹不匹配

SUM(校验和)

4.生成模板-PS_RegModel

功能:	 	将CharBuffer1 和 CharBuffer2 的特征文件合并生成模板,结果存放在CharBuffer1 与 CharBuffer2
参数: 	 	无
返回: 	 	确认字
指令代码: 	05H

简述:
首先我们通过指令码包给AS608指纹模块让它将CharBuffer1 和 CharBuffer2 的特征文件合并生成模板,指纹模块会返回应答包给我们。我们通过应答包的确认字去判断这次的结果。
指令包格式:
在这里插入图片描述

首先我们是我们给指纹模块发送的内容 可以结合上图指令包格式

1、发送包头:		0XEF01 		(2个字节)
2、发送芯片地址:	0XFFFFFFFF	(4个字节)
3、发送包标识:	0X01		(1个字节)
4、发送包长度:	0X0003		(2个字节)
5、发送指令码:	0X05		(1个字节)
6、发送校验和:	0X09		(2个字节)

应答包格式
在这里插入图片描述

发送完指令包给指纹模块 我们则会收到它发的应答包 可以结合上图应答包格式

1、接收到包头:	0XEF01 		(2个字节)
2、接收到芯片地址	0XFFFFFFFF	(4个字节)
3、接收到包标识:	0X07		(1个字节)
4、接收到包长度:	0X0003		(2个字节)
5、接收到确认码:	xxH			(1个字节)
6、接收到校验和:	SUM			(2个字节)

xxH(确认码):
00H:		合并成功
01H:		收包有误
0AH:		合并失败(不是同一个手指)

SUM(校验和)

5.储存模板-PS_StoreChar

功能:	 	将CharBuffer1 和 CharBuffer2 的模板文件,存放到PageID号flash数据库位置
参数: 	 	BufferID(缓冲区号 0x01/0x02),PageID(指纹库位置号)
返回: 	 	确认字
指令代码: 	06H

简述:
首先我们通过指令码包给AS608指纹模块让它将CharBuffer1 和 CharBuffer2 生成的模板进行储存模板,指纹模块会返回应答包给我们。我们通过应答包的确认字去判断这次的结果。
指令包格式:
在这里插入图片描述

首先我们是我们给指纹模块发送的内容 可以结合上图指令包格式

1、发送包头:		0XEF01 		(2个字节)
2、发送芯片地址:	0XFFFFFFFF	(4个字节)
3、发送包标识:	0X01		(1个字节)
4、发送包长度:	0X0006		(2个字节)
5、发送指令码:	0X06		(1个字节)
6、发送缓冲区号:	BufferID	(1个字节)
7、发送位置号:	PageID		(2个字节)
7、发送校验和:	SUM			(2个字节)

SUM(校验和) = 包标识+包长度+指令码+BufferID+PageID;
SUM(校验和) = 0X01+0X06+0X06+BufferID+PageID;

应答包格式
在这里插入图片描述

发送完指令包给指纹模块 我们则会收到它发的应答包 可以结合上图应答包格式

1、接收到包头:	0XEF01 		(2个字节)
2、接收到芯片地址	0XFFFFFFFF	(4个字节)
3、接收到包标识:	0X07		(1个字节)
4、接收到包长度:	0X0003		(2个字节)
5、接收到确认码:	xxH			(1个字节)
6、接收到校验和:	SUM			(2个字节)

xxH(确认码):
00H:		储存模板成功
01H:		收包有误
0BH:		PageID超出指纹库范围
18H:		写FLASH出错

SUM(校验和)

你都看到这里了,那么你添加指纹的操作就可以完成了。

6.删除模板-PS_DeletChar

功能:	 	删除flash数据库中指定ID号开始的N个指纹模板。
参数: 	 	PageID(指纹库模板号),N(删除的模板个数)
返回: 	 	确认字
指令代码: 	0CH

简述:
首先我们通过指令码包给AS608指纹模块让它删除模板,指纹模块会返回应答包给我们。我们通过应答包的确认字去判断这次的结果。
指令包格式:
在这里插入图片描述

首先我们是我们给指纹模块发送的内容 可以结合上图指令包格式

1、发送包头:		0XEF01 		(2个字节)
2、发送芯片地址:	0XFFFFFFFF	(4个字节)
3、发送包标识:	0X01		(1个字节)
4、发送包长度:	0X0007		(2个字节)
5、发送指令码:	0X0C		(1个字节)
6、发送位置号:	PageID		(2个字节)
7、发送删除个数:	N			(2个字节)
7、发送校验和:	SUM			(2个字节)

SUM(校验和) = 包标识+包长度+指令码+PageID+N;
SUM(校验和) = 0X01+0X07+0X0C+PageID+N;

应答包格式
在这里插入图片描述

发送完指令包给指纹模块 我们则会收到它发的应答包 可以结合上图应答包格式

1、接收到包头:	0XEF01 		(2个字节)
2、接收到芯片地址	0XFFFFFFFF	(4个字节)
3、接收到包标识:	0X07		(1个字节)
4、接收到包长度:	0X0003		(2个字节)
5、接收到确认码:	xxH			(1个字节)
6、接收到校验和:	SUM			(2个字节)

xxH(确认码):
00H:		删除模板成功
01H:		收包有误
10H:		删除模板失败

SUM(校验和)

7.清空指纹库-PS_Empty

功能:	 	删除flash数据库所有指纹模板
参数: 	 	无
返回: 	 	确认字
指令代码: 	0DH

简述:
首先我们通过指令码包给AS608指纹模块让它清空所有模板,指纹模块会返回应答包给我们。我们通过应答包的确认字去判断这次的结果。
指令包格式:
在这里插入图片描述

首先我们是我们给指纹模块发送的内容 可以结合上图指令包格式

1、发送包头:		0XEF01 		(2个字节)
2、发送芯片地址:	0XFFFFFFFF	(4个字节)
3、发送包标识:	0X01		(1个字节)
4、发送包长度:	0X0003		(2个字节)
5、发送指令码:	0X0D		(1个字节)
6、发送校验和:	0X0011		(2个字节)

应答包格式
在这里插入图片描述

发送完指令包给指纹模块 我们则会收到它发的应答包 可以结合上图应答包格式

1、接收到包头:	0XEF01 		(2个字节)
2、接收到芯片地址	0XFFFFFFFF	(4个字节)
3、接收到包标识:	0X07		(1个字节)
4、接收到包长度:	0X0003		(2个字节)
5、接收到确认码:	xxH			(1个字节)
6、接收到校验和:	SUM			(2个字节)

xxH(确认码):
00H:		清空所有成功
01H:		收包有误
10H:		清空所有失败

SUM(校验和)

你都看到这里了,那么你删除指纹的操作就可以完成了。

8.高速搜索指纹-PS_HighSpeedSearch

功能:	 	以CharBuffer1 或 CharBuffer2中的特征文件高速搜索整个或部分指纹库。如果搜索到,返回页码。
参数: 	 	BufferID(0x01/0x02),StartPage(起始页),PageNum(页数)
返回: 	 	确认字,页码(匹配的指纹模板)
指令代码: 	1BH

简述:
首先我们通过指令码包给AS608指纹模块让它高速搜索是否和咱这个指纹一样,指纹模块会返回应答包给我们。我们通过应答包的确认字去判断这次的结果。
指令包格式:
在这里插入图片描述

首先我们是我们给指纹模块发送的内容 可以结合上图指令包格式

1、发送包头:		0XEF01 		(2个字节)
2、发送芯片地址:	0XFFFFFFFF	(4个字节)
3、发送包标识:	0X01		(1个字节)
4、发送包长度:	0X0008		(2个字节)
5、发送指令码:	0X1B		(1个字节)
6、发送缓冲区号:	BufferID	(1个字节)
7、发送起始页:	StartPage	(2个字节)
7、发送页数:		PageNum		(2个字节)
7、发送校验和:	SUM			(2个字节)

StartPage(起始页):开始搜索的页码
PageNum(页数):	 搜索多少页

SUM(校验和) = 包标识+包长度+指令码+BufferID+StartPage+PageNum;
SUM(校验和) = 0x01+0x08+0x1B+BufferID+StartPage+PageNum;

应答包格式
在这里插入图片描述

发送完指令包给指纹模块 我们则会收到它发的应答包 可以结合上图应答包格式

1、接收到包头:	0XEF01 		(2个字节)
2、接收到芯片地址	0XFFFFFFFF	(4个字节)
3、接收到包标识:	0X07		(1个字节)
4、接收到包长度:	0X0007		(2个字节)
5、接收到确认码:	xxH			(1个字节)
6、接收到页码:	PageID		(2个字节)
7、接收到得分:	MatchScore	(2个字节)
8、接收到校验和:	SUM			(2个字节)

xxH(确认码):
00H:		搜索到
01H:		收包有误
09H:		没有搜索到 页码和得分也会是 0

SUM(校验和)

9.搜索指纹-PS_Search

功能:	 	以CharBuffer1 或 CharBuffer2中的特征文件搜索整个或部分指纹库。如果搜索到,返回页码。
参数: 	 	BufferID(0x01/0x02),StartPage(起始页),PageNum(页数)
返回: 	 	确认字,页码(匹配的指纹模板)
指令代码: 	04H

简述:
首先我们通过指令码包给AS608指纹模块让它搜索是否和咱这个指纹一样,指纹模块会返回应答包给我们。我们通过应答包的确认字去判断这次的结果。
指令包格式:
在这里插入图片描述

首先我们是我们给指纹模块发送的内容 可以结合上图指令包格式

1、发送包头:		0XEF01 		(2个字节)
2、发送芯片地址:	0XFFFFFFFF	(4个字节)
3、发送包标识:	0X01		(1个字节)
4、发送包长度:	0X0008		(2个字节)
5、发送指令码:	0X04		(1个字节)
6、发送缓冲区号:	BufferID	(1个字节)
7、发送起始页:	StartPage	(2个字节)
7、发送页数:		PageNum		(2个字节)
7、发送校验和:	SUM			(2个字节)

StartPage(起始页):开始搜索的页码
PageNum(页数):	 搜索多少页

SUM(校验和) = 包标识+包长度+指令码+BufferID+StartPage+PageNum;
SUM(校验和) = 0x01+0x08+0x04+BufferID+StartPage+PageNum;

应答包格式
在这里插入图片描述

发送完指令包给指纹模块 我们则会收到它发的应答包 可以结合上图应答包格式

1、接收到包头:	0XEF01 		(2个字节)
2、接收到芯片地址	0XFFFFFFFF	(4个字节)
3、接收到包标识:	0X07		(1个字节)
4、接收到包长度:	0X0007		(2个字节)
5、接收到确认码:	xxH			(1个字节)
6、接收到页码:	PageID		(2个字节)
7、接收到得分:	MatchScore	(2个字节)
8、接收到校验和:	SUM			(2个字节)

xxH(确认码):
00H:		搜索到
01H:		收包有误
09H:		没有搜索到 页码和得分也会是 0

SUM(校验和)

这两个都是搜索。。一个高速一个不是 我估计就是高速更快,但是估计没不高速那个那么精确吧。个人感觉。
你都看到这里了,那么你验证指纹的操作就可以完成了。

10.查有效模板个数-PS_ValidTempleteNum

功能:	 	读取有效模板个数(查询当前一共有多少个指纹)
参数: 	 	无
返回: 	 	确认字,有效模板个数ValidN
指令代码: 	1DH

简述:
首先我们通过指令码包给AS608指纹模块让它清空所有模板,指纹模块会返回应答包给我们。我们通过应答包的确认字去判断这次的结果。
指令包格式:
在这里插入图片描述

首先我们是我们给指纹模块发送的内容 可以结合上图指令包格式

1、发送包头:		0XEF01 		(2个字节)
2、发送芯片地址:	0XFFFFFFFF	(4个字节)
3、发送包标识:	0X01		(1个字节)
4、发送包长度:	0X0003		(2个字节)
5、发送指令码:	0X1D		(1个字节)
6、发送校验和:	0X0021		(2个字节)

应答包格式
在这里插入图片描述

发送完指令包给指纹模块 我们则会收到它发的应答包 可以结合上图应答包格式

1、接收到包头:	0XEF01 		(2个字节)
2、接收到芯片地址	0XFFFFFFFF	(4个字节)
3、接收到包标识:	0X07		(1个字节)
4、接收到包长度:	0X0005		(2个字节)
5、接收到确认码:	xxH			(1个字节)
6、接收到模板数:	ValidN		(2个字节)
7、接收到校验和:	SUM			(2个字节)

xxH(确认码):
00H:		读取成功
01H:		收包有误

SUM(校验和)

你都看到这里了,那么你查询当前有多少个指纹就可以完成了。

11.关于包长度和校验和

指令包格式:
在这里插入图片描述
包长度如何计算的?
我们可以看出来嘛 包长度这个表格是说3个。那么我看后面确实还剩3个字节。1字节的指令码+2字节的校验和 = 3字节。
结论: 包长度: 提示了后面还有多少个字节数据

校验和如何计算的?
我们同样也可以看出来 它的校验和是说是5。那么我们很容易发现,校验和其实是 从 包标识 0x01 + 包长度 0x0003 + 指令码 0x01 = 5。
结论: 校验和 = 包标识开始 + … 到校验和 但不含校验和。

三: 编写指令集代码

0.预代码

看到这里了你也知道了发送指令包其实很多都是一样的,比如发送包头,发送芯片地址…等。我们现在打包成一个个函数。这样方便我们后面编写各个功能指令函数。
预定义:

#define		CharBuffer1		0x01
#define		CharBuffer2		0x02
uint16_t AS608_HEAD = 0XEF01;			//包头
uint32_t AS608_ADDR	= 0XFFFFFFFF;		//芯片地址

然后下面就是一些打包的函数

/***************************************************************************
描述: 发送包头
****************************************************************************/
static void as608_send_head(void)
{
    
    
	USART2_SendData(AS608_HEAD>>8);
	USART2_SendData(AS608_HEAD);
}

/***************************************************************************
描述: 发送芯片地址
****************************************************************************/
static void as608_send_address(void)
{
    
    
	USART2_SendData(AS608_ADDR>>24);
	USART2_SendData(AS608_ADDR>>16);
	USART2_SendData(AS608_ADDR>>8);
	USART2_SendData(AS608_ADDR);
}

/***************************************************************************
描述: 发送包标识
****************************************************************************/
static void as608_send_logo(uint8_t logo)
{
    
    
	USART2_SendData(logo);
}

/***************************************************************************
描述: 发送包长度
****************************************************************************/
static void as608_send_length(uint16_t length)
{
    
    
	USART2_SendData(length>>8);
	USART2_SendData(length);
}

/***************************************************************************
描述: 发送指令码
****************************************************************************/
static void as608_send_cmd(uint8_t cmd)
{
    
    
	USART2_SendData(cmd);
}


/***************************************************************************
描述: 发送校验和
****************************************************************************/
static void as608_send_checksum(uint16_t checksum)
{
    
    
	USART2_SendData(checksum>>8);
	USART2_SendData(checksum);
}

/***************************************************************************
描述: 发送BufferID
****************************************************************************/
static void as608_send_BufferID(uint8_t BufferID)
{
    
    
	USART2_SendData(BufferID);
}

/***************************************************************************
描述: 发送StartPage
****************************************************************************/
static void as608_send_StartPage(uint16_t StartPage)
{
    
    
	USART2_SendData(StartPage>>8);
	USART2_SendData(StartPage);
}

/***************************************************************************
描述: 发送PageNum
****************************************************************************/
static void as608_send_PageNum(uint16_t PageNum)
{
    
    
	USART2_SendData(PageNum>>8);
	USART2_SendData(PageNum);
}

/***************************************************************************
描述: 发送PageID号
****************************************************************************/
static void as608_send_PageID(uint16_t PageID)
{
    
    
	USART2_SendData(PageID>>8);
	USART2_SendData(PageID);
}

/***************************************************************************
描述: 发送个数
****************************************************************************/
static void as608_send_N(uint16_t N)
{
    
    
	USART2_SendData(N>>8);
	USART2_SendData(N);
}

好了封装了一下 这下子就方便多了

1.读取图像-PS_GetImage

/***************************************************************************
描述: 获取手指指纹图像 存放于图像缓冲区
参数: 无 					指令代码:02H
返回: 00H: 录入指纹成功		01H:收包错误	02H:无手指	03H:录入不成功
****************************************************************************/
uint8_t PS_GetImage(void)
{
    
    	
	uint8_t result;				//存放结果

	CLEAR_BUFFER;				//清空缓冲区
	
	as608_send_head();			//发送包头
	as608_send_address();		//发送芯片地址
	as608_send_logo(0x01);		//发送包标识
	as608_send_length(0x03);	//发送包长度
	as608_send_cmd(0x01);		//发送指令码
	as608_send_checksum(0x05);	//发送校验和
	OPEN_USART2_RECEIVE;		//开启串口接收

	result = as608_detection_data(300,NULL);	//检测指纹模块数据 3秒时间
	if(result == 0XFF)	result = 0x01;	

	return result;
}

2.生成特征-PS_GenChar

/***************************************************************************
描述: 生成特征
参数: BufferID(特征缓冲区号) 指令代码:02H 
	  CharBuffer1 的 BufferID: 01H  CharBuffer2的 BufferID: 02H
返回: 00H: 生成特征成功		01H:收包错误	06H:指纹图像太乱生成失败
	  07H: 特征太少			15H:图像缓冲区没图像
****************************************************************************/
uint8_t PS_GenChar(uint8_t BufferID)
{
    
    
	uint16_t checksum;				//存放校验和
	uint8_t result;					//存放结果

	CLEAR_BUFFER;					//清空缓冲区
	as608_send_head();				//发送包头
	as608_send_address();			//发送芯片地址
	as608_send_logo(0x01);			//发送包标识
	as608_send_length(0x04);		//发送包长度
	as608_send_cmd(0x02);			//发送指令码
	as608_send_BufferID(BufferID);	//发送BufferID
	checksum = 0x01 + 0x04 + 0x02 + BufferID;	
	as608_send_checksum(checksum);	//发送校验和
	OPEN_USART2_RECEIVE;			//开启串口接收	

	result = as608_detection_data(300,NULL);	//检测指纹模块数据 3秒时间
	if(result == 0XFF)	result = 0x01;	

	return result;
}

3.比对特征-PS_Match

/***************************************************************************
描述: 精确比对两枚指纹特征 
参数: 无					指令代码:03H 
返回: 00H: 指纹匹配成功		08H:指纹不匹配		01H:收包错误
****************************************************************************/
uint8_t PS_Match(void)
{
    
    
	uint8_t result;					//存放结果
	
	CLEAR_BUFFER;					//清空缓冲区
	as608_send_head();				//发送包头
	as608_send_address();			//发送芯片地址
	as608_send_logo(0x01);			//发送包标识
	as608_send_length(0x03);		//发送包长度
	as608_send_cmd(0x03);			//发送指令码
	as608_send_checksum(0x07);		//发送校验和
	OPEN_USART2_RECEIVE;			//开启串口接收

	result = as608_detection_data(300,NULL);	//检测指纹模块数据 3秒时间
	if(result == 0XFF)	result = 0x01;	

	return result;
}

4.生成模板-PS_RegModel

/***************************************************************************
描述: 合并特征 将CharBuffer1 和 CharBuffer2 中的 特征合并生成模板 
	  结果存在CharBuffer1 和 CharBuffer2	
参数: 无				指令代码:05H 
返回: 00H: 合并成功		01H:收包错误	0AH:合并失败(两枚手指不是同一个)
****************************************************************************/
uint8_t PS_RegModel(void)
{
    
    
	uint8_t result;					//存放结果

	CLEAR_BUFFER;					//清空缓冲区
	as608_send_head();				//发送包头
	as608_send_address();			//发送芯片地址
	as608_send_logo(0x01);			//发送包标识
	as608_send_length(0x03);		//发送包长度
	as608_send_cmd(0x05);			//发送指令码
	as608_send_checksum(0x09);		//发送校验和
	OPEN_USART2_RECEIVE;			//开启串口接收

	result = as608_detection_data(300,NULL);	//检测指纹模块数据 3秒时间
	if(result == 0XFF)	result = 0x01;	

	return result;		
}

5.储存模板-PS_StoreChar

/***************************************************************************
描述: 储存模板 将CharBuffer1和CharBuffer2的模板文件存到PageID号Flash数据库位置 
参数: BufferID:	01H/02H		PageID:指纹库位置号		指令代码:06H 
返回: 00H: 储存成功	01H:收包错误 0BH:PageID超出指纹库范围 18H:写Flash出错
****************************************************************************/
uint8_t PS_StoreChar(uint8_t BufferID,uint16_t PageID)
{
    
    
	uint16_t checksum;				//存放校验和
	uint8_t result;					//存放结果

	CLEAR_BUFFER;					//清空缓冲区
	as608_send_head();				//发送包头
	as608_send_address();			//发送芯片地址
	as608_send_logo(0x01);			//发送包标识
	as608_send_length(0x06);		//发送包长度
	as608_send_cmd(0x06);			//发送指令码
	as608_send_BufferID(BufferID);	//发送BufferID
	as608_send_PageID(PageID);		//发送指纹库位置号	
	checksum = 0x01+0x06+0x06+BufferID+PageID;
	as608_send_checksum(checksum);	//发送校验和
	OPEN_USART2_RECEIVE;			//开启串口接收	

	result = as608_detection_data(300,0);	//检测指纹模块数据 3秒时间
	if(result == 0XFF)	result = 0x01;	

	return result;		
}

6.删除模板-PS_DeletChar

/***************************************************************************
描述: 删除模板  删除Flash数据库中指定的ID号开始的N个指纹模板
参数: PageID:指纹库模板号 N:删除的模板个数		指令代码:0CH 
返回: 00H: 删除模板成功		01H:收包错误 	10H:删除模板失败
****************************************************************************/
uint8_t PS_DeletChar(uint16_t PageID,uint16_t N)
{
    
    
	uint16_t checksum;				//存放校验和
	uint8_t result;					//存放结果

	CLEAR_BUFFER;					//清空缓冲区
	as608_send_head();				//发送包头
	as608_send_address();			//发送芯片地址
	as608_send_logo(0x01);			//发送包标识
	as608_send_length(0x07);		//发送包长度
	as608_send_cmd(0x0C);			//发送指令码
	as608_send_PageID(PageID);		//发送指纹库位置号
	as608_send_N(N);				//发送删除模板的个数
	
	checksum = 0x01+0x07+0x0C+PageID+N;
	as608_send_checksum(checksum);		//发送校验和
	OPEN_USART2_RECEIVE;			//开启串口接收	

	result = as608_detection_data(300,NULL);	//检测指纹模块数据 3秒时间
	if(result == 0XFF)	result = 0x01;	

	return result;			
}

7.清空指纹库-PS_Empty

/***************************************************************************
描述: 清空Flash数据库中所有指纹模板 
参数: 无				指令代码:0DH 
返回: 00H: 清空成功	01H:收包错误 	11H:清空失败
****************************************************************************/
uint8_t PS_Empty(void)
{
    
    
	uint8_t result;					//存放结果

	CLEAR_BUFFER;					//清空缓冲区
	as608_send_head();				//发送包头
	as608_send_address();			//发送芯片地址
	as608_send_logo(0x01);			//发送包标识
	as608_send_length(0x03);		//发送包长度
	as608_send_cmd(0x0D);			//发送指令码
	as608_send_checksum(0X11);		//发送校验和
	OPEN_USART2_RECEIVE;			//开启串口接收	

	result = as608_detection_data(300,NULL);	//检测指纹模块数据 3秒时间
	if(result == 0XFF)	result = 0x01;	

	return result;			
}

8.高速搜索指纹-PS_HighSpeedSearch

/***************************************************************************
描述: 高速搜索 以CharBuffer1或CharBuffer2的特征文件高速搜索整个或者部分指纹库 
参数: BufferID:	01H/02H	  StartPage:起始页	 PageNum:页数	指令代码:1BH 
      ID: 存放搜索到的指纹ID号 否则为0
返回: 确认字00H: 搜索到	01H:收包错误 09H:没有搜索到(页码就是0) 和 对应页码
****************************************************************************/
uint8_t PS_HighSpeedSearch(uint8_t BufferID,uint16_t StartPage,uint16_t PageNum,uint16_t *ID)
{
    
    
	uint16_t checksum;				//存放校验和
	uint8_t result;					//存放结果

	CLEAR_BUFFER;					//清空缓冲区
	as608_send_head();				//发送包头
	as608_send_address();			//发送芯片地址
	as608_send_logo(0x01);			//发送包标识
	as608_send_length(0x08);		//发送包长度
	as608_send_cmd(0x1B);			//发送指令码
	as608_send_BufferID(BufferID);	//发送BufferID
	as608_send_StartPage(StartPage);//发送起始页
	as608_send_PageNum(PageNum);	//发送页数	
	checksum = 0x01+0x08+0x1B+BufferID+StartPage+PageNum;
	as608_send_checksum(checksum);	//发送校验和
	OPEN_USART2_RECEIVE;			//开启串口接收	

	result = as608_detection_data(300,&ID);	//检测指纹模块数据 3秒时间
	if(result == 0XFF)	result = 0x01;	

	return result;			
}

9.搜索指纹-PS_Search

/***************************************************************************
描述: 搜索指纹 								指令代码:04H 
参数: BufferID:	01H/02H	 StartPage:起始页	PageNum:页数 
	  ID: 存放搜索到的指纹ID号 否则为0
返回: 00H: 搜索到	09H:没有搜索到 		01H:收包错误
****************************************************************************/
uint8_t PS_Search(uint8_t BufferID,uint16_t StartPage,uint16_t PageNum,uint16_t *ID)
{
    
    
	uint16_t checksum;				//存放校验和
	uint8_t result;					//存放结果
	
	CLEAR_BUFFER;					//清空缓冲区
	as608_send_head();				//发送包头
	as608_send_address();			//发送芯片地址
	as608_send_logo(0x01);			//发送包标识
	as608_send_length(0x08);		//发送包长度
	as608_send_cmd(0x04);			//发送指令码
	as608_send_BufferID(BufferID);	//发送BufferID
	as608_send_StartPage(StartPage);//发送起始页
	as608_send_PageNum(PageNum);	//发送页数
	checksum = 0x01+0x08+0x04+BufferID+StartPage+PageNum;
	as608_send_checksum(checksum);	//发送校验和
	OPEN_USART2_RECEIVE;			//开启串口接收		
	
	result = as608_detection_data(300,&ID);	//检测指纹模块数据 3秒时间
	if(result == 0XFF)	result = 0x01;	

	return result;	
}

10.查有效模板个数-PS_ValidTempleteNum

/***************************************************************************
描述: 读取模板个数 
参数: NUM:个数会保存在NUM中			指令代码:1DH 
返回: 00H: 注册成功	01H:收包错误 	NUM也会返回
****************************************************************************/
uint8_t PS_ValidTempleteNum(uint16_t *NUM)
{
    
    
	uint8_t result;					//存放结果

	CLEAR_BUFFER;					//清空缓冲区
	as608_send_head();				//发送包头
	as608_send_address();			//发送芯片地址
	as608_send_logo(0x01);			//发送包标识
	as608_send_length(0x03);		//发送包长度
	as608_send_cmd(0x1D);			//发送指令码
	as608_send_checksum(0X21);		//发送校验和
	OPEN_USART2_RECEIVE;			//开启串口接收	

	result = as608_detection_data(300,&NUM);	//检测指纹模块数据 3秒时间
	if(result == 0XFF)	result = 0x01;	

	return result;			
}

三: 指纹代码编写

0.接收处理

我思路是这样的 返回的指令包都有一个固定的格式的,我们通过是否和这个固定的格式匹配,如果匹配再进行下一步,为了数据准确性,我这里还校验一下这个校验和,如果是找到这个数据格式头,但是校验和是错的,那数据也是有问题的。

第一步:匹配固定数据格式
第二步:校验和验证
第三步:返回确认码(如果有ID,或者模板个数,则需要传变量过去进行存放)

匹配固定数据格式

/***************************************************************************
描述: 检测串口返回的数据
参数: wait_time:等待的时间 一次:10ms	
ID_OR_NUM: 如果不是搜索指令或者查找模板个数设置为NULL 否则存放ID号或者NUM个数	
返回: 无效数据返回0XFF  否则返回结果
****************************************************************************/
uint8_t as608_detection_data(uint16_t wait_time,uint16_t **ID_OR_NUM)
{
    
    
	char *data;
	uint8_t result = 0XFF;	//存放结果

	while(wait_time--)
	{
    
    	
		delay_ms(10);
		//匹配数据帧头
		data = strstr((char *)as608_receive_data,(char *)check_head);
		if(data != NULL)
		{
    
    
			result = as608_detection_checknum(data,&*ID_OR_NUM);	
			break;
		}	
	}
	CLOSE_USART2_RECEIVE;			//禁止串口接收
	return result;	
}

验证校验和是否准确

/***************************************************************************
描述: 校验数据是否正确
参数: data:数据包		
ID_OR_NUM: 如果不是搜索指令或者查找模板个数设置为NULL 否则存放ID号或者NUM个数	
返回: 数据错误返回0XFF   否则 返回接收结果
****************************************************************************/
uint8_t as608_detection_checknum(char *data , uint16_t **ID_OR_NUM)
{
    
    
	//包标识位置:6	包长度位置:7、8
	uint8_t packet_length;	//包长度
	uint8_t checksum1 = 0;		//数据包校验和
	uint8_t checksum2 = 0;		//计算出的校验和
	uint8_t i;

	packet_length = (data[7]*10) + data[8];	//获取数据包长度
	if(packet_length == 0) return 0XFF;		//如果无长度 返回错误
	
	checksum1 = (data[6+packet_length+1]*10) + data[6+packet_length+2];	//数据包校验和

	//自己校验的校验和
	for(i=0;i<packet_length+1;i++)
	{
    
    
		checksum2 += data[i+6];
	}
	//匹配校验和是否准确
	if(checksum1 == checksum2)
	{
    
    
		//如果是搜索指令 ID进行保存 如果是查找模板个数 NUM进行保存
		if(*ID_OR_NUM != NULL)
			**ID_OR_NUM = (data[10]*10) + data[11];	//获取指纹ID号/模板个数
	
		printf("数据校验和匹配 数据位:%#X\r\n",data[9]);
		return data[9];		//返回结果
		
	}
	printf("数据校验和错误\r\n");
	return 0XFF;
}

检测手指是否在

/***************************************************************************
描述: 检测手指是否在模块中
参数: wait_time:等待的时间 一次:10ms
返回: 0:手指在 	1:不在
****************************************************************************/
uint8_t as608_detection_finger(uint16_t wait_time)
{
    
    
	finger_status = FINGER_NO_EXIST;
	//检测手指是否在模块中
	while(wait_time--)
	{
    
    
		delay_ms(10);
		if(finger_status == FINGER_EXIST)
		{
    
    
			finger_status = FINGER_NO_EXIST;
			return 0;
		}	
	}
	return 1;
}

1.添加指纹

首先添加指纹需要的步骤:

第一步:读取指纹图像
第二步:生成特征(存放在CharBuffer1)
第三步:再次读取指纹图像
第四步:生成特征(存放在CharBuffer2)
第五步:比对两个特征是否一样
第六步:合并特征生成模板
第七步:存储模板(我这里是CharBuffer2,以及设置存放的位置:PageID)
/***************************************************************************
描述: 添加指纹 函数
返回: 0: 录入指纹成功	1: 录入指纹失败
****************************************************************************/
uint8_t as608_add_fingerprint(uint16_t PageID)
{
    
    
	uint8_t result;					//录入的结果
	uint8_t add_stage = 1;			//录入的阶段
	
	while(add_stage != EXIT)
	{
    
    
		switch(add_stage)
		{
    
    
			//第一阶段 获取第一次指纹图像 并且生成特征图
			case 1:
				printf("请放置手指\r\n");
				if(as608_detection_finger(800))	return 0x02;	//等待手指按下			
				result = PS_GetImage();	//获取指纹图像
				if(result) return 1;
				result = PS_GenChar(CharBuffer1);//生成特征图	
				if(result) return 1;
				add_stage = 2;		//跳转到第二阶段
				break;
			
			//第二阶段 获取第二次指纹图像 并且生成特征图
			case 2:
				printf("请再放置手指\r\n");
				if(as608_detection_finger(800))	return 0x02;	//等待手指按下		
				result = PS_GetImage();	//获取指纹图像
				if(result)	return 1;
				result = PS_GenChar(CharBuffer2);//生成特征图
				if(result)	return 1;
				add_stage = 3;	//跳转到第三阶段
				break;		

			//第三阶段 比对两枚指纹特征
			case 3:
				result = PS_Match();//比对两枚指纹特征
				if(result)	return 1;
				add_stage = 4;		//跳转到第四阶段
				break;

			//第四阶段 特征合并生成模板
			case 4:
				result = PS_RegModel();//特征合并生成模板
				if(result)	return 1;
				add_stage = 5;		//跳转到第五阶段				
				break;

			//第五阶段 储存模板
			case 5:
				result = PS_StoreChar(CharBuffer2,PageID);//储存模板
				if(result)	return 1;
				add_stage = EXIT;
				break;
		}		
	}
	
	return 0;
	
}

2.验证指纹

首先验证指纹的步骤:

第一步:读取指纹图像
第二步:生成特征(存放在CharBuffer1)
第三步:高速搜索
/***************************************************************************
描述: 验证指纹 函数
返回: 返回ID号  如果没有该指纹则ID是0 
****************************************************************************/
uint16_t as608_verify_fingerprint(void)
{
    
    
	uint8_t result;				//存放结果
	uint8_t verify_stage = 1;	//验证的阶段
	uint16_t ID = 0;			//存放指纹的ID号

	while(verify_stage != EXIT)
	{
    
    
		switch(verify_stage)
		{
    
    
			//第一阶段 获取指纹图像
			case 1:
				printf("请放置手指\r\n");			
				if(as608_detection_finger(800))	return 0x02;	//等待手指按下			
				result = PS_GetImage();	//获取指纹图像
				if(result)	verify_stage = EXIT;
				verify_stage = 2;
				break;
			
			//第二阶段 生成特征图
			case 2:
				result = PS_GenChar(CharBuffer1);//生成特征图
				if(result)	verify_stage = EXIT;
				verify_stage = 3;
				break;	


			//第三阶段 高速搜索
			case 3:
				result = PS_HighSpeedSearch(CharBuffer1,0,99,&ID);
				if(result)	ID = 0;
				verify_stage = EXIT;
				break;				
		}		
	}
	if(ID == 0x00)
		printf("验证指纹失败 ID:%d\r\n",ID);
	else
		printf("验证指纹成功 ID:%d\r\n",ID);
	return ID;
}

3.删除指纹

1.删除单个或多个

我这里只是删除一个 删除多个修改PS_DeletChar()第二参数即可
步骤:

第一步:先验证是否有这个指纹,如果没有就那删除啥是吧,直接返回就行。
第二步:把验证到的指纹ID给到删除指纹函数执行即可。
/***************************************************************************
描述: 删除指纹 函数
返回: 0: 删除指纹成功	1: 删除指纹失败
****************************************************************************/
uint8_t as608_delete_fingerprint(void)
{
    
    
	uint8_t result;					//存放结果
	uint16_t ID;					//存放ID号
	
	//1-识别要删除的指纹 如果没有这个指纹 则返回1
	ID = as608_verify_fingerprint();
	if(ID == 0X00)
	{
    
    
		printf("删除指纹失败-没有该指纹\r\n");
		return 1;
	}
	//2-针对ID号码进行删除
	result = PS_DeletChar(ID,1);		//删除指纹 ID号 
	if(result)
		printf("删除指纹失败 ID:%d\r\n",ID);
	else
		printf("删除指纹成功 ID:%d\r\n",ID);
	return 0;
}

2.删除所有

这个比较简单

/***************************************************************************
描述: 清空所有指纹 函数
返回: 0: 清空所有指纹成功	1: 清空所有指纹失败
****************************************************************************/
uint8_t as608_empty_all_fingerprint(void)
{
    
    
	uint8_t result;		//存放结果
	
	result = PS_Empty();	//删除所有指纹
	switch(result)
	{
    
    
		case 0x00:
			printf("清空所有指纹成功\r\n");
			break;
		case 0x01:
			printf("清空所有指纹失败-收包错误\r\n");
			break;
		case 0x11:
			printf("清空所有指纹失败-清空失败\r\n");
			break;	
	}
	if(result) result = 1;
	return result;
}

4.查询指纹个数

/***************************************************************************
描述: 查找 指纹个数 函数
返回: 查找到的个数
****************************************************************************/
uint8_t as608_find_fingerprints_num(void)
{
    
    
	uint8_t result;
	uint16_t NUM;		//存放指纹个数(模板个数)
	result = PS_ValidTempleteNum(&NUM);
	if(result)
		printf("查找指纹个数失败 NUM:%d\r\n",NUM);
	else
		printf("查找指纹个数成功 NUM:%d\r\n",NUM);	
	return NUM;
}


代码基本就是这些啦

四: 主程序代码

#include "stm32f10x.h"
#include "delay.h"
#include "usart.h"
#include "as608.h"

uint8_t handler_flag;

/**************************************************************
描述:菜单
***************************************************************/
void menu(void)
{
    
    
	printf("=============================\r\n");
	printf("\t1-添加指纹\r\n");
	printf("\t2-验证指纹\r\n");
	printf("\t3-删除指纹\r\n");
	printf("\t4-查询指纹个数\r\n");
	printf("=============================\r\n");
}

int  main()
{
    
    
	uint8_t ID = 0;
	usart1_init(115200);	//串口1初始化 用于打印信息和输入信息
	usart2_init(57600);		//串口2初始化 用于和指纹模块通信
	as60x_wak_init();		//指纹模块初始化
	printf("      --指纹模块小Demo--\r\n");
	menu();
	while(1)
	{
    
    
		
		switch(handler_flag)
		{
    
    
			//添加指纹
			case 1:
				
			SCANF:
				printf("\t添加指纹\r\n");
				handler_flag = 0;
				ID = 0;
				printf("请输入ID号(1~9)\r\n");
				while(ID == 0)
				{
    
    	
					ID = handler_flag;
				}
				if(ID >0 && ID < 10)		printf("ID号:%d\r\n",ID);		
				else						goto SCANF;
					
				if(as608_add_fingerprint(ID))	printf("添加指纹失败\r\n");
				else						 	printf("添加指纹成功\r\n");
				handler_flag = 0;
				menu();
				break;
			//验证指纹
			case 2:
				printf("\t验证指纹\r\n");
				as608_verify_fingerprint();
				handler_flag = 0;
				menu();
				break;	
			//删除指纹
			case 3:
				printf("\t删除指纹\r\n");
				as608_delete_fingerprint();	
				handler_flag = 0;	
				menu();
				break;			
			//查询模板个数
			case 4:
				printf("\t查看指纹个数\r\n");
				as608_find_fingerprints_num();
				handler_flag = 0;					
				menu();
				break;
		}
	}  
}


五: 项目展示

在这里插入图片描述

六: 总结

都看到这里了,不妨给我点个赞啥的哈,哈哈哈哈鼓励鼓励。

==问题:==指纹这个不难。按着手册写就行,然后我这里发现了一个问题,我不知道是不是我模块有问题,还是都这样的。
就是WAK引脚,正常是不按是低电平,有手指按就是高电平,但是我发现,它不管你三七二十一,大概是每隔1分钟多点,它自动会高电平几次,然后恢复低电平。。。。。一开始以为我程序有问题,后来发现是这个模块就这样。。。。不知道大家的是不是也这样。

如果我哪里写的有问题,或者不好,请大家多多指教

#整个工程代码。
printf("+meQ:844797079\n")

如果觉得这篇文章对你有用。欢迎大家点赞、评论哈哈
需要整个工程代码,欢迎大家打赏,请o( ̄︶ ̄)o

继续加油!!!

猜你喜欢

转载自blog.csdn.net/weixin_47457689/article/details/125013474