指纹模块程序驱动(四-四)

Fingerprint

Fingerprint.h

指纹模块驱动头文件

#ifndef __FINGERPRINT_H
#define __FINGERPRINT_H

#include "core51_it.h"
#include "delay.h"

/******************************
!!!!!!注意!!!!!!!!
1、必须将FP_Handler接收中断回调函数放在相应串口中断服务函数中
2、注意接收缓冲区大小设置
******************************/
#define NULL 0
sbit TOUCH = P3^7;
sbit FP_LED_Test = P0^0;

/*指纹模块型号*/
#define YX_F112	0
#define AS608 		1
#define FP_Model YX_F112

/*驱动类型*/
#define Simplification	0			//精简模式,部分功能函数无法使用,用于缩小代码体积和运行内存占用空间
#define Entirety			1			//全功能模式
#define Drive_Mode Simplification

/*接收缓冲区大小,精简模式下不小于14字节,全功能模式下不小于52字节*/
#define FP_RData_Size	14

/*判断缓冲区设置大小是否合理*/
#if ((Drive_Mode == Entirety) && (FP_RData_Size < 52))			//指纹模块结构体中的参数数组调整至40字节,所以相比精简版的缓冲区大38B
	#error Too few FP_RData_Size in entirety mode
#endif

#if ((Drive_Mode == Simplification) && (FP_RData_Size < 14))	//帧头不会存入接收缓冲区,且指纹模块结构体中的参数数组调整至4字节,16B-2B=14B
	#error Too few FP_RData_Size in simplification mode
#endif

/*指纹模块结构体*/
typedef struct
{
	u8  RData[FP_RData_Size];
	u8  RevFlag;
	u8  Addr[4];			//设备地址
	u8  Affirm;				//确认码
	
	#if (Drive_Mode == Simplification)
	u8  Param[4];			//参数
	#endif
	
	#if (Drive_Mode == Entirety)
	u8  Param[40];			//参数
	u16 System_State;		//系统状态寄存器
	u16 Discern_Number;	//识别码
	u16 Capacity;			//指纹库容量
	u16 Safety;				//安全等级
	u16 Data_Byte;			//数据包大小
	u16 Baud;				//波特率
	#endif
}FP_Struct;

static void FP_TOUCH_Init(void);			//初始化感应引脚
static u8 FP_Receive_Data(void);			//接收FP数据
static u8 FP_Verify(u8 *Data);			//数据包校验
static u8 Wait_FP_Ack(void);				//等待FP应答
void FP_Handler(void);						//串口中断回调函数
u8 FP_Init(FP_Struct *Fd);					//初始化
u8 FP_Send_Command(u8 Command, u8 *Param,u8 Len);	//发送指令
u8 Scan_Fingerprint(u16 StartPage, u16 EndPage);	//扫描指纹
u8 Add_Fingerprint(u8 Step,u16 Addr);	//添加指纹
u8 Del_Fingerprint(u16 Addr,u16 Num);	//删除指纹
u8 Cls_Del_Fingerprint(void);				//清空指纹库
void FP_Test(void);							//指纹模块测试函数

/*全功能模式下*/
#if (Drive_Mode == Entirety)
u8 Read_SysPara(void);						//读取系统参数
u8 Read_Valid_Templete_Num(void);		//读取有效模板个数
u8 Set_FP_Addr(u8 *Addr);					//设置模块地址
u8 Write_Reg(u8 Reg_Number,u8 Data);	//写寄存器
u8 Read_Index_Table(u8 Page_Number);	//读取已录入模板的索引表
						  
#endif

#endif

Fingerprint.c

指纹模块驱动头文件

#include "Fingerprint.H"

FP_Struct *FP;

/*******************************************************************************
* 函 数 名         : FP_Handler
* 输    入         : 空
* 输    出         :	空
* 函数功能		    : 指纹模块中断回调函数
* 详细描述			 :	此函数一般放在串口中断服务函数中,用于接收指纹模块数据
*******************************************************************************/
void FP_Handler(void)
{
	FP->RevFlag = FP_Receive_Data();
}

/*******************************************************************************
* 函 数 名         : FP_TOUCH_Init
* 输    入         : 空
* 输    出         :	空
* 函数功能		    : 接指纹模块触摸输出的引脚初始化
* 详细描述			 :	空
*******************************************************************************/
static void FP_TOUCH_Init(void)
{
	TOUCH = 1;
}

/*******************************************************************************
* 函 数 名         : FP_Receive_Data
* 输    入         : 空
* 输    出         :	0:接收失败
*							1:接收成功
*
* 函数功能		    : 接收指纹模块数据
* 详细描述			 :	空
*******************************************************************************/
static u8 FP_Receive_Data(void)
{
	u16 Count;
	
	RI = 0;					//清除接收中断
	
	if(SBUF == 0xEF)		//判断包头
	{
		#if Uart
		if(UART1_Wait_Receive(300))
			return 0;
		#endif

		if(SBUF == 0x01)	//判断包头
		{
			for(Count = 0;(Count < (FP->RData[6] + 7)) && (Count < FP_RData_Size);Count ++)	//接收数据
			{
				#if Uart
				if(UART1_Wait_Receive(300))
					return 0;
				#endif
				
				FP->RData[Count] = SBUF;
			}
		}
		else
			return 0;
	}
	else
		return 0;
	
	return 1;
}

/*******************************************************************************
* 函 数 名         : FP_Verify
* 输    入         : 空
* 输    出         :	0:校验成功
*							1:校验和错误
*
* 函数功能		    : 数据包校验
* 详细描述			 :	空
*******************************************************************************/
static u8 FP_Verify(u8 *Data)
{
	u16 Count;
	u16 Sum = 0;
	
	for(Count = 0;Count < (Data[6] + 1);Count ++)		//校验和
		Sum += Data[4 + Count];
	
	if((Data[FP->RData[6] + 7 - 2] != ((Sum >> 8) & 0xFF)) || 
		(Data[FP->RData[6] + 7 - 1] != (Sum & 0xFF)))
		return 1;	//校验和错误
	
	return 0;
}

/*******************************************************************************
* 函 数 名         : Wait_FP_Ack
* 输    入         : 空
* 输    出         :	0xFE:数据包校验错误
*							0xFF:应答超时
*							其他:应答正常
*
* 函数功能		    : 等待指纹模块应答
* 详细描述			 :	空
*******************************************************************************/
static u8 Wait_FP_Ack(void)
{
	u16 Count = 500;
	
	while((FP->RevFlag == 0) && (Count > 0))	//等待接收
	{
		Count --;
		Delay_Xms(1);
	}
	
	FP->RevFlag = 0;
	
	if(FP_Verify(FP->RData) != 0)		//数据包校验错误
		return 0xFE;				
	
	if(Count > 0)
	{
		FP->Affirm = FP->RData[7];		//保存确认码
		
		for(Count = 0;Count < (((FP->RData[5] << 8) | FP->RData[6]) - 3);Count ++)	//保存返回参数
			FP->Param[Count] = FP->RData[Count + 8];
		
		return FP->Affirm;
	}
	else
		return 0xFF;						//等待超时
}

/*******************************************************************************
* 函 数 名         : FP_Send_Command
* 输    入         : 空
* 输    出         :	0:发送成功
*							1:发送失败
*
* 函数功能		    : 发送指令
* 详细描述			 :	空
*******************************************************************************/
u8 FP_Send_Command(u8 Command,u8 *Param,u8 Len)
{
	u8 Count,Data[20]={0xEF,0x01};
	u16 Sum;
	
	Data[2] = FP->Addr[3];						//模块地址
	Data[3] = FP->Addr[2];
	Data[4] = FP->Addr[1];
	Data[5] = FP->Addr[0];
	Data[6] = 0x01;								//包标识
	Data[7] = ((Len + 3) >> 8) & 0xFF;		//包长度
	Data[8] = (Len + 3) & 0xFF;			
	Data[9] = Command;							//指令
	
	for(Count = 0;Count < Len;Count ++)		//参数
		Data[Count + 10] = *(Param + Count);
	
	for(Count = Sum = 0;Count < (Len + 4);Count ++)	//数据累加和
		Sum += Data[Count + 6];
	
	Data[Len + 10] = (Sum >> 8) & 0xFF;		//校验和
	Data[Len + 11] = Sum & 0xFF;
	
	#if Uart
	if(UART1_Send_Data(Data,Len + 12) == 1)
		return 1;
	#endif

	return 0;
}

/*******************************************************************************
* 函 数 名         : Set_FP_Addr
* 输    入         : StartPage:扫描起始页
*							EndPage:扫描结束页
*
* 输    出         :	0:成功
*							其他:失败
*
* 函数功能		    : 扫描指纹
* 详细描述			 :	空
*******************************************************************************/
u8 Scan_Fingerprint(u16 StartPage,u16 EndPage)
{
	u8 Temp[5];
	
	FP_Send_Command(0x01,NULL,0);	//获取图像
	
	if(Wait_FP_Ack())					//等待应答
		return FP->Affirm;				//应答超时或指令执行失败返回确认码
	
	Temp[0] = 1;							//生成特征存放于CharBuffer1
	FP_Send_Command(0x02,Temp,1);	//生成特征
	
	if(Wait_FP_Ack())					//等待应答
		return FP->Affirm;				//应答超时或指令执行失败返回确认码
	
	Temp[0] = 1;
	Temp[1] = (StartPage >> 8) & 0xFF;
	Temp[2] = StartPage & 0xFF;
	Temp[3] = ((EndPage - StartPage) >> 8) & 0xFF;
	Temp[4] = (EndPage - StartPage) & 0xFF;
	FP_Send_Command(0x04,Temp,5);	//搜索指纹
	
	if(Wait_FP_Ack())					//等待应答
		return FP->Affirm;				//应答超时或指令执行失败返回确认码
	
	return 0;
}

/*******************************************************************************
* 函 数 名         : Add_Fingerprint
* 输    入         : Step:步骤
*							Addr:指纹存储地址
*
* 输    出         :	0:成功
*							其他:失败
*
* 函数功能		    : 添加指纹
* 详细描述			 :	空
*******************************************************************************/
#if (FP_Model == YX_F112)
u8 Add_Fingerprint(u8 Step,u16 Addr)
{
	u8 Temp[10];
	
	switch(Step)
	{
		case 0:
			FP_Send_Command(0x01,NULL,0);	//获取图像
		
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
	
			Temp[0] = 1;						//生成特征存放于CharBuffer1
			FP_Send_Command(0x02,Temp,1);	//生成特征
			
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
		break;
			
		case 1:	
			FP_Send_Command(0x01,NULL,0);	//获取图像
		
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
			
			Temp[0] = 2;						//生成特征存放于CharBuffer2
			FP_Send_Command(0x02,Temp,1);	//生成特征
			
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
		break;
			
		case 2:	
			FP_Send_Command(0x01,NULL,0);	//获取图像
		
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
			
			Temp[0] = 3;						//生成特征存放于CharBuffer2
			FP_Send_Command(0x02,Temp,1);	//生成特征
			
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
		break;
			
		case 3:	
			FP_Send_Command(0x01,NULL,0);	//获取图像
		
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
			
			Temp[0] = 4;						//生成特征存放于CharBuffer2
			FP_Send_Command(0x02,Temp,1);	//生成特征
			
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
		break;
			
		case 4:	
			FP_Send_Command(0x01,NULL,0);	//获取图像
		
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
			
			Temp[0] = 5;						//生成特征存放于CharBuffer2
			FP_Send_Command(0x02,Temp,1);	//生成特征
			
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
		break;
			
		case 5:	
			FP_Send_Command(0x01,NULL,0);	//获取图像
		
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
			
			Temp[0] = 6;						//生成特征存放于CharBuffer2
			FP_Send_Command(0x02,Temp,1);	//生成特征
			
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
		break;
			
		case 6:
			FP_Send_Command(0x05,NULL,0);	//将CharBuffer1和CharBuffer2中的特征文件合并,生成模板
		
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
			
			Temp[0] = 2;
			Temp[1] = (Addr >> 8) & 0xFF;
			Temp[2] = Addr & 0xFF;
			FP_Send_Command(0x06,Temp,3);	//将CharBuffer2中的模板 存储于Flash数据库Addr中
			
			if(Wait_FP_Ack())					//等待应答
				return FP->Affirm;			//应答超时或指令执行失败返回确认码
		break;
	}
	
	return 0;
}
#endif

#if (FP_Model == AS608)
u8 Add_Fingerprint(u8 Step,u16 Addr)
{
	u8 Temp[10];
	
	switch(Step)
	{
		case 0:
			FP_Send_Command(FP,0x01,NULL,0);	//获取图像
		
			if(Wait_FP_Ack(FP))					//等待应答
				return FP->Affirm;				//应答超时或指令执行失败返回确认码
	
			Temp[0] = 1;							//生成特征存放于CharBuffer1
			FP_Send_Command(FP,0x02,Temp,1);	//生成特征
			
			if(Wait_FP_Ack(FP))					//等待应答
				return FP->Affirm;				//应答超时或指令执行失败返回确认码
		break;
			
		case 1:	
			FP_Send_Command(FP,0x01,NULL,0);	//获取图像
		
			if(Wait_FP_Ack(FP))					//等待应答
				return FP->Affirm;				//应答超时或指令执行失败返回确认码
			
			Temp[0] = 2;							//生成特征存放于CharBuffer2
			FP_Send_Command(FP,0x02,Temp,1);	//生成特征
			
			if(Wait_FP_Ack(FP))					//等待应答
				return FP->Affirm;				//应答超时或指令执行失败返回确认码
		break;
		
		case 2:	
			FP_Send_Command(FP,0x03,NULL,0);	//将CharBuffer1和CharBuffer2中的特征文件合并,生成模板
		
			if(Wait_FP_Ack(FP))					//等待应答
				return FP->Affirm;				//应答超时或指令执行失败返回确认码
		break;
			
		case 3:
			FP_Send_Command(FP,0x05,NULL,0);	//将CharBuffer1和CharBuffer2中的特征文件合并,生成模板
		
			if(Wait_FP_Ack(FP))					//等待应答
				return FP->Affirm;				//应答超时或指令执行失败返回确认码
			
			Temp[0] = 2;
			Temp[1] = (Addr >> 8) & 0xFF;
			Temp[2] = Addr & 0xFF;
			FP_Send_Command(FP,0x06,Temp,3);	//将CharBuffer2中的模板 存储于Flash数据库Addr中
			
			if(Wait_FP_Ack(FP))					//等待应答
				return FP->Affirm;				//应答超时或指令执行失败返回确认码
		break;
	}
	
	return 0;
}
#endif

/*******************************************************************************
* 函 数 名         : Del_Fingerprint
* 输    入         : Addr:指纹存储地址
*							Num:指纹地址开始的N个模板
*
* 输    出         :	0:成功
*							其他:失败
*
* 函数功能		    : 删除指纹
* 详细描述			 :	空
*******************************************************************************/
u8 Del_Fingerprint(u16 Addr,u16 Num)
{
	u8 Temp[10];
	
	Temp[0] = (Addr >> 8) & 0xFF;
	Temp[1] = Addr & 0xFF;			
	Temp[2] = (Num >> 8) & 0xFF;
	Temp[3] = Num & 0xFF;
	FP_Send_Command(0x0C,Temp,4);	//生成特征
	
	if(Wait_FP_Ack())					//等待应答
		return FP->Affirm;				//应答超时或指令执行失败返回确认码
	
	return 0;
}

/*******************************************************************************
* 函 数 名         : Cls_Del_Fingerprint
* 输    入         : 空
* 输    出         :	0:成功
*							其他:失败
*
* 函数功能		    : 清空指纹库
* 详细描述			 :	空
*******************************************************************************/
u8 Cls_Del_Fingerprint(void)
{
	FP_Send_Command(0x0D,NULL,0);	//生成特征
	
	if(Wait_FP_Ack())					//等待应答
		return FP->Affirm;				//应答超时或指令执行失败返回确认码
	
	return 0;
}

/*******************************************************************************
* 函 数 名         : Read_Valid_Templete_Num
* 输    入         : Fd:指纹结构体指针
* 输    出         :	0:成功
*							其他:失败
*
* 函数功能		    : 指纹模块初始化
* 详细描述			 :	空
*******************************************************************************/
u8 FP_Init(FP_Struct *Fd)
{
	Delay_Xms(700);	//等待模块上电稳定
	FP_TOUCH_Init();
	
	FP = Fd;
	FP->Addr[0] = 0xFF;
	FP->Addr[1] = 0xFF;
	FP->Addr[2] = 0xFF;
	FP->Addr[3] = 0xFF;
	
#if (Drive_Mode == Entirety)
	return Read_SysPara(FP);
#endif
	
#if (Drive_Mode == Simplification)
	return 0;
#endif
}

#if (Drive_Mode == Entirety)
/*******************************************************************************
* 函 数 名         : Read_SysPara
* 输    入         : 空
* 输    出         :	0:成功
*							其他:失败
*
* 函数功能		    : 写系统参数
* 详细描述			 :	空
*******************************************************************************/
u8 Read_SysPara(void)
{
	FP_Send_Command(FP,0x0F,NULL,0);		//读取系统参数
	
	if((FP->Affirm = Wait_FP_Ack(FP)))//等待应答
		return FP->Affirm;				//应答超时或指令执行失败返回确认码
	
	FP->System_State = (u16)(FP->Param[0] << 8) | FP->Param[1];		//系统状态寄存器
	FP->Discern_Number = (u16)(FP->Param[2] << 8) | FP->Param[3];	//识别码
	FP->Capacity = (u16)(FP->Param[4] << 8) | FP->Param[5];			//指纹库容量
	FP->Safety = (u16)(FP->Param[6] << 8) | FP->Param[7];				//安全等级 
	FP->Addr[3] = FP->Param[8];												//设备地址
	FP->Addr[2] = FP->Param[9];
	FP->Addr[1] = FP->Param[10];
	FP->Addr[0] = FP->Param[11];
	FP->Data_Byte = (u16)(FP->Param[12] << 8) | FP->Param[13];		//数据包大小
	FP->Baud = (u16)(FP->Param[14] << 8) | FP->Param[15];				//波特率
	
	return 0;
}
/*******************************************************************************
* 函 数 名         : Write_Reg
* 输    入         : Reg_Number:寄存器号(4-6)
*							Data:数据
*
* 输    出         :	0:成功
*							其他:失败
*
* 函数功能		    : 写系统参数
* 详细描述			 :	空
*******************************************************************************/
u8 Write_Reg(u8 Reg_Number,u8 Data)
{
	u8 Temp[10];
	
	Temp[0] = Reg_Number;
	Temp[1] = Data;
	FP_Send_Command(FP,0x0E,Temp,2);	//写寄存器
	
	if(Wait_FP_Ack(FP))					//等待应答
		return FP->Affirm;				//应答超时或指令执行失败返回确认码

	return 0;
}

/*******************************************************************************
* 函 数 名         : Read_Valid_Templete_Num
* 输    入         : 空
* 输    出         :	0:成功
*							其他:失败
*
* 函数功能		    : 读取有效模板个数
* 详细描述			 :	空
*******************************************************************************/
u8 Read_Valid_Templete_Num(void)
{
	FP_Send_Command(FP,0x1D,NULL,0);	//读取有效模板个数
	
	if(Wait_FP_Ack(FP))					//等待应答
		return FP->Affirm;				//应答超时或指令执行失败返回确认码
	
	return 0;
}

/*******************************************************************************
* 函 数 名         : Read_Valid_Templete_Num
* 输    入         : Page_Number:索引表页码
* 输    出         :	0:成功
*							其他:失败
*
* 函数功能		    : 读取已录入模板的索引表
* 详细描述			 :	空
*******************************************************************************/
u8 Read_Index_Table(u8 Page_Number)
{
	u8 Temp[10];
	
	Temp[0] = Page_Number;
	FP_Send_Command(FP,0x1F,Temp,1);	//读取已录入模板的索引表
	
	if(Wait_FP_Ack(FP))					//等待应答
		return FP->Affirm;				//应答超时或指令执行失败返回确认码

	return 0;
}

/*******************************************************************************
* 函 数 名         : Set_FP_Addr
* 输    入         : Addr:需设置的模块地址
* 输    出         :	0:成功
*							其他:失败
*
* 函数功能		    : 设置模块地址
* 详细描述			 :	空
*******************************************************************************/
u8 Set_FP_Addr(u8 *Addr)
{
	FP_Send_Command(FP,0x15,Addr,4);	//搜索指纹
	
	if(Wait_FP_Ack(FP))					//等待应答
		return FP->Affirm;				//应答超时或指令执行失败返回确认码

	return 0;
}
#endif

/*******************************************************************************
* 函 数 名         : FP_Test
* 输    入         : 空
* 输    出         :	空
* 函数功能		    : 指纹模块测试函数
* 详细描述			 :	空
*******************************************************************************/
void FP_Test(void)
{
	u8 err = 0,Step = 0,Step_Max = 4,Cnt;
	FP_Struct xdata FP;
	
#if (FP_Model == YX_F112)
	Step_Max = 7;
#endif
	
#if (FP_Model == AS608)
	Step_Max = 4;
#endif
	
	FP_Init(&FP);
	
	while(1)
	{
		/*指纹对比*/
//		err = Scan_Fingerprint(0,100);
//		if(err == 0)
//			FP_LED_Test = 0;
//		else
//			FP_LED_Test = 1;
//		
		/*录入指纹到地址0中*/
		err = Add_Fingerprint(Step,0);
		if(err == 0x00)
		{
			FP_LED_Test = 0;
			Step ++;
		}
		else
			FP_LED_Test = 1;

		if(Step == Step_Max)
		{
			for(Cnt = 0;Cnt < 10;Cnt ++)
			{
				FP_LED_Test = !FP_LED_Test;
				Delay_Xms(300);
			}
			
			FP_LED_Test = 1;
			Step = 0;
		}
		
		FP_LED_Test = TOUCH;
		Delay_Xms(1000);
	}
}

外部链接

码云下载:https://gitee.com/LWTDZ/Core8051.git
店铺地址:https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-22129052348.16.6b222269wKu2dH&id=615384296160
QQ群(STM32嵌入式Linux&单片机):950822175


版权声明:本文为qq_34390075原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。