毕设-基于STM32刷卡、指纹的门禁系统(进阶版)

简介

基础版本做完了,感觉很平淡所以这次来了一个很好玩的模块——AS608指纹模块

模块介绍

该模块的通信方式是串口,驱动方式使用串口指令,模块会根据指令执行。基本原理是内置的图像识别技术,根据存储的指纹特征点和需要对比的指纹进行对比。
在这里插入图片描述

引脚介绍

在这里插入图片描述
在这里插入图片描述

接线顺序从左到右依次是:
Vi——接开发板3.3V
Tx——接开发板PA3
Rx——接开发板PA2
GND——接开发板GND
WAK——接开发板PB12
Vi——接开发板3.3V或悬空

指令

1)录入指纹图像 PS_GetImage
在这里插入图片描述
2)生成特征 PS_GenChar
在这里插入图片描述
3)搜索指纹 PS_Search
在这里插入图片描述
4) 合并特征(生成模板) PS_RegModel
在这里插入图片描述
5)储存模板 PS_StoreChar
在这里插入图片描述
6)删除模板 PS_DeletChar在这里插入图片描述

驱动方式

该模块采用的是串口指令的方式,使用串口与之连接然后发送16进制的数据指令,模块会根据数据指令完成对应的任务。
录入指纹数据的步骤
1)删除指定缓存区的数据
2)录入指纹图像
3) 生成特征放在buffer1中
4)录取指纹图像
5)生成特征放在buffer2中
6)合并特征模板
7)存储特征模板
搜索指纹数据的步骤
1)录取指纹数据
2)生成特征放在buffer1中
3)搜索指纹数据

代码编写

串口初始化

由于AS608使用的是串口驱动,所以第一步需要初始化串口和串口中断;
我用的是串口二

/************************AS608.h***************************/
#ifndef __AS608__H__
#define __AS608__H__
#define USART2_MAX_RECV_LEN		400					//最大接收缓存字节数
extern u8  USART2_RX_BUF[USART2_MAX_RECV_LEN];
extern int counts ;
#define AS608USART	USART2
#endif
/**************************AS608.c**************************/
//串口二初始化
void AS608_Init(u32 bound)
	{  
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(LORA_GPIO_USART_CLOCK, ENABLE);	
	RCC_APB1PeriphClockCmd(LORA_USART_CLOCK,ENABLE);	
  
	//USART1_TX   
	GPIO_InitStructure.GPIO_Pin = LORA_USART_TX_GPIO; //PA.9
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	
	GPIO_Init(LORA_GPIO_USART, &GPIO_InitStructure);
   
	//USART1_RX	  
	GPIO_InitStructure.GPIO_Pin = LORA_USART_RX_GPIO;//PA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(LORA_GPIO_USART, &GPIO_InitStructure);
  
	//USART 

	USART_InitStructure.USART_BaudRate = bound;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	

	USART_Init(AS608USART, &USART_InitStructure); 
	USART_ITConfig(AS608USART, USART_IT_RXNE, ENABLE);
	USART_Cmd(AS608USART, ENABLE);  

	  //Usart1 NVIC 
     NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x00;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =0x02;		
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			
	NVIC_Init(&NVIC_InitStructure);
}
//串口二中断服务函数
void USART2_IRQHandler(void)
{
	u8 res;	
	if(USART_GetITStatus(AS608USART, USART_IT_RXNE) != RESET)//接收到数据
	{	
		res =USART_ReceiveData(AS608USART);
		
		USART2_RX_BUF[counts++] = res;
	}
}

串口发送数据

将串口二初始化完之后就需要发送16进制的数据,这里需要注意一下由于32的串口数据寄存器只有1个字节 也就是每次只能发2位16进制的数据

//发送1个字节的数据
void AS608_SendData_8bit(u8 Data)
{   
	while(USART_GetFlagStatus(AS608USART, USART_FLAG_TC) == RESET);
	
	USART2->DR = Data;
}

//发送2个字节数据
void AS608_SendData_16bit(u16 Data){
	AS608_SendData_8bit(Data>>8);//发送高第八位数据
	AS608_SendData_8bit(Data&0x00FF);//发送低第八位数据
}

//发送4个字节数据
void AS608_SendData_32bit(u32 Data){
	AS608_SendData_8bit(Data>>24);
	AS608_SendData_8bit((Data>>16)&0x00FF);
	AS608_SendData_8bit((Data>>8)&0x0000FF);
	AS608_SendData_8bit(Data&0x000000FF);
}

发送指令

由于每个指令的头和指令都是一样的所以可以封装一下

void Data_Head(void){//数据头
	AS608_SendData_16bit(0xEF01);//发送EF01
}

void Address_Data(void){//数据地址
	AS608_SendData_32bit(0xFFFFFFFF);//发送0xFFFFFFFF
}
void Package_Identifer(u8 package_data){//包标志
	AS608_SendData_8bit(package_data);
}
void Package_len(u16 package_len){//包长度
	AS608_SendData_16bit(package_len);
}
void Command_Code(u8 Command_Data){//指令
	AS608_SendData_8bit(Command_Data);
}

删除flash库中指定ID号开始的N个数据

void PS_DeletChar(u16 Address){
	u16 temp;
	Data_Head();
	Address_Data();
	Package_Identifer(0x01);
	Package_len(0x0007);
	Command_Code(0x0C);
	AS608_SendData_16bit(Address); //指定的ID号
	AS608_SendData_16bit(0x0001);	//删除的个数
	temp=0x01+0x0007+0x0C+Address+0x0001;
	AS608_SendData_16bit(temp);
}

录取指纹图像

void PS_GetImage(void){
	Data_Head();
	Address_Data();
	Package_Identifer(0x01);
	Package_len(0x0003);
	Command_Code(0x01);
	AS608_SendData_16bit(0x0005);
}

生成特征 存储在缓冲区1中

void PS_GenChar_Buffer1(void){
	Data_Head();
	Address_Data();
	Package_Identifer(0x01);
	Package_len(0x0004);
	Command_Code(0x02);
	AS608_SendData_8bit(0x01);
	AS608_SendData_16bit(0x0008);
}

生成特征 存储在缓冲区2中

void PS_GenChar_Buffer1(void){
	Data_Head();
	Address_Data();
	Package_Identifer(0x01);
	Package_len(0x0004);
	Command_Code(0x02);
	AS608_SendData_8bit(0x02);
	AS608_SendData_16bit(0x0008);
}

合并指纹特征

void PS_LoadChar(u16 Address){
	u16 temp;
	Data_Head();
	Address_Data();
	Package_Identifer(0x01);
	Package_len(0x0006);
	Command_Code(0x07);
	AS608_SendData_8bit(0x02);
	AS608_SendData_16bit(Address);
	temp=0x01+0x0006+0x07+0x02+Address;
	AS608_SendData_16bit(temp);
}

将buffer1和buffer2中的模板文件存储到指定的地址中

void PS_Match(void){
	Data_Head();
	Address_Data();
	Package_Identifer(0x01);
	Package_len(0x0003);
	Command_Code(0x03);
	AS608_SendData_16bit(0x0007);
}

搜索指纹

void PS_Search(void){
	Data_Head();
	Address_Data();
	Package_Identifer(0x01);
	Package_len(0x0008);
	Command_Code(0x04);
	AS608_SendData_8bit(0x01);
	AS608_SendData_16bit(0x0000);
	AS608_SendData_16bit(0x012C);
	AS608_SendData_16bit(0x003B);
}

接受数据验证

发送指令后需要知道指令是否正常执行就需要的对返回的数据进行验证,由于返回的数据格式基本一致所以判断数据也就很简单。这里简单介绍一个的思路,判断是否删除指定缓存的思路。
通过开发板发送指令到AS608,AS608会回一个16进制的指令数据指令格式为:
在这里插入图片描述
确认码就是可以判断指令是否执行的唯一标准,判断确认码的值我们只需要找到返回数据中的包长度(0x0003)其后面的就是确认码。判断一下第一次搜索到0x070003的位置,然后指针向后移动3位就是确认码的值。

是否删除指定缓存

u8 Check_DeletChar(void){
	u8 Check[5];
	char *p=NULL;
	
	Check[0]=0x07;
	Check[1]=0x00;
	Check[2]=0x03;
	Check[3]='\0';
	p=strstr((char *)USART2_RX_BUF,(char *)Check);
	if(p!=NULL){
//	printf("%d\r\n",*(p+3));
		if(*(p+3)==0x00){
			printf("删除成功\r\n");
			Clear_Data();
			return 0;
			printf("删除成功1\r\n");
		}
		else{
			printf("删除失败\r\n");
			Clear_Data();
			return 1;
		}
	delay_us(10);
	}
	Clear_Data();
	return 1;
}

是否录入指纹数据

u8 Check_GetImage(void){
	u8 Check[5];
	char *p=NULL;
	Check[0]=0x07;
	Check[1]=0x00;
	Check[2]=0x03;
	Check[3]='\0';
	p=strstr((char *)USART2_RX_BUF,(char *)Check);
	if(p!=NULL){
//	printf("%d\r\n",*(p+1));
		if(*(p+3)==0x00){
			Clear_Data();
			printf("录入指纹成功\r\n");
			return 0;
		}
		else{
			Clear_Data();
			printf("录入指纹失败\r\n");
			return 1;
		}
	delay_us(10);
	}
	Clear_Data();
	return 1;
}

生成特征码是否成功

u8 Check_GenChar_Buffer1(void){
	u8 Check[5];
	char *p=NULL;
	Check[0]=0x07;
	Check[1]=0x00;
	Check[2]=0x03;
	Check[3]='\0';
	p=strstr((char *)USART2_RX_BUF,(char *)Check);
	if(p!=NULL){
//	printf("%d\r\n",*(p+1));
		if(*(p+3)==0x00){
			Clear_Data();
			printf("生成特征码——1成功\r\n");
			return 0;
		}else{
			Clear_Data();
			printf("生成特征码——1失败\r\n");
			return 1;
		}
	delay_us(10);
	}
	Clear_Data();
	return 1;
}

生成特征码是否成功

u8 Check_GenChar_Buffer2(void){
	u8 Check[5];
	char *p=NULL;
	Check[0]=0x07;
	Check[1]=0x00;
	Check[2]=0x03;
	Check[3]='\0';
	p=strstr((char *)USART2_RX_BUF,(char *)Check);
	if(p!=NULL){
//	printf("%d\r\n",*(p+1));
		if(*(p+3)==0x00){
			Clear_Data();
			printf("生成特征码——2成功\r\n");
			return 0;
		}else{
			Clear_Data();
			printf("生成特征码——2失败\r\n");
			return 1;
		}
	delay_us(10);
	}
	Clear_Data();
	return 1;
}

合成特征数据是否成功

u8 Check_RegModel(void){
	u8 Check[5];
	char *p=NULL;
	Check[0]=0x07;
	Check[1]=0x00;
	Check[2]=0x03;
	Check[3]='\0';
	p=strstr((char *)USART2_RX_BUF,(char *)Check);
	if(p!=NULL){
//	printf("%d\r\n",*(p+1));
		if(*(p+3)==0x00){
			Clear_Data();
			printf("合成特征成功\r\n");
			return 0;
		}else{
			Clear_Data();
			printf("合成特征失败\r\n");
			return 1;
		}
	delay_us(10);
	}
	Clear_Data();
	return 1;
}

存储数据是否成功

u8 Check_StoreChar(void){
	u8 Check[5];
	char *p=NULL;
	Check[0]=0x07;
	Check[1]=0x00;
	Check[2]=0x03;
	Check[3]='\0';
	p=strstr((char *)USART2_RX_BUF,(char *)Check);
	if(p!=NULL){
//	printf("%d\r\n",*(p+1));
		if(*(p+3)==0x00){
			Clear_Data();
			printf("存储特征成功\r\n");
			return 0;
		}else{
			Clear_Data();
			printf("存储特征失败\r\n");
			return 1;
		}
	delay_us(10);
	}
	Clear_Data();
	return 1;
}

是否搜索到指纹

u8 Check_Search(void){
	u8 Check[5];
	char *p=NULL;
	Check[0]=0x07;
	Check[1]=0x00;
	Check[2]=0x07;
	Check[3]='\0';
	p=strstr((char *)USART2_RX_BUF,(char *)Check);
	if(p!=NULL){
//	printf("%d\r\n",*(p+3));
		if(*(p+3)==0x00){
			printf("搜索成功\r\n");
			Clear_Data();
			return 0;
		}
		else{
			printf("搜索失败\r\n");
			Clear_Data();
			return 1;
		}
	delay_us(10);
	}
	Clear_Data();
	return 1;
}

指纹录入

依据驱动方式来编写代码,代码如下:

u8 Input_Fingerprint(u16 Address){
	u8 temp=1;
	//删除录入缓存区的数据
	 while(temp){
		 PS_DeletChar(Address);
		  delay_ms(1000);
		 temp=Check_DeletChar();

	 }
	 temp=1;
	 Clear_Data();
	 delay_ms(500);
	//录取指纹
	
	 while(temp){
		 PS_GetImage();
		  delay_ms(1000);
		temp= Check_GetImage();

	 }
	temp=1;
	 Clear_Data();
	 delay_ms(500);
	//生成特征放在buff1
	
	 while(temp){
		 PS_GenChar_Buffer1();
		 delay_ms(1000);
		temp= Check_GenChar_Buffer1();

	 }
	temp=1;
	 Clear_Data();
	 delay_ms(500);
	//再次录取

	 while(temp){
		 PS_GetImage();
		  delay_ms(1000);
		temp=Check_GetImage();

	 }
	temp=1;
	 Clear_Data();
	 delay_ms(500);
	//生成特征放在buff2
	
	 while(temp){
		 PS_GenChar_Buffer2();
		  delay_ms(1000);
		temp=Check_GenChar_Buffer2();

	 }
	temp=1;
	 Clear_Data();
	  delay_ms(500);
	//合并特征模板
	 while(temp){
		 PS_RegModel();
		  delay_ms(1000);
		temp=Check_RegModel();

	 }
	temp=1;
	 Clear_Data();
	  delay_ms(500);
	//储存模板
	
	 while(temp){
		 PS_StoreChar(Address);
		  delay_ms(1000);
		temp=Check_StoreChar();

	 }
	return temp;
}

指纹搜索

u8 Search_FingerMat(void){
	u8 temp=1;
	TWO:
	//录取指纹
	while(temp){
		 PS_GetImage();
		  delay_ms(500);
		 temp=Check_GetImage();

	 }
	 temp=1;
	 Clear_Data();
	 delay_ms(500);
	//生成特征
	 while(temp){
		 PS_GenChar_Buffer1();
		  delay_ms(500);
		 temp=Check_GenChar_Buffer1();

	 }
	 temp=1;
	 Clear_Data();
	 delay_ms(500);
	//搜索指纹数据
	 while(temp){
		 PS_Search();
		  delay_ms(500);
		 temp=Check_Search();
		 if(temp){
			 printf("换个手指试试\r\n");
			 delay_ms(1000);
			 delay_ms(1000);
			goto TWO;
		 }

	 }
	 Clear_Data();
	 delay_ms(500);
	return 0;
}

参考工程链接
群:985432073
有疑问加群、评论或私信!

版权声明:本文为CSDN博主「嘿嘿の」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43460106/article/details/121784021

生成海报
点赞 0

嘿嘿の

我还没有学会写个人说明!

暂无评论

相关推荐

毕设-基于LoRa的智能农业大棚(一)

任务目标 实现功能: (1)能够实时检测显示土壤湿度,当需要浇水的时候自动打开灌溉系统,土壤湿度满足要求后,关闭灌溉系统; (2&

基于STM32的室内环境监测系统

设计简介: 本设计是基于单片机的室内环境监测器,主要实现以下功能: 可实现LCD1602显示环境数据实时监测一氧化碳、甲烷、烟雾值空气质量大于各自限值报警,并通过TTS报警 标签&#x

基于stm32f407的示波器

一.设计要求 二.整体思路 硬件部分主要负责电压的缩放以及垂直灵敏度的控制,因为stm32的大部分引脚最高输入电压为3.3v,而要求的电压需要50v,需要进行电压缩放。 软件部分主要负责方波的实现&#x

实验一 stm32F407VETx点亮流水灯

二、设计指标 使电路板上的8个LED轮流点亮,并按键控制点亮速度。 三、操作 1、CubeMX操作 1.1依据开发板LED引脚设置CubeMX中8个LED的引脚为GPIO_Output模式, 2、按键设置