成人免费无码不卡毛片,亚洲AⅤ无码精品一区二区三区,国产尤物精品视频,久久精品日本亚洲,欧美成人一区三区无码乱码A片,中文字日产幕码一区二区色哟哟,亞洲日韓中文字幕網AV

  • 正文
    • 一、前言
    • 二、芯片介紹
    • 三、通訊原理和通訊的流程講解
    • 四、編程講解
  • 推薦器件
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

AS608光學(xué)指紋模組編程和應(yīng)用詳解

2024/07/12
5878
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

一、前言

上次講解了兩個(gè)簡(jiǎn)單實(shí)用的傳感器,反饋很多,能夠幫助到大家,我也很開(kāi)心。所以今天繼續(xù)給大家介紹一個(gè)實(shí)用易上手的傳感器,在這里有些同學(xué)可能就會(huì)質(zhì)疑了,指紋識(shí)別哪里簡(jiǎn)單了?別急,容我細(xì)細(xì)道來(lái),看完整篇文章,你可能就會(huì)覺(jué)得,不過(guò)如此嘛。

需要程序源碼,原理圖,數(shù)據(jù)手冊(cè)等資料可以到文章底部的鏈接自行下載。因?yàn)檫@個(gè)是我大學(xué)做畢設(shè)時(shí)用到的一個(gè)模塊,內(nèi)容比較多,有些細(xì)節(jié)一時(shí)記不清了,所以有些地方可能講的不是特別深入,如果你們有什么地方看不懂,可以留言和私信給我,我再給你們解答。

如果能夠幫助到你,請(qǐng)點(diǎn)贊+關(guān)注,又快到做畢設(shè)的日子了,我后面也會(huì)繼續(xù)寫更多的博文,希望能夠幫到你們。

二、芯片介紹

1、芯片簡(jiǎn)介

AS608是一個(gè)集成的光學(xué)指紋芯片,內(nèi)部有指紋算法,其實(shí)指紋識(shí)別最難的地方在于算法,目前的算法是前人不斷開(kāi)發(fā)完善得到的,所以在前幾年,算法都是某些大企業(yè)獨(dú)有的技術(shù),他們只賣芯片不賣算法。當(dāng)然現(xiàn)在的話,光學(xué)指紋的算法也逐漸放出來(lái)了,因?yàn)楝F(xiàn)在用的更多的是半導(dǎo)體,超聲波指紋識(shí)別,光學(xué)指紋他們已經(jīng)玩膩了。

說(shuō)遠(yuǎn)了,回歸正題,雖然AS608內(nèi)部的算法我們是看不到的,但是它預(yù)留了一個(gè)串口和相關(guān)的串口指令集,我們可以用這些指令調(diào)用指紋算法,從而實(shí)現(xiàn)我們需要的功能。

2、引腳定義

在這里插入圖片描述

三、通訊原理和通訊的流程講解

1、通訊方法

通過(guò)給AS608串口發(fā)送特定的指令,就可以調(diào)用里面的算法,進(jìn)行相應(yīng)的操作。這些指令有三種格式:命令包格式,數(shù)據(jù)包格式和接收包格式。命令包是用來(lái)控制AS608的,數(shù)據(jù)包和結(jié)束包只在導(dǎo)出(把模塊里面的指紋導(dǎo)出到別的設(shè)備)和導(dǎo)入(把其他設(shè)備的數(shù)據(jù)導(dǎo)入模塊)指紋數(shù)據(jù)的時(shí)候用到的。

在這里插入圖片描述

我這里以命令包格式為例,給大家講解一下,包頭是2個(gè)字節(jié)的數(shù)據(jù),固定為0xEF01;芯片地址4個(gè)字節(jié),默認(rèn)是0xFFFFFFFF,可以后面發(fā)送指令修改;包識(shí)別是用來(lái)區(qū)分指令的類型的,如命令包固定為0x01;包長(zhǎng)度是指這一條指令有多少個(gè)重要的數(shù)據(jù),包長(zhǎng)度=包長(zhǎng)度至校驗(yàn)和(指令、參數(shù)或數(shù)據(jù))的總字節(jié)數(shù),包含校驗(yàn)和,但不包含包長(zhǎng)度本身的字節(jié)數(shù);指令就是需要AS608執(zhí)行的操作,具體的定義我后面再說(shuō);參數(shù)和具體的指令有關(guān),不同的指令,參數(shù)的長(zhǎng)度和數(shù)值都有所不同;校驗(yàn)和是為了確保串口通訊過(guò)程中出現(xiàn)錯(cuò)誤,導(dǎo)致命令出錯(cuò),校驗(yàn)和是從包標(biāo)識(shí)至校驗(yàn)和之間所有字節(jié)之和。

2、功能的實(shí)現(xiàn)及通訊的流程

我這里只詳細(xì)講解錄入指紋、識(shí)別指紋和刪除指紋這三個(gè)最常用的功能的實(shí)現(xiàn)和操作步驟。如果你們需要用到導(dǎo)出和導(dǎo)入指紋,可以留言或私信給我,我再詳細(xì)講解。

1)錄入指紋

錄入指紋有以下幾個(gè)步驟:

第一,錄入圖像。當(dāng)你的手指放在光學(xué)指紋窗口的時(shí)候執(zhí)行這個(gè)指令,就可以把指紋的圖像拍下來(lái)。

第二,生成特征。當(dāng)你的指紋圖像拍下來(lái)之后,調(diào)用這個(gè)指令就可以把圖像中的指紋特征記錄下來(lái)。AS608里面有2個(gè)緩存區(qū)可以存這個(gè)特征,我們這里先用第1個(gè)存。

第三,再次錄入圖像。把同一個(gè)手指放在光學(xué)指紋窗口,然后執(zhí)行這個(gè)指令,再拍一個(gè)指紋圖像。

第四,再次生成特征。把第二次錄入的圖像的指紋特征存到第2個(gè)緩存區(qū)。

第五.精確比對(duì)兩枚指紋特征。錄入指紋的時(shí)候?yàn)榱嗽黾訙?zhǔn)確性,最好是記錄多次指紋特征,這個(gè)指令就是對(duì)錄入的兩個(gè)指紋特征進(jìn)行比對(duì),如果一致就說(shuō)明是同一個(gè)人的同一個(gè)指紋。

第六,合并特征(生成模板)。當(dāng)錄入了兩個(gè)指紋特征,并且兩個(gè)特征是一致的時(shí)候,就可以把兩個(gè)特征合并成一個(gè)指紋模板。這個(gè)指紋模板就是我們最終要錄入的指紋。

第七,儲(chǔ)存模板。當(dāng)生成一個(gè)模板的時(shí)候,我們可以把這個(gè)模板存到AS608內(nèi)部的Flash里面,存儲(chǔ)的時(shí)候需要輸入一個(gè)指紋ID號(hào),這個(gè)ID其實(shí)是Flash的地址,不同的ID號(hào),存儲(chǔ)的位置不同,最多好像能存兩三百個(gè)指紋。

2)識(shí)別指紋

第一,錄入圖像。這一步和錄入指紋的第一步是一樣的,目的是把指紋的圖像拍下來(lái)。

第二,生成特征。這一步和錄入指紋的第二步是一樣的。指紋特征可以存到第一個(gè)緩存區(qū)也可以存到第二個(gè)緩存區(qū)。

第三,搜索指紋。調(diào)用這個(gè)指令就會(huì)將已經(jīng)存在Flash里面的指紋模板和緩存區(qū)的指紋特征一一比對(duì),如果有搜索到,會(huì)返回這個(gè)指紋的ID。要注意的是,調(diào)用的時(shí)候需要指明比對(duì)的特征是緩存區(qū)1還是緩存區(qū)2,你要選擇第二步生成的特征所存儲(chǔ)的緩存區(qū)。

3)刪除指紋

刪除指紋可以選擇刪除個(gè)別指紋或者刪除所有指紋。

刪除一個(gè)或幾個(gè):調(diào)用“刪除模板”指令,調(diào)用的時(shí)候需要輸入要?jiǎng)h除的起始ID號(hào)和刪除個(gè)數(shù),調(diào)用之后就會(huì)把Flash里面ID號(hào)對(duì)應(yīng)位置的數(shù)據(jù)清除掉。如:起始ID號(hào)是3,刪除個(gè)數(shù)是4,那么就會(huì)把3,4,5,6這四個(gè)ID號(hào)對(duì)應(yīng)的指紋刪掉。

刪除所有:調(diào)用“清空指紋庫(kù)”指令即可。

4)導(dǎo)出指紋模板

第一,讀出模板存到緩存區(qū)。

第二,上傳特征或模板。

5)導(dǎo)入指紋模板

第一,下載特征或模板。

第二,儲(chǔ)存模板。

6)導(dǎo)出圖像

第一,錄入圖像。
第二,上傳圖像。

7)導(dǎo)入圖像

第一,下載圖像。
第二,生成特征。
第三,存儲(chǔ)模板。

3、指令講解

所有的指令在“AS60x指紋識(shí)別SOC用戶手冊(cè)V10”這個(gè)文件中都有說(shuō)明,我這里只給大家講解一些常用的指令。

1) 錄入圖像

這個(gè)指令你只需要按照下面指令包格式用串口給AS608發(fā)送數(shù)據(jù)就可以了,建議先用電腦串口助手發(fā),理解這個(gè)通訊的過(guò)程之后再用單片機(jī)發(fā)。注意下面的數(shù)據(jù)是十六進(jìn)制表示的,所以你如果用串口助手發(fā)的話要用“hex發(fā)送”。發(fā)送成功之后模塊應(yīng)該會(huì)有回復(fù),根據(jù)回復(fù)的內(nèi)容可以知道指令執(zhí)行的狀態(tài)。

如:發(fā)送:EF 01 FF FF FF FF 01 00 03 01 00 05 回復(fù):EF 01 FF FF FF FF 07 00 03 00 00 0A

說(shuō)明圖像錄入成功。

在這里插入圖片描述

2) 生成特征

這個(gè)指令的發(fā)送和接收跟上面錄入圖像基本一致,唯一的區(qū)別是多了一個(gè)緩存區(qū)號(hào),緩存區(qū)有兩個(gè),是用來(lái)暫存和比較兩個(gè)指紋特征的。我們可以把第一次錄入的圖像生成特征存在緩存區(qū)1,把第二次錄入的圖像生成特征存在緩存區(qū)2。

在這里插入圖片描述

3) 精確比對(duì)兩枚指紋特征

這個(gè)指令可以比對(duì)2個(gè)緩存區(qū)的指紋特征。

在這里插入圖片描述

4) 合并特征(生成模板)

把錄入的指紋特征進(jìn)行合并,生成模板以便于存儲(chǔ),合并之后的特征分別存在緩存區(qū)1和緩存區(qū)2。

在這里插入圖片描述

5) 儲(chǔ)存模板

當(dāng)生成一個(gè)模板的時(shí)候,我們可以把這個(gè)模板存到AS608內(nèi)部的Flash里面。存儲(chǔ)的時(shí)候要選擇緩存區(qū)號(hào)和指紋ID。緩存區(qū)號(hào)1和緩存區(qū)號(hào)2分別對(duì)應(yīng)你兩次錄入的指紋,選擇其中一個(gè)保存即可。ID是模塊內(nèi)部Flash的存儲(chǔ)地址,不同的ID代表存儲(chǔ)的位置不同,同一個(gè)位置只能存一個(gè)指紋,如果錄入了兩個(gè)不同的指紋,但是都存到同一個(gè)ID里面,那么第二次錄入的指紋就會(huì)覆蓋掉第一次錄入的。

在這里插入圖片描述

6) 搜索指紋

這個(gè)指令是用來(lái)識(shí)別指紋的。調(diào)用這個(gè)指令就會(huì)將已經(jīng)存在Flash里面的指紋模板和緩存區(qū)的指紋特征一一比對(duì),如果有搜索到,會(huì)返回這個(gè)指紋的ID。要注意的是,調(diào)用的時(shí)候需要指明比對(duì)的特征是在緩存區(qū)1還是緩存區(qū)2的,你在調(diào)用這個(gè)指令之前就應(yīng)該把要識(shí)別的指紋的特征存到緩存區(qū)1或緩存區(qū)2。

在這里插入圖片描述

7) 刪除模板

調(diào)用的時(shí)候需要輸入要?jiǎng)h除的起始ID號(hào)和刪除個(gè)數(shù),調(diào)用之后就會(huì)把Flash里面ID號(hào)對(duì)應(yīng)位置的數(shù)據(jù)清除掉。如:起始ID號(hào)是3,刪除個(gè)數(shù)是4,那么就會(huì)把3,4,5,6這四個(gè)ID號(hào)對(duì)應(yīng)的指紋刪掉。

在這里插入圖片描述

四、編程講解

我這里以stm32驅(qū)動(dòng)為例,我這個(gè)程序是做一個(gè)學(xué)生考勤系統(tǒng)的。上位機(jī)通過(guò)串口給單片機(jī)發(fā)對(duì)應(yīng)的指令,單片機(jī)執(zhí)行相應(yīng)的操作,用到了OLED顯示屏,語(yǔ)音播報(bào)模塊,flash芯片等外設(shè),因此里面會(huì)有一些外設(shè)相關(guān)的程序,可以忽略,你們可以只看錄入指紋、識(shí)別指紋和清空指紋那部分。

1、 底層驅(qū)動(dòng)

#include <string.h>
#include "delay.h" 	
#include "usart2.h"
#include "as608.h"

u32 AS608Addr = 0XFFFFFFFF; //默認(rèn)地址

//初始化PA6為下拉輸入		    
//讀摸出感應(yīng)狀態(tài)(觸摸感應(yīng)時(shí)輸出高電平信號(hào))
void PS_StaGPIO_Init(void)
{   
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA時(shí)鐘
	//初始化讀狀態(tài)引腳GPIOA
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//輸入下拉模式
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO	
	GPIO_ResetBits(GPIOA,GPIO_Pin_6);		//輸出低
}
//串口發(fā)送一個(gè)字節(jié)
static void MYUSART_SendData(u8 data)
{
	while((USART2->SR&0X40)==0); 
	USART2->DR = data;
}
//發(fā)送包頭
static void SendHead(void)
{
	MYUSART_SendData(0xEF);
	MYUSART_SendData(0x01);
}
//發(fā)送地址
static void SendAddr(void)
{
	MYUSART_SendData(AS608Addr>>24);
	MYUSART_SendData(AS608Addr>>16);
	MYUSART_SendData(AS608Addr>>8);
	MYUSART_SendData(AS608Addr);
}
//發(fā)送包標(biāo)識(shí),
static void SendFlag(u8 flag)
{
	MYUSART_SendData(flag);
}
//發(fā)送包長(zhǎng)度
static void SendLength(int length)
{
	MYUSART_SendData(length>>8);
	MYUSART_SendData(length);
}
//發(fā)送指令碼
static void Sendcmd(u8 cmd)
{
	MYUSART_SendData(cmd);
}
//發(fā)送校驗(yàn)和
static void SendCheck(u16 check)
{
	MYUSART_SendData(check>>8);
	MYUSART_SendData(check);
}
//判斷中斷接收的數(shù)組有沒(méi)有應(yīng)答包
//waittime為等待中斷接收數(shù)據(jù)的時(shí)間(單位1ms)
//返回值:數(shù)據(jù)包首地址
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]='?';
	USART2_RX_STA=0;
	while(--waittime)
	{
		delay_ms(1);
		if(USART2_RX_STA&0X8000)//接收到一次數(shù)據(jù)
		{
			USART2_RX_STA=0;
			data=strstr((const char*)USART2_RX_BUF,(const char*)str);
			if(data)
				return (u8*)data;	
		}
	}
	return 0;
}
//錄入圖像 PS_GetImage
//功能:探測(cè)手指,探測(cè)到后錄入指紋圖像存于ImageBuffer。 
//模塊返回確認(rèn)字
u8 PS_GetImage(void)
{
	u16 temp;
	u8  ensure;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	SendLength(0x03);
	Sendcmd(0x01);
	temp =  0x01+0x03+0x01;
	SendCheck(temp);
	data=JudgeStr(1500);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;
	return ensure;
}
//生成特征 PS_GenChar
//功能:將ImageBuffer中的原始圖像生成指紋特征文件存于CharBuffer1或CharBuffer2			 
//參數(shù):BufferID --> charBuffer1:0x01	charBuffer1:0x02												
//模塊返回確認(rèn)字
u8 PS_GenChar(u8 BufferID)
{
	u16 temp;
  	u8  ensure;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	SendLength(0x04);
	Sendcmd(0x02);
	MYUSART_SendData(BufferID);
	temp = 0x01+0x04+0x02+BufferID;
	SendCheck(temp);
	data=JudgeStr(1500);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;
	return ensure;
}
//精確比對(duì)兩枚指紋特征 PS_Match
//功能:精確比對(duì)CharBuffer1 與CharBuffer2 中的特征文件 
//模塊返回確認(rèn)字
u8 PS_Match(void)
{
	u16 temp;
  	u8  ensure;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	SendLength(0x03);
	Sendcmd(0x03);
	temp = 0x01+0x03+0x03;
	SendCheck(temp);
	data=JudgeStr(1500);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;
	return ensure;
}
//搜索指紋 PS_Search
//功能:以CharBuffer1或CharBuffer2中的特征文件搜索整個(gè)或部分指紋庫(kù).若搜索到,則返回頁(yè)碼。			
//參數(shù):  BufferID @ref CharBuffer1	CharBuffer2
//說(shuō)明:  模塊返回確認(rèn)字,頁(yè)碼(相配指紋模板)
u8 PS_Search(u8 BufferID,u16 StartPage,u16 PageNum,SearchResult *p)
{
	u16 temp;
  	u8  ensure;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	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];	
	}
	else
		ensure = 0xff;
	return ensure;	
}
//合并特征(生成模板)PS_RegModel
//功能:將CharBuffer1與CharBuffer2中的特征文件合并生成 模板,結(jié)果存于CharBuffer1與CharBuffer2	
//說(shuō)明:  模塊返回確認(rèn)字
u8 PS_RegModel(void)
{
	u16 temp;
  	u8  ensure;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	SendLength(0x03);
	Sendcmd(0x05);
	temp = 0x01+0x03+0x05;
	SendCheck(temp);
	data=JudgeStr(2000);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;
	return ensure;		
}
//儲(chǔ)存模板 PS_StoreChar
//功能:將 CharBuffer1 或 CharBuffer2 中的模板文件存到 PageID 號(hào)flash數(shù)據(jù)庫(kù)位置。			
//參數(shù):  BufferID @ref charBuffer1:0x01	charBuffer1:0x02
//       PageID(指紋庫(kù)位置號(hào))
//說(shuō)明:  模塊返回確認(rèn)字
u8 PS_StoreChar(u8 BufferID,u16 PageID)
{
	u16 temp;
  	u8  ensure;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	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];
	else
		ensure=0xff;
	return ensure;	
}
//刪除模板 PS_DeletChar
//功能:  刪除flash數(shù)據(jù)庫(kù)中指定ID號(hào)開(kāi)始的N個(gè)指紋模板
//參數(shù):  PageID(指紋庫(kù)模板號(hào)),N刪除的模板個(gè)數(shù)。
//說(shuō)明:  模塊返回確認(rèn)字
u8 PS_DeletChar(u16 PageID,u16 N)
{
	u16 temp;
  	u8  ensure;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	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];
	else
		ensure=0xff;
	return ensure;
}
//清空指紋庫(kù) PS_Empty
//功能:  刪除flash數(shù)據(jù)庫(kù)中所有指紋模板
//參數(shù):  無(wú)
//說(shuō)明:  模塊返回確認(rèn)字
u8 PS_Empty(void)
{
	u16 temp;
  	u8  ensure;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	SendLength(0x03);
	Sendcmd(0x0D);
	temp = 0x01+0x03+0x0D;
	SendCheck(temp);
	data=JudgeStr(2000);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;
	return ensure;
}
//寫系統(tǒng)寄存器 PS_WriteReg
//功能:  寫模塊寄存器
//參數(shù):  寄存器序號(hào)RegNum:456
//說(shuō)明:  模塊返回確認(rèn)字
u8 PS_WriteReg(u8 RegNum,u8 DATA)
{
	u16 temp;
  	u8  ensure;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	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];
	else
		ensure=0xff;
	if(ensure==0)
		printf("rn設(shè)置參數(shù)成功!");
	else
		printf("rn%s",EnsureMessage(ensure));
	return ensure;
}
//讀系統(tǒng)基本參數(shù) PS_ReadSysPara
//功能:  讀取模塊的基本參數(shù)(波特率,包大小等)
//參數(shù):  無(wú)
//說(shuō)明:  模塊返回確認(rèn)字 + 基本參數(shù)(16bytes)
u8 PS_ReadSysPara(SysPara *p)
{
	u16 temp;
  	u8  ensure;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	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];
	}		
	else
		ensure=0xff;
	if(ensure==0x00)
	{
		printf("rn模塊最大指紋容量=%d",p->PS_max);
		printf("rn對(duì)比等級(jí)=%d",p->PS_level);
		printf("rn地址=%x",p->PS_addr);
		printf("rn波特率=%d",p->PS_N*9600);
	}
	else 
			printf("rn%s",EnsureMessage(ensure));
	return ensure;
}
//設(shè)置模塊地址 PS_SetAddr
//功能:  設(shè)置模塊地址
//參數(shù):  PS_addr
//說(shuō)明:  模塊返回確認(rèn)字
u8 PS_SetAddr(u32 PS_addr)
{
	u16 temp;
  	u8  ensure;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	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;//發(fā)送完指令,更換地址
  	data=JudgeStr(2000);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;	
		AS608Addr = PS_addr;
	if(ensure==0x00)
		printf("rn設(shè)置地址成功!");
	else
		printf("rn%s",EnsureMessage(ensure));
	return ensure;
}
//功能: 模塊內(nèi)部為用戶開(kāi)辟了256bytes的FLASH空間用于存用戶記事本,
//	該記事本邏輯上被分成 16 個(gè)頁(yè)。
//參數(shù):  NotePageNum(0~15),Byte32(要寫入內(nèi)容,32個(gè)字節(jié))
//說(shuō)明:  模塊返回確認(rèn)字
u8 PS_WriteNotepad(u8 NotePageNum,u8 *Byte32)
{
	u16 temp;
  	u8  ensure,i;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	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];
	else
		ensure=0xff;
	return ensure;
}
//讀記事PS_ReadNotepad
//功能:  讀取FLASH用戶區(qū)的128bytes數(shù)據(jù)
//參數(shù):  NotePageNum(0~15)
//說(shuō)明:  模塊返回確認(rèn)字+用戶信息
u8 PS_ReadNotepad(u8 NotePageNum,u8 *Byte32)
{
	u16 temp;
  	u8  ensure,i;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	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];
		}
	}
	else
		ensure=0xff;
	return ensure;
}
//高速搜索PS_HighSpeedSearch
//功能:以 CharBuffer1或CharBuffer2中的特征文件高速搜索整個(gè)或部分指紋庫(kù)。
//		  若搜索到,則返回頁(yè)碼,該指令對(duì)于的確存在于指紋庫(kù)中 ,且登錄時(shí)質(zhì)量
//		  很好的指紋,會(huì)很快給出搜索結(jié)果。
//參數(shù):  BufferID, StartPage(起始頁(yè)),PageNum(頁(yè)數(shù))
//說(shuō)明:  模塊返回確認(rèn)字+頁(yè)碼(相配指紋模板)
u8 PS_HighSpeedSearch(u8 BufferID,u16 StartPage,u16 PageNum,SearchResult *p)
{
	u16 temp;
  	u8  ensure;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	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];
	}
	else
		ensure=0xff;
	return ensure;
}
//讀有效模板個(gè)數(shù) PS_ValidTempleteNum
//功能:讀有效模板個(gè)數(shù)
//參數(shù): 無(wú)
//說(shuō)明: 模塊返回確認(rèn)字+有效模板個(gè)數(shù)ValidN
u8 PS_ValidTempleteNum(u16 *ValidN)
{
	u16 temp;
  	u8  ensure;
	u8  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包標(biāo)識(shí)
	SendLength(0x03);
	Sendcmd(0x1d);
	temp = 0x01+0x03+0x1d;
	SendCheck(temp);
  	data=JudgeStr(2000);
	if(data)
	{
		ensure=data[9];
		*ValidN = (data[10]<<8) +data[11];
	}		
	else
		ensure=0xff;
	
	if(ensure==0x00)
	{
		printf("rn有效指紋個(gè)數(shù)=%d",(data[10]<<8)+data[11]);
	}
	else
		printf("rn%s",EnsureMessage(ensure));
	return ensure;
}
//與AS608握手 PS_HandShake
//參數(shù): PS_Addr地址指針
//說(shuō)明: 模塊返新地址(正確地址)	
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)//接收到數(shù)據(jù)
	{		
		if(//判斷是不是模塊返回的應(yīng)答包				
					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;		
}
//模塊應(yīng)答包確認(rèn)碼信息解析
//功能:解析確認(rèn)碼錯(cuò)誤信息返回信息
//參數(shù): ensure
const char *EnsureMessage(u8 ensure) 
{
	const char *p;
	switch(ensure)
	{
		case  0x00:
			p="OK";break;		
		case  0x01:
			p="數(shù)據(jù)包接收錯(cuò)誤";break;
		case  0x02:
			p="傳感器上沒(méi)有手指";break;
		case  0x03:
			p="錄入指紋圖像失敗";break;
		case  0x04:
			p="指紋圖像太干、太淡而生不成特征";break;
		case  0x05:
			p="指紋圖像太濕、太糊而生不成特征";break;
		case  0x06:
			p="指紋圖像太亂而生不成特征";break;
		case  0x07:
			p="指紋圖像正常,但特征點(diǎn)太少(或面積太?。┒怀商卣?;break;
		case  0x08:
			p="指紋不匹配";break;
		case  0x09:
			p="沒(méi)搜索到指紋";break;
		case  0x0a:
			p="特征合并失敗";break;
		case  0x0b:
			p="訪問(wèn)指紋庫(kù)時(shí)地址序號(hào)超出指紋庫(kù)范圍";
		case  0x10:
			p="刪除模板失敗";break;
		case  0x11:
			p="清空指紋庫(kù)失敗";break;	
		case  0x15:
			p="緩沖區(qū)內(nèi)沒(méi)有有效原始圖而生不成圖像";break;
		case  0x18:
			p="讀寫 FLASH 出錯(cuò)";break;
		case  0x19:
			p="未定義錯(cuò)誤";break;
		case  0x1a:
			p="無(wú)效寄存器號(hào)";break;
		case  0x1b:
			p="寄存器設(shè)定內(nèi)容錯(cuò)誤";break;
		case  0x1c:
			p="記事本頁(yè)碼指定錯(cuò)誤";break;
		case  0x1f:
			p="指紋庫(kù)滿";break;
		case  0x20:
			p="地址錯(cuò)誤";break;
		default :
			p="模塊返回確認(rèn)碼有誤";break;
	}
 	return p;	
}

2、錄指紋函數(shù)

//錄入指紋
u16 Add_FR(u16 ID)
{
	u8 i=0,ensure,processnum=0;
	int a=1;
	Audio(2);  //播放"開(kāi)始錄入指紋"
	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);  //顯示"請(qǐng)按手指"
					delay_ms(50);
					if(PS_Sta==1)
					{
					ensure=PS_GetImage();  //錄入圖像
					if(ensure==0x00) 
					{	
						ensure=PS_GenChar(CharBuffer1);  //生成特征
						if(ensure==0x00)
						{ 
							Audio(4);  //播報(bào)"開(kāi)始錄入指紋"
							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);  //顯示"指紋錯(cuò)誤"						
						}
					}		
				}										
				break;		
			case 1:
					i++;
			  		Audio(5);  //播報(bào)"請(qǐng)?jiān)侔匆淮问种?	
			  		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);  //顯示"指紋錯(cuò)誤"		
							}
						}			
					}						
					break;
			case 2:
					i++;			  
					ensure=PS_Match();  //對(duì)比兩次指紋
					if(ensure==0x00)  //兩次指紋一致
					{				 
						processnum=3;  //跳到第四步 
					}
					else  //兩次指紋不一致
					{ 
          				Audio(19);  //播報(bào)"兩次指紋不一樣,請(qǐng)重新錄入"						
  						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);  //"請(qǐng)重新錄入"
						delay_ms(1500);
						OLED_ShowString(8,2,"                 ",16);
						OLED_ShowString(8,4,"                 ",16);
						i=0;
						processnum=0;  //跳回第一步		
					}
					break;
			case 3:	
					ensure=PS_RegModel();  //產(chǎn)生一個(gè)指紋模板
					if(ensure==0x00)  //生成指紋模板成功 
					{										
						processnum=4;  //跳到第五步
					}
					else 
        			{
				  		processnum=0;
					}
					break;	
			case 4:	
		    		i++;
					ensure=PS_StoreChar(CharBuffer2,ID);  //儲(chǔ)存模板
					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);  //寫入當(dāng)前ID       		
         				a=0;
		      			break;
					}
			        else 
			        {
				  		processnum=0;
					}	
					break;							
				}
    		delay_ms(1000);		
			if(i>5) 
			{		
				i=0;
				a=0;
				Audio(7);  //播報(bào)"錄入失敗"
				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);//播報(bào)“開(kāi)始簽到,請(qǐng)按手指”
	}
	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);  //顯示"開(kāi)始簽到"
//	printf("開(kāi)始簽到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);    //顯示"比對(duì)中..."						
//			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:%dn",seach.pageID,seach.mathscore);//顯示匹配指紋的ID和分?jǐn)?shù)
//					printf(" 匹配指紋的ID和分?jǐn)?shù)  %sn",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);//播報(bào)“簽到成功”					
					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、清空指紋

這個(gè)函數(shù)在底層驅(qū)動(dòng)里面有,直接調(diào)用即可

PS_Empty();

5、上傳和下載指紋

如果沒(méi)有用到這個(gè)功能可以跳過(guò)

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);		//寫入當(dāng)前ID
			OLED_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函數(shù)

我這份程序是做一個(gè)學(xué)生簽到系統(tǒng),上位機(jī)通過(guò)串口給單片機(jī)發(fā)送指令,單片機(jī)執(zhí)行相應(yīng)的操作

int main(void)
{		
  	u16 t=0;
	delay_init();
  	Audio_Init();//語(yǔ)音模塊初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置系統(tǒng)中斷優(yōu)先級(jí)分組2

	TIM4_Int_Init(9999,7199);//10Khz的計(jì)數(shù)頻率,1s定時(shí)中斷
	uart_init(115200);	//初始化串口1波特率為115200,用于與上位機(jī)通訊
	usart2_init(57600);//初始化串口2,用于與指紋模塊通訊
	PS_StaGPIO_Init();	//初始化FR讀狀態(tài)引腳
	OLED_Init(); //OLED初始化
	OLED_Clear();//OLED清屏
	SPI_Flash_Init(); //外接FLASH芯片W25Q64初始化,用來(lái)存學(xué)生學(xué)號(hào)(指紋是存到AS608芯片里面的) 	
	LED_Init();

	while(SPI_Flash_ReadID()!=W25Q64)  //檢測(cè)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();//等待串口接收指令(我這里是用上位機(jī)給單片機(jī)串口發(fā)指令的)
		delay_ms(100);
		if(command==0x01)  //收到錄入指紋命令
		{
			command=0;			
			SPI_Flash_Write((u8*)TEXT_Buffer,FLASH_SIZE-100,1);//從倒數(shù)第100個(gè)地址處開(kāi)始,寫入SIZE長(zhǎng)度的數(shù)據(jù)
			SPI_Flash_Read(ZW_ID,FLASH_SIZE-100,1);				//讀取當(dāng)前已存的最大指紋ID號(hào)
			ID=ZW_ID[0]+1;	
			
			Add_FR(ID);		//錄指紋	
 
      		show_main_page();		//顯示首頁(yè)界面
		}
		else if(command==0x02)  //上傳指紋
		{	
			command=0;
			SPI_Flash_Read(ZW_ID,FLASH_SIZE-100,1);				//讀取當(dāng)前已存的最大指紋ID號(hào)
			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];  //向上位機(jī)上傳指紋信息
			}
//			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);  //讀取當(dāng)前已存的最大指紋ID號(hào)
			ID=ZW_ID[0]+1;
			Down_FR(ID);  //下載指紋
			show_main_page();  
		}
		else if(command==0x04)  //上傳學(xué)號(hào)/開(kāi)始簽到
		{
		  	press_FR();  
		}		
		else if(command==0x05)  //下載學(xué)號(hào)
		{	
			command=0;
			Down_stu_num(ID);  
			show_main_page();
		}
		else if(command==0x06) //結(jié)束簽到
		{	
			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);//顯示"結(jié)束簽到"	
			delay_ms(1500);
			show_main_page();
		}
		else if(command==0x07) //清空數(shù)據(jù)
		{	
			command=0;
			PS_Empty();
			ZW_ID[0]=0;
			SPI_Flash_Write((u8*)ZW_ID,FLASH_SIZE-100,1);		//寫入當(dāng)前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);//"已清空數(shù)據(jù)"		
			Audio(18);  //播放"播放已清空數(shù)據(jù)"		
			delay_ms(1500);
			show_main_page();
		}		
	}		
} 	

好了,關(guān)于這個(gè)光學(xué)指紋識(shí)別模塊就講到這里,程序是以前寫的,現(xiàn)在回看,諸多地方都不滿意,也沒(méi)時(shí)間一一去改了,如果你們覺(jué)得寫的不好,勿怪,如果大家還有什么問(wèn)題可以留言給我。

源碼下載鏈接1:https://pan.baidu.com/s/1A2fbiTy10-2pZUxAaQdJnw ,提取碼:8kdp
源碼下載鏈接2:https://pan.baidu.com/s/1aOKyCLwdMrvzPlpIq5tMtA,提取碼:abcd

如果覺(jué)得博主寫的文章有用,那就點(diǎn)贊+關(guān)注支持一下吧,創(chuàng)作不易,加班狗用業(yè)余時(shí)間寫博客,不容易吶,所以請(qǐng)尊重每一位博主的勞動(dòng),后續(xù)也會(huì)繼續(xù)介紹一些適合大學(xué)生使用的模塊,謝謝大家?。?!

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
ABS07-32.768KHZ-9-T 1 Abracon Corporation CRYSTAL 32.7680KHZ 9PF SMD

ECAD模型

下載ECAD模型
$1.4 查看
CPC2017NTR 1 IXYS Corporation Transistor Output SSR, 2-Channel, 1500V Isolation, ROHS COMPLIANT, MINIATURE, SOIC-8
$3.87 查看
KSZ8851SNLI 1 Microchip Technology Inc DATACOM, ETHERNET TRANSCEIVER, PQCC32
$5.06 查看

相關(guān)推薦

民乐县| 池州市| 雷波县| 漠河县| 高清| 通江县| 正镶白旗| 莆田市| 拉孜县| 大厂| 怀化市| 杭锦旗| 随州市| 金寨县| 清镇市| 济南市| 大竹县| 乐清市| 杨浦区| 岳阳县| 邵阳县| 西平县| 周宁县| 东乌| 邓州市| 武陟县| 南涧| 砚山县| 永城市| 安陆市| 兴安县| 定南县| 德州市| 遵化市| 新巴尔虎右旗| 长海县| 青阳县| 故城县| 奇台县| 通城县| 治多县|