AS608光学指纹模组编程和应用详解

一、前言

上次讲解了两个简单实用的传感器,反馈很多,能够帮助到大家,我也很开心。所以今天继续给大家介绍一个实用易上手的传感器,在这里有些同学可能就会质疑了,指纹识别哪里简单了?别急,容我细细道来,看完整篇文章,你可能就会觉得,不过如此嘛。
需要程序源码,原理图,数据手册等资料可以到文章底部的链接自行下载。因为这个是我大学做毕设时用到的一个模块,内容比较多,有些细节一时记不清了,所以有些地方可能讲的不是特别深入,如果你们有什么地方看不懂,可以留言和私信给我,我再给你们解答。
如果能够帮助到你,请点赞+关注,又快到做毕设的日子了,我后面也会继续写更多的博文,希望能够帮到你们。

二、芯片介绍

1、芯片简介
AS608是一个集成的光学指纹芯片,内部有指纹算法,其实指纹识别最难的地方在于算法,目前的算法是前人不断开发完善得到的,所以在前几年,算法都是某些大企业独有的技术,他们只卖芯片不卖算法。当然现在的话,光学指纹的算法也逐渐放出来了,因为现在用的更多的是半导体,超声波指纹识别,光学指纹他们已经玩腻了。说远了,回归正题,虽然AS608内部的算法我们是看不到的,但是它预留了一个串口和相关的串口指令集,我们可以用这些指令调用指纹算法,从而实现我们需要的功能。

2、引脚定义

三、通讯原理和通讯的流程讲解

1、通讯方法
通过给AS608串口发送特定的指令,就可以调用里面的算法,进行相应的操作。这些指令有三种格式:命令包格式,数据包格式和接收包格式。命令包是用来控制AS608的,数据包和结束包只在导出(把模块里面的指纹导出到别的设备)和导入(把其他设备的数据导入模块)指纹数据的时候用到的。

我这里以命令包格式为例,给大家讲解一下,包头是2个字节的数据,固定为0xEF01;芯片地址4个字节,默认是0xFFFFFFFF,可以后面发送指令修改;包识别是用来区分指令的类型的,如命令包固定为0x01;包长度是指这一条指令有多少个重要的数据,包长度=包长度至校验和(指令、参数或数据)的总字节数,包含校验和,但不包含包长度本身的字节数;指令就是需要AS608执行的操作,具体的定义我后面再说;参数和具体的指令有关,不同的指令,参数的长度和数值都有所不同;校验和是为了确保串口通讯过程中出现错误,导致命令出错,校验和是从包标识至校验和之间所有字节之和。

2、功能的实现及通讯的流程
我这里只详细讲解录入指纹、识别指纹和删除指纹这三个最常用的功能的实现和操作步骤。如果你们需要用到导出和导入指纹,可以留言或私信给我,我再详细讲解。
1)录入指纹
录入指纹有以下几个步骤:
第一,录入图像。当你的手指放在光学指纹窗口的时候执行这个指令,就可以把指纹的图像拍下来。
第二,生成特征。当你的指纹图像拍下来之后,调用这个指令就可以把图像中的指纹特征记录下来。AS608里面有2个缓存区可以存这个特征,我们这里先用第1个存。
第三,再次录入图像。把同一个手指放在光学指纹窗口,然后执行这个指令,再拍一个指纹图像。
第四,再次生成特征。把第二次录入的图像的指纹特征存到第2个缓存区。
第五.精确比对两枚指纹特征。录入指纹的时候为了增加准确性,最好是记录多次指纹特征,这个指令就是对录入的两个指纹特征进行比对,如果一致就说明是同一个人的同一个指纹。
第六,合并特征(生成模板)。当录入了两个指纹特征,并且两个特征是一致的时候,就可以把两个特征合并成一个指纹模板。这个指纹模板就是我们最终要录入的指纹。
第七,储存模板。当生成一个模板的时候,我们可以把这个模板存到AS608内部的Flash里面,存储的时候需要输入一个指纹ID号,这个ID其实是Flash的地址,不同的ID号,存储的位置不同,最多好像能存两三百个指纹。
2)识别指纹
第一,录入图像。这一步和录入指纹的第一步是一样的,目的是把指纹的图像拍下来。
第二,生成特征。这一步和录入指纹的第二步是一样的。指纹特征可以存到第一个缓存区也可以存到第二个缓存区。
第三,搜索指纹。调用这个指令就会将已经存在Flash里面的指纹模板和缓存区的指纹特征一一比对,如果有搜索到,会返回这个指纹的ID。要注意的是,调用的时候需要指明比对的特征是缓存区1还是缓存区2,你要选择第二步生成的特征所存储的缓存区。
3)删除指纹
删除指纹可以选择删除个别指纹或者删除所有指纹。
删除一个或几个:调用“删除模板”指令,调用的时候需要输入要删除的起始ID号和删除个数,调用之后就会把Flash里面ID号对应位置的数据清除掉。如:起始ID号是3,删除个数是4,那么就会把3,4,5,6这四个ID号对应的指纹删掉。
删除所有:调用“清空指纹库”指令即可。
4)导出指纹模板
第一,读出模板存到缓存区。
第二,上传特征或模板。
5)导入指纹模板
第一,下载特征或模板。
第二,储存模板。
6)导出图像
第一,录入图像。
第二,上传图像。
7)导入图像
第一,下载图像。
第二,生成特征。
第三,存储模板。

3、指令讲解
所有的指令在“AS60x指纹识别SOC用户手册V10”这个文件中都有说明,我这里只给大家讲解一些常用的指令。
1) 录入图像
这个指令你只需要按照下面指令包格式用串口给AS608发送数据就可以了,建议先用电脑串口助手发,理解这个通讯的过程之后再用单片机发。注意下面的数据是十六进制表示的,所以你如果用串口助手发的话要用“hex发送”。发送成功之后模块应该会有回复,根据回复的内容可以知道指令执行的状态。
如:发送:EF 01 FF FF FF FF 01 03 01 05 回复:EF 01 FF FF FF FF 07 03 00 0A
说明图像录入成功。

2) 生成特征
这个指令的发送和接收跟上面录入图像基本一致,唯一的区别是多了一个缓存区号,缓存区有两个,是用来暂存和比较两个指纹特征的。我们可以把第一次录入的图像生成特征存在缓存区1,把第二次录入的图像生成特征存在缓存区2。

3) 精确比对两枚指纹特征
这个指令可以比对2个缓存区的指纹特征。

4) 合并特征(生成模板)
把录入的指纹特征进行合并,生成模板以便于存储,合并之后的特征分别存在缓存区1和缓存区2。

5) 储存模板
当生成一个模板的时候,我们可以把这个模板存到AS608内部的Flash里面。存储的时候要选择缓存区号和指纹ID。缓存区号1和缓存区号2分别对应你两次录入的指纹,选择其中一个保存即可。ID是模块内部Flash的存储地址,不同的ID代表存储的位置不同,同一个位置只能存一个指纹,如果录入了两个不同的指纹,但是都存到同一个ID里面,那么第二次录入的指纹就会覆盖掉第一次录入的。

6) 搜索指纹
这个指令是用来识别指纹的。调用这个指令就会将已经存在Flash里面的指纹模板和缓存区的指纹特征一一比对,如果有搜索到,会返回这个指纹的ID。要注意的是,调用的时候需要指明比对的特征是在缓存区1还是缓存区2的,你在调用这个指令之前就应该把要识别的指纹的特征存到缓存区1或缓存区2。

7) 删除模板
调用的时候需要输入要删除的起始ID号和删除个数,调用之后就会把Flash里面ID号对应位置的数据清除掉。如:起始ID号是3,删除个数是4,那么就会把3,4,5,6这四个ID号对应的指纹删掉。

四、编程讲解

我这里以stm32驱动为例,我这个程序是做一个学生考勤系统的。上位机通过串口给单片机发对应的指令,单片机执行相应的操作,用到了OLED显示屏,语音播报模块,flash芯片等外设,因此里面会有一些外设相关的程序,可以忽略,你们可以只看录入指纹、识别指纹和清空指纹那部分。
1、 底层驱动

#include <string.h>
#include "delay.h"
#include "usart2.h"
#include "as608.h"u32 AS608Addr = 0XFFFFFFFF; //默认地址//初始化PA6为下拉输入
//读摸出感应状态(触摸感应时输出高电平信号)
void PS_StaGPIO_Init(void)
{   GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA时钟//初始化读状态引脚GPIOAGPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//输入下拉模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO    GPIO_ResetBits(GPIOA,GPIO_Pin_6);       //输出低
}
//串口发送一个字节
static void MYUSART_SendData(u8 data)
{while((USART2->SR&0X40)==0); USART2->DR = data;
}
//发送包头
static void SendHead(void)
{MYUSART_SendData(0xEF);MYUSART_SendData(0x01);
}
//发送地址
static void SendAddr(void)
{MYUSART_SendData(AS608Addr>>24);MYUSART_SendData(AS608Addr>>16);MYUSART_SendData(AS608Addr>>8);MYUSART_SendData(AS608Addr);
}
//发送包标识,
static void SendFlag(u8 flag)
{MYUSART_SendData(flag);
}
//发送包长度
static void SendLength(int length)
{MYUSART_SendData(length>>8);MYUSART_SendData(length);
}
//发送指令码
static void Sendcmd(u8 cmd)
{MYUSART_SendData(cmd);
}
//发送校验和
static void SendCheck(u16 check)
{MYUSART_SendData(check>>8);MYUSART_SendData(check);
}
//判断中断接收的数组有没有应答包
//waittime为等待中断接收数据的时间(单位1ms)
//返回值:数据包首地址
static u8 *JudgeStr(u16 waittime)
{char *data;u8 str[8];str[0]=0xef;str[1]=0x01;str[2]=AS608Addr>>24;str[3]=AS608Addr>>16;str[4]=AS608Addr>>8;str[5]=AS608Addr;str[6]=0x07;str[7]='\0';USART2_RX_STA=0;while(--waittime){delay_ms(1);if(USART2_RX_STA&0X8000)//接收到一次数据{USART2_RX_STA=0;data=strstr((const char*)USART2_RX_BUF,(const char*)str);if(data)return (u8*)data;  }}return 0;
}
//录入图像 PS_GetImage
//功能:探测手指,探测到后录入指纹图像存于ImageBuffer。
//模块返回确认字
u8 PS_GetImage(void)
{u16 temp;u8  ensure;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x03);Sendcmd(0x01);temp =  0x01+0x03+0x01;SendCheck(temp);data=JudgeStr(1500);if(data)ensure=data[9];elseensure=0xff;return ensure;
}
//生成特征 PS_GenChar
//功能:将ImageBuffer中的原始图像生成指纹特征文件存于CharBuffer1或CharBuffer2
//参数:BufferID --> charBuffer1:0x01   charBuffer1:0x02
//模块返回确认字
u8 PS_GenChar(u8 BufferID)
{u16 temp;u8  ensure;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x04);Sendcmd(0x02);MYUSART_SendData(BufferID);temp = 0x01+0x04+0x02+BufferID;SendCheck(temp);data=JudgeStr(1500);if(data)ensure=data[9];elseensure=0xff;return ensure;
}
//精确比对两枚指纹特征 PS_Match
//功能:精确比对CharBuffer1 与CharBuffer2 中的特征文件
//模块返回确认字
u8 PS_Match(void)
{u16 temp;u8  ensure;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x03);Sendcmd(0x03);temp = 0x01+0x03+0x03;SendCheck(temp);data=JudgeStr(1500);if(data)ensure=data[9];elseensure=0xff;return ensure;
}
//搜索指纹 PS_Search
//功能:以CharBuffer1或CharBuffer2中的特征文件搜索整个或部分指纹库.若搜索到,则返回页码。
//参数:  BufferID @ref CharBuffer1   CharBuffer2
//说明:  模块返回确认字,页码(相配指纹模板)
u8 PS_Search(u8 BufferID,u16 StartPage,u16 PageNum,SearchResult *p)
{u16 temp;u8  ensure;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x08);Sendcmd(0x04);MYUSART_SendData(BufferID);MYUSART_SendData(StartPage>>8);MYUSART_SendData(StartPage);MYUSART_SendData(PageNum>>8);MYUSART_SendData(PageNum);temp = 0x01+0x08+0x04+BufferID+(StartPage>>8)+(u8)StartPage+(PageNum>>8)+(u8)PageNum;SendCheck(temp);data=JudgeStr(2000);if(data){ensure = data[9];p->pageID   =(data[10]<<8)+data[11];p->mathscore=(data[12]<<8)+data[13];  }elseensure = 0xff;return ensure;
}
//合并特征(生成模板)PS_RegModel
//功能:将CharBuffer1与CharBuffer2中的特征文件合并生成 模板,结果存于CharBuffer1与CharBuffer2
//说明:  模块返回确认字
u8 PS_RegModel(void)
{u16 temp;u8  ensure;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x03);Sendcmd(0x05);temp = 0x01+0x03+0x05;SendCheck(temp);data=JudgeStr(2000);if(data)ensure=data[9];elseensure=0xff;return ensure;
}
//储存模板 PS_StoreChar
//功能:将 CharBuffer1 或 CharBuffer2 中的模板文件存到 PageID 号flash数据库位置。
//参数:  BufferID @ref charBuffer1:0x01  charBuffer1:0x02
//       PageID(指纹库位置号)
//说明:  模块返回确认字
u8 PS_StoreChar(u8 BufferID,u16 PageID)
{u16 temp;u8  ensure;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x06);Sendcmd(0x06);MYUSART_SendData(BufferID);MYUSART_SendData(PageID>>8);MYUSART_SendData(PageID);temp = 0x01+0x06+0x06+BufferID+(PageID>>8)+(u8)PageID;SendCheck(temp);data=JudgeStr(2000);if(data)ensure=data[9];elseensure=0xff;return ensure;
}
//删除模板 PS_DeletChar
//功能:  删除flash数据库中指定ID号开始的N个指纹模板
//参数:  PageID(指纹库模板号),N删除的模板个数。
//说明:  模块返回确认字
u8 PS_DeletChar(u16 PageID,u16 N)
{u16 temp;u8  ensure;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x07);Sendcmd(0x0C);MYUSART_SendData(PageID>>8);MYUSART_SendData(PageID);MYUSART_SendData(N>>8);MYUSART_SendData(N);temp = 0x01+0x07+0x0C+(PageID>>8)+(u8)PageID+(N>>8)+(u8)N;SendCheck(temp);data=JudgeStr(2000);if(data)ensure=data[9];elseensure=0xff;return ensure;
}
//清空指纹库 PS_Empty
//功能:  删除flash数据库中所有指纹模板
//参数:  无
//说明:  模块返回确认字
u8 PS_Empty(void)
{u16 temp;u8  ensure;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x03);Sendcmd(0x0D);temp = 0x01+0x03+0x0D;SendCheck(temp);data=JudgeStr(2000);if(data)ensure=data[9];elseensure=0xff;return ensure;
}
//写系统寄存器 PS_WriteReg
//功能:  写模块寄存器
//参数:  寄存器序号RegNum:4\5\6
//说明:  模块返回确认字
u8 PS_WriteReg(u8 RegNum,u8 DATA)
{u16 temp;u8  ensure;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x05);Sendcmd(0x0E);MYUSART_SendData(RegNum);MYUSART_SendData(DATA);temp = RegNum+DATA+0x01+0x05+0x0E;SendCheck(temp);data=JudgeStr(2000);if(data)ensure=data[9];elseensure=0xff;if(ensure==0)printf("\r\n设置参数成功!");elseprintf("\r\n%s",EnsureMessage(ensure));return ensure;
}
//读系统基本参数 PS_ReadSysPara
//功能:  读取模块的基本参数(波特率,包大小等)
//参数:  无
//说明:  模块返回确认字 + 基本参数(16bytes)
u8 PS_ReadSysPara(SysPara *p)
{u16 temp;u8  ensure;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x03);Sendcmd(0x0F);temp = 0x01+0x03+0x0F;SendCheck(temp);data=JudgeStr(2000);if(data){ensure = data[9];p->PS_max = (data[14]<<8)+data[15];p->PS_level = data[17];p->PS_addr=(data[18]<<24)+(data[19]<<16)+(data[20]<<8)+data[21];p->PS_size = data[23];p->PS_N = data[25];}     elseensure=0xff;if(ensure==0x00){printf("\r\n模块最大指纹容量=%d",p->PS_max);printf("\r\n对比等级=%d",p->PS_level);printf("\r\n地址=%x",p->PS_addr);printf("\r\n波特率=%d",p->PS_N*9600);}else printf("\r\n%s",EnsureMessage(ensure));return ensure;
}
//设置模块地址 PS_SetAddr
//功能:  设置模块地址
//参数:  PS_addr
//说明:  模块返回确认字
u8 PS_SetAddr(u32 PS_addr)
{u16 temp;u8  ensure;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x07);Sendcmd(0x15);MYUSART_SendData(PS_addr>>24);MYUSART_SendData(PS_addr>>16);MYUSART_SendData(PS_addr>>8);MYUSART_SendData(PS_addr);temp = 0x01+0x07+0x15+(u8)(PS_addr>>24)+(u8)(PS_addr>>16)+(u8)(PS_addr>>8) +(u8)PS_addr;                SendCheck(temp);AS608Addr=PS_addr;//发送完指令,更换地址data=JudgeStr(2000);if(data)ensure=data[9];elseensure=0xff;    AS608Addr = PS_addr;if(ensure==0x00)printf("\r\n设置地址成功!");elseprintf("\r\n%s",EnsureMessage(ensure));return ensure;
}
//功能: 模块内部为用户开辟了256bytes的FLASH空间用于存用户记事本,
//  该记事本逻辑上被分成 16 个页。
//参数:  NotePageNum(0~15),Byte32(要写入内容,32个字节)
//说明:  模块返回确认字
u8 PS_WriteNotepad(u8 NotePageNum,u8 *Byte32)
{u16 temp;u8  ensure,i;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(36);Sendcmd(0x18);MYUSART_SendData(NotePageNum);for(i=0;i<32;i++){MYUSART_SendData(Byte32[i]);temp += Byte32[i];}temp =0x01+36+0x18+NotePageNum+temp;SendCheck(temp);data=JudgeStr(2000);if(data)ensure=data[9];elseensure=0xff;return ensure;
}
//读记事PS_ReadNotepad
//功能:  读取FLASH用户区的128bytes数据
//参数:  NotePageNum(0~15)
//说明:  模块返回确认字+用户信息
u8 PS_ReadNotepad(u8 NotePageNum,u8 *Byte32)
{u16 temp;u8  ensure,i;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x04);Sendcmd(0x19);MYUSART_SendData(NotePageNum);temp = 0x01+0x04+0x19+NotePageNum;SendCheck(temp);data=JudgeStr(2000);if(data){ensure=data[9];for(i=0;i<32;i++){Byte32[i]=data[10+i];}}elseensure=0xff;return ensure;
}
//高速搜索PS_HighSpeedSearch
//功能:以 CharBuffer1或CharBuffer2中的特征文件高速搜索整个或部分指纹库。
//        若搜索到,则返回页码,该指令对于的确存在于指纹库中 ,且登录时质量
//        很好的指纹,会很快给出搜索结果。
//参数:  BufferID, StartPage(起始页),PageNum(页数)
//说明:  模块返回确认字+页码(相配指纹模板)
u8 PS_HighSpeedSearch(u8 BufferID,u16 StartPage,u16 PageNum,SearchResult *p)
{u16 temp;u8  ensure;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x08);Sendcmd(0x1b);MYUSART_SendData(BufferID);MYUSART_SendData(StartPage>>8);MYUSART_SendData(StartPage);MYUSART_SendData(PageNum>>8);MYUSART_SendData(PageNum);temp = 0x01+0x08+0x1b+BufferID+(StartPage>>8)+(u8)StartPage+(PageNum>>8)+(u8)PageNum;SendCheck(temp);data=JudgeStr(2000);if(data){ensure=data[9];p->pageID  =(data[10]<<8) +data[11];p->mathscore=(data[12]<<8) +data[13];}elseensure=0xff;return ensure;
}
//读有效模板个数 PS_ValidTempleteNum
//功能:读有效模板个数
//参数: 无
//说明: 模块返回确认字+有效模板个数ValidN
u8 PS_ValidTempleteNum(u16 *ValidN)
{u16 temp;u8  ensure;u8  *data;SendHead();SendAddr();SendFlag(0x01);//命令包标识SendLength(0x03);Sendcmd(0x1d);temp = 0x01+0x03+0x1d;SendCheck(temp);data=JudgeStr(2000);if(data){ensure=data[9];*ValidN = (data[10]<<8) +data[11];}        elseensure=0xff;if(ensure==0x00){printf("\r\n有效指纹个数=%d",(data[10]<<8)+data[11]);}elseprintf("\r\n%s",EnsureMessage(ensure));return ensure;
}
//与AS608握手 PS_HandShake
//参数: PS_Addr地址指针
//说明: 模块返新地址(正确地址)
u8 PS_HandShake(u32 *PS_Addr)
{SendHead();SendAddr();MYUSART_SendData(0X01);MYUSART_SendData(0X00);MYUSART_SendData(0X00);    delay_ms(200);if(USART2_RX_STA&0X8000)//接收到数据{      if(//判断是不是模块返回的应答包              USART2_RX_BUF[0]==0XEF&&USART2_RX_BUF[1]==0X01&&USART2_RX_BUF[6]==0X07){*PS_Addr=(USART2_RX_BUF[2]<<24) + (USART2_RX_BUF[3]<<16)+(USART2_RX_BUF[4]<<8) + (USART2_RX_BUF[5]);USART2_RX_STA=0;return 0;}USART2_RX_STA=0;                    }return 1;
}
//模块应答包确认码信息解析
//功能:解析确认码错误信息返回信息
//参数: ensure
const char *EnsureMessage(u8 ensure)
{const char *p;switch(ensure){case  0x00:p="OK";break;       case  0x01:p="数据包接收错误";break;case  0x02:p="传感器上没有手指";break;case  0x03:p="录入指纹图像失败";break;case  0x04:p="指纹图像太干、太淡而生不成特征";break;case  0x05:p="指纹图像太湿、太糊而生不成特征";break;case  0x06:p="指纹图像太乱而生不成特征";break;case  0x07:p="指纹图像正常,但特征点太少(或面积太小)而生不成特征";break;case  0x08:p="指纹不匹配";break;case  0x09:p="没搜索到指纹";break;case  0x0a:p="特征合并失败";break;case  0x0b:p="访问指纹库时地址序号超出指纹库范围";case  0x10:p="删除模板失败";break;case  0x11:p="清空指纹库失败";break;  case  0x15:p="缓冲区内没有有效原始图而生不成图像";break;case  0x18:p="读写 FLASH 出错";break;case  0x19:p="未定义错误";break;case  0x1a:p="无效寄存器号";break;case  0x1b:p="寄存器设定内容错误";break;case  0x1c:p="记事本页码指定错误";break;case  0x1f:p="指纹库满";break;case  0x20:p="地址错误";break;default :p="模块返回确认码有误";break;}return p;
}

2、录指纹函数

//录入指纹
u16 Add_FR(u16 ID)
{u8 i=0,ensure,processnum=0;int a=1;Audio(2);  //播放"开始录入指纹"delay_ms(1000);OLED_Clear();OLED_ShowCHinese(28,0,14);OLED_ShowCHinese(48,0,15);OLED_ShowCHinese(68,0,16);OLED_ShowCHinese(88,0,17);  //显示"录入指纹"  while(a){   switch (processnum){    case 0:i++;Audio(3);          OLED_ShowCHinese(28,2,18);OLED_ShowCHinese(48,2,25);OLED_ShowCHinese(68,2,26);OLED_ShowCHinese(88,2,27);  //显示"请按手指"delay_ms(50);if(PS_Sta==1){ensure=PS_GetImage();  //录入图像if(ensure==0x00) {   ensure=PS_GenChar(CharBuffer1);  //生成特征if(ensure==0x00){ Audio(4);  //播报"开始录入指纹"OLED_ShowCHinese(28,2,16);OLED_ShowCHinese(48,2,17);OLED_ShowCHinese(68,2,28);OLED_ShowCHinese(88,2,29);  //显示"指纹正确"delay_ms(1000);              i=0;processnum=1;  //跳到第二步                        }else {OLED_ShowCHinese(28,2,16);OLED_ShowCHinese(48,2,17);OLED_ShowCHinese(68,2,8);OLED_ShowCHinese(88,2,9);  //显示"指纹错误"                     }}      }                                       break;      case 1:i++;Audio(5);  //播报"请再按一次手指" OLED_ShowCHinese(8,2,30);OLED_ShowCHinese(28,2,25);OLED_ShowCHinese(48,2,31);OLED_ShowCHinese(68,2,32);OLED_ShowCHinese(88,2,26);OLED_ShowCHinese(108,2,27);  //显示"再按一次手指"if(PS_Sta==1){ensure=PS_GetImage();  //录入图像if(ensure==0x00) {      ensure=PS_GenChar(CharBuffer2);  //生成特征            if(ensure==0x00){Audio(4);                            OLED_ShowString(8,2,"                ",16);OLED_ShowCHinese(28,2,16);OLED_ShowCHinese(48,2,17);OLED_ShowCHinese(68,2,28);OLED_ShowCHinese(88,2,29);  //显示"指纹正确"                      i=0;processnum=2;  //跳到第三步}else {OLED_ShowCHinese(28,2,16);OLED_ShowCHinese(48,2,17);OLED_ShowCHinese(68,2,8);OLED_ShowCHinese(88,2,9);  //显示"指纹错误"        }}          }                       break;case 2:i++;           ensure=PS_Match();  //对比两次指纹if(ensure==0x00)  //两次指纹一致{                 processnum=3;  //跳到第四步 }else  //两次指纹不一致{ Audio(19);  //播报"两次指纹不一样,请重新录入"                     delay_ms(50);OLED_ShowCHinese(8,2,33);OLED_ShowCHinese(28,2,32);OLED_ShowCHinese(48,2,16);OLED_ShowCHinese(68,2,17);OLED_ShowCHinese(88,2,34);OLED_ShowCHinese(108,2,35);   //显示"两次指纹不同"OLED_ShowCHinese(8,4,18);OLED_ShowCHinese(28,4,36);OLED_ShowCHinese(48,4,37);OLED_ShowCHinese(68,4,14);OLED_ShowCHinese(88,4,15);  //"请重新录入"delay_ms(1500);OLED_ShowString(8,2,"                 ",16);OLED_ShowString(8,4,"                 ",16);i=0;processnum=0;  //跳回第一步     }break;case 3:  ensure=PS_RegModel();  //产生一个指纹模板if(ensure==0x00)  //生成指纹模板成功 {                                      processnum=4;  //跳到第五步}else {processnum=0;}break; case 4: i++;ensure=PS_StoreChar(CharBuffer2,ID);  //储存模板if(ensure==0x00) { Audio(6);   MYUSART_SendData1(0x3A);MYUSART_SendData1(0x01);MYUSART_SendData1(0x00);MYUSART_SendData1(0x01);MYUSART_SendData1(0x01);MYUSART_SendData1(0x00);MYUSART_SendData1(0x04);MYUSART_SendData1(0x3A);                    OLED_ShowString(8,2,"                 ",16);OLED_ShowCHinese(28,2,14);OLED_ShowCHinese(48,2,15);OLED_ShowCHinese(68,2,6);OLED_ShowCHinese(88,2,7);  //显示"录入成功"          ZW_ID[0]=ID;SPI_Flash_Write((u8*)ZW_ID,FLASH_SIZE-100,1);  //写入当前ID            a=0;break;}else {processnum=0;}   break;                          }delay_ms(1000);        if(i>5) {        i=0;a=0;Audio(7);  //播报"录入失败"MYUSART_SendData1(0x3A);MYUSART_SendData1(0x01);MYUSART_SendData1(0x00);MYUSART_SendData1(0x01);MYUSART_SendData1(0x00);MYUSART_SendData1(0x00);MYUSART_SendData1(0x04);MYUSART_SendData1(0x3A);OLED_ShowCHinese(28,2,14);OLED_ShowCHinese(48,2,15);OLED_ShowCHinese(68,2,4);OLED_ShowCHinese(88,2,5);  //显示"录入失败"delay_ms(1000);OLED_ShowString(28,2,"                ",16);} }
}

3、刷指纹

void press_FR(void)
{   SearchResult seach;u8 ensure;if(audio_flag){audio_flag=0;Audio(11);//播报“开始签到,请按手指”}OLED_ShowString(0,0,"   ",16);OLED_ShowString(104,0,"    ",16);OLED_ShowString(0,2,"                   ",16);OLED_ShowString(0,4,"                   ",16);OLED_ShowString(0,6,"                   ",16);OLED_ShowCHinese(28,0,10);OLED_ShowCHinese(48,0,11);OLED_ShowCHinese(68,0,12);OLED_ShowCHinese(88,0,13);  //显示"开始签到"
//  printf("开始签到\n");if(PS_Sta==1){ensure=PS_GetImage();if(ensure==0x00)//获取图像{OLED_ShowCHinese(28,2,69);OLED_ShowCHinese(48,2,70);OLED_ShowCHinese(68,2,71);OLED_ShowString(88,2,"...",16);    //显示"比对中..."
//          printf("获取图像成功 \n");ensure=PS_GenChar(CharBuffer1);if(ensure==0x00) //生成特征{
//              printf("生成特征成功 \n");ensure=PS_HighSpeedSearch(CharBuffer1,0,300,&seach);if(ensure==0x00)//搜索成功{
//                  printf("搜索指纹成功\n ");//搜索指纹成功
//                  delay_ms(100);
//                  sprintf(str,"Match ID:%d  Match score:%d\n",seach.pageID,seach.mathscore);//显示匹配指纹的ID和分数
//                  printf(" 匹配指纹的ID和分数  %s\n",str);
//                  printf("%d",seach.pageID);
//                  OLED_ShowNum(0,6,seach.pageID,6,16);Up_stu_num(seach.pageID);ID=seach.pageID;OLED_ShowCHinese(28,4,12);OLED_ShowCHinese(48,4,13);OLED_ShowCHinese(68,4,6);OLED_ShowCHinese(88,4,7);  //显示"签到成功"  Audio(12);//播报“签到成功”                    delay_ms(1000);}else{Audio(13);OLED_ShowCHinese(28,4,12);OLED_ShowCHinese(48,4,13);OLED_ShowCHinese(68,4,4);OLED_ShowCHinese(88,4,5);  //显示"签到失败" delay_ms(1000);
//                  ShowErrMessage(ensure); }
//      delay_ms(50);           }
//          else
//              ShowErrMessage(ensure);
//              delay_ms(50);}}
}

4、清空指纹
这个函数在底层驱动里面有,直接调用即可

PS_Empty();

5、上传和下载指纹
如果没有用到这个功能可以跳过

u16 Up_FR(u16 ID)  //上传指纹
{u8 ensure; Audio(15);OLED_Clear();OLED_ShowCHinese(28,0,60);OLED_ShowCHinese(48,0,61);OLED_ShowCHinese(68,0,16);OLED_ShowCHinese(88,0,17);  //显示"上传指纹"ensure=PS_LoadChar(CharBuffer2,ID);  //读出模板if(ensure==0x00){PS_UpChar(CharBuffer2);  //上传特征     if(ensure==0x00){//         printf("上传指纹成功");Audio(16);OLED_ShowCHinese(8,2,60);OLED_ShowCHinese(28,2,61);OLED_ShowCHinese(48,2,16);OLED_ShowCHinese(68,2,17);  OLED_ShowCHinese(88,2,6);  OLED_ShowCHinese(108,2,7);  //显示"上传指纹成功"}else{Audio(17);OLED_ShowCHinese(8,2,60);OLED_ShowCHinese(28,2,61);OLED_ShowCHinese(48,2,16);OLED_ShowCHinese(68,2,17);  OLED_ShowCHinese(88,2,4);  OLED_ShowCHinese(108,2,5);  //显示"上传指纹失败"delay_ms(1000);}}else{   OLED_ShowCHinese(8,2,60);OLED_ShowCHinese(28,2,61);OLED_ShowCHinese(48,2,16);OLED_ShowCHinese(68,2,17);  OLED_ShowCHinese(88,2,6);  OLED_ShowCHinese(108,2,7);  //显示"上传指纹失败"delay_ms(1000);}
}u16 Down_FR(u16 ID)  //下载指纹
{u8 ensure;u16 i;Audio(8);OLED_Clear();OLED_ShowCHinese(28,0,58);OLED_ShowCHinese(48,0,59);OLED_ShowCHinese(68,0,16);OLED_ShowCHinese(88,0,17);  //显示"下载指纹"ensure=PS_DownChar(CharBuffer2);if(ensure==0x00) {  for(i=4;i<838;i++){while((USART2->SR&0X40)==0);          USART2->DR = USART_RX_BUF[i];       }ensure=PS_StoreChar(CharBuffer2,ID);if(ensure==0x00) {  MYUSART_SendData1(0x3A);MYUSART_SendData1(0x03);MYUSART_SendData1(0x00);MYUSART_SendData1(0x01);MYUSART_SendData1(0x01);MYUSART_SendData1(0x00);MYUSART_SendData1(0x03);MYUSART_SendData1(0x3A);
//          printf("下载指纹成功");ZW_ID[0]=ID;SPI_Flash_Write((u8*)ZW_ID,FLASH_SIZE-100,1);       //写入当前IDOLED_ShowCHinese(8,2,58);OLED_ShowCHinese(28,2,59);OLED_ShowCHinese(48,2,16);OLED_ShowCHinese(68,2,17);  OLED_ShowCHinese(88,2,6);  OLED_ShowCHinese(108,2,7);  //显示"下载指纹成功"delay_ms(1000);show_main_page();}else{Audio(10);OLED_ShowCHinese(8,2,58);OLED_ShowCHinese(28,2,59);OLED_ShowCHinese(48,2,16);OLED_ShowCHinese(68,2,17);  OLED_ShowCHinese(88,2,4);  OLED_ShowCHinese(108,2,5);  //显示"下载指纹失败"}}
}

6、main函数
我这份程序是做一个学生签到系统,上位机通过串口给单片机发送指令,单片机执行相应的操作

int main(void)
{       u16 t=0;delay_init();Audio_Init();//语音模块初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2TIM4_Int_Init(9999,7199);//10Khz的计数频率,1s定时中断uart_init(115200);  //初始化串口1波特率为115200,用于与上位机通讯usart2_init(57600);//初始化串口2,用于与指纹模块通讯PS_StaGPIO_Init();   //初始化FR读状态引脚OLED_Init(); //OLED初始化OLED_Clear();//OLED清屏SPI_Flash_Init(); //外接FLASH芯片W25Q64初始化,用来存学生学号(指纹是存到AS608芯片里面的)     LED_Init();while(SPI_Flash_ReadID()!=W25Q64)  //检测W25Q64{delay_ms(100);LED0=!LED0;  //DS0闪烁}while(PS_HandShake(&AS608Addr))  //与AS608模块握手{ OLED_ShowCHinese(8,0,0);OLED_ShowCHinese(28,0,1);OLED_ShowCHinese(48,0,2); OLED_ShowCHinese(68,0,3);           OLED_ShowString(88,0,"...",16);    //显示"正在连接..."}OLED_ShowCHinese(8,0,2);OLED_ShowCHinese(28,0,3);OLED_ShowCHinese(48,0,6); OLED_ShowCHinese(68,0,7);OLED_ShowString(88,0,"   ",16);      //显示"连接成功"
//  printf("\n连接成功\n");OLED_Clear();show_main_page();//OLED显示主界面      while(1){command_rx();//等待串口接收指令(我这里是用上位机给单片机串口发指令的)delay_ms(100);if(command==0x01)  //收到录入指纹命令{command=0;         SPI_Flash_Write((u8*)TEXT_Buffer,FLASH_SIZE-100,1);//从倒数第100个地址处开始,写入SIZE长度的数据SPI_Flash_Read(ZW_ID,FLASH_SIZE-100,1);               //读取当前已存的最大指纹ID号ID=ZW_ID[0]+1;    Add_FR(ID);     //录指纹   show_main_page();       //显示首页界面}else if(command==0x02)  //上传指纹{  command=0;SPI_Flash_Read(ZW_ID,FLASH_SIZE-100,1);              //读取当前已存的最大指纹ID号ID=ZW_ID[0];
//          MYUSART_SendData1(0x3A);
//          MYUSART_SendData1(0x02);
//          MYUSART_SendData1(0x03);
//          MYUSART_SendData1(0x42);Up_FR(ID);  //获取指纹信息for(t=0;t<841;t++){while((USART1->SR&0X40)==0);USART1->DR = zw_up[t];  //向上位机上传指纹信息}
//          MYUSART_SendData1(0x03);
//          MYUSART_SendData1(0x45);
//          MYUSART_SendData1(0x3A);show_main_page();  }    else if(command==0x03)  //下载指纹{   command=0;SPI_Flash_Read(ZW_ID,FLASH_SIZE-100,1);  //读取当前已存的最大指纹ID号ID=ZW_ID[0]+1;Down_FR(ID);  //下载指纹show_main_page();  }else if(command==0x04)  //上传学号/开始签到{press_FR();  }        else if(command==0x05)  //下载学号{   command=0;Down_stu_num(ID);  show_main_page();}else if(command==0x06) //结束签到{    command=0;Audio(14);OLED_Clear();     OLED_ShowCHinese(28,0,12);OLED_ShowCHinese(48,0,13);  OLED_ShowCHinese(68,0,62);OLED_ShowCHinese(88,0,63);//显示"结束签到"   delay_ms(1500);show_main_page();}else if(command==0x07) //清空数据{   command=0;PS_Empty();ZW_ID[0]=0;SPI_Flash_Write((u8*)ZW_ID,FLASH_SIZE-100,1);     //写入当前ID    OLED_Clear();MYUSART_SendData1(0x3A);MYUSART_SendData1(0x07);MYUSART_SendData1(0x00);MYUSART_SendData1(0x01);MYUSART_SendData1(0x00);MYUSART_SendData1(0x04);MYUSART_SendData1(0x3A);OLED_ShowCHinese(12,4,64);OLED_ShowCHinese(30,4,65);OLED_ShowCHinese(48,4,66);OLED_ShowCHinese(66,4,67);OLED_ShowCHinese(84,4,68);//"已清空数据"      Audio(18);  //播放"播放已清空数据"     delay_ms(1500);show_main_page();}       }
}

好了,关于这个光学指纹识别模块就讲到这里,程序是以前写的,现在回看,诸多地方都不满意,也没时间一一去改了,如果你们觉得写的不好,勿怪,如果大家还有什么问题可以留言给我。

源码下载链接1:https://pan.baidu.com/s/1A2fbiTy10-2pZUxAaQdJnw ,提取码:8kdp
源码下载链接2:https://pan.baidu.com/s/1aOKyCLwdMrvzPlpIq5tMtA,提取码:abcd

如果觉得博主写的文章有用,那就点赞+关注支持一下吧,创作不易,加班狗用业余时间写博客,不容易呐,所以请尊重每一位博主的劳动,后续也会继续介绍一些适合大学生使用的模块,谢谢大家!!!**

AS608光学指纹模组编程和应用详解相关推荐

  1. 光学指纹模组解锁方案设计指纹锁方案

    指纹柜锁方案,是一种针对物流柜.保险箱.储物箱开发出来的指纹柜锁方案.此方案配合各类箱柜能够操控其解锁方式,以智能化的形式,最大程度的保障物品的安全,相比传统的物理锁具,更加方便,解锁更加快捷. 指纹 ...

  2. 【雕爷学编程】Arduino动手做(141)---AS608光学指纹识别模块

    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的.鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为 ...

  3. AS608光学指纹识别模块 智能锁/考勤门禁开发/指纹采集模块

    一.注册指纹 /*[Arduino]168种传感器模块系列实验(资料+代码+图形+仿真)实验一百五十:AS608光学指纹识别模块 智能锁/考勤门禁开发/指纹采集模块实验之二:输入序号,注册指纹示例安装 ...

  4. 51驱动AS608光学指纹识别模块 12864显示

    51驱动AS608光学指纹识别模块 12864显示 AS608光学指纹识别模块 模块工作原理 1.指纹特征 2.指纹处理 模块参数 引脚说明 实验程序 硬件设备和接线 程序讲解 按键 主函数 实验步骤 ...

  5. K_A12_007 基于STM32等单片机驱动AS608光学指纹识别模块 OLED0.96显示

    K_A12_007 基于STM32等单片机驱动AS608光学指纹识别模块 OLED0.96显示 一.资源说明 二.基本参数 参数 引脚说明 三.驱动说明 对应程序: 四.部分代码说明 1.接线引脚定义 ...

  6. 指纹传感器的测试软件,【Arduino】168种传感器系列实验(149)-AS608光学指纹识别模块-Arduino中文社区 - Powered by Discuz!...

    [mw_shl_code=arduino,true]/* [Arduino]168种传感器模块系列实验(资料+代码+图形+仿真) 实验一百五十:AS608光学指纹识别模块+0.91寸OLED液晶屏显示 ...

  7. 【蓝桥杯Python组】2022年第十三届蓝桥杯省赛B组Python解题思路详解

    第十三届蓝桥杯省赛B组Python解题思路详解 因为今年采用线上的举办方式进行比赛,所以组委会对题目做了一定的调整,将原来的5道填空+5道编程题变成了2道填空+8道编程题,据说是为了防止抄袭.其实题目 ...

  8. 跟着东木学:UG_NX数控编程培训教程详解

    UG_NX数控编程培训教程详解 主讲:耳木东木 博客地址:http://www.cnblogs.com/ermudongmu/ 菜单栏和工具栏 加工菜单栏选项 加工工具栏图标 过滤选项 创建过滤方法图 ...

  9. 基于 UDP 的 组播、广播详解

    背景 有些时候我们在网络通信中也需要用到 组播(多播).广播.现在我们来介绍如何实现. 建议:在此之前,关闭防火墙. ubuntu: service ufw stop windows: 控制面板关闭 ...

最新文章

  1. android+3e错误,Android 错误
  2. Windows下的鱿鱼(Squid)
  3. php-fpm with php-5.3.2 + APC
  4. android获取子线程id,Android 开发 知晓各种id信息 获取线程ID、activityID、内核ID
  5. 22 WM配置-策略-入库策略2-定义未清存储策略C(Open Strategy)
  6. Go 语言 bytes.Buffer 源码详解之1
  7. linux的基本使用方法,Linux/Unix基本使用方法
  8. 2025年全球5G设备将达到14亿部 但4G仍占主导地位
  9. 中英文对照 —— 手机 App/PC 端软件(系统)、互联网
  10. Cordova WP8 插件开发
  11. Docker学习之数据管理
  12. win 10 linux shell,实用工具:Win10下的bash shell打开教程
  13. 软考计算机网络初级试题答案,2015年下半年中级软考《计算机网络—网络工程师》试题及答案...
  14. 生产排程系统_APS(高级计划排产)系统该如何选型,主要从哪些方面考虑?
  15. 图文安装VMware Workstation教程
  16. 三刺激值计算公式_三刺激值及对应的xyU'V'
  17. excel宏设置之一键生成多张sheet并写入内容与格式
  18. 对接微信公众号出现【invalid ip xxx.xxx.xxx.xxx 】
  19. 【神经网络第三期】RBF神经网络基本原理和模型应用
  20. Visual Studio2010随云而动 特性大揭秘

热门文章

  1. 增长黑客AB-Test系统(三)——AB-Test Hash分流
  2. 汽车美容店管理系统如何管理店铺数据?
  3. 全面领先!小i机器人再获2018年度最佳智能解决方案奖
  4. 新一代的 Python 包管理工具 -- PDM
  5. win10电脑中病毒了怎么办,win10电脑中毒怎么解决
  6. 天蓝色在ps中的色值_用天蓝色构建混合云
  7. 第二章.Java程序设计基础
  8. eslint报错解决方案:--fix的使用
  9. AR502H-CN开发笔记01:硬件接口
  10. chrome谷歌浏览器调试微信H5页面