基于stm32f103支持远程开锁的指纹密码锁设计

1.选型:

1.单片机:stm32f103c8t6

2.指纹模块:AS608

3.按键模块:3x4矩阵按键

4.网络模块:NB-G122mini

5.显示模块:LCD1602

6.锁:塑料钛丝锁DC3V

7.蜂鸣器:有源一体电磁式蜂鸣器0905

8.控制锁:继电器

9.调节背光:电阻(4.7k)

10.服务端:java

11.手机端:Android

2.单片机需要的资源:

两个串口(AS608和NB-G122mini)

3+4=7个IO口(按键)

8+2=10个IO口(LCD1602数据8位,使能,命令/数据)

1个USB口(AS608指纹录入)

两个IO口(蜂鸣器)

1个IO口(AS608感应信号)

1个IO口(继电器开关)

3.器件原理

1.LCD1602:

1.引脚:

8根数据口,3根控制口(E(使能),R/W(读/写),R/S(数据/命令)),背光电源,芯片电源,液晶显示偏压信号(4.7k电阻下拉)

2.时序图

3.lcd1602.h:

#ifndef __LCD1602_H
#define __LCD1602_H
#include "stm32f103xb.h"
//命令/数据
#define RS GPIOB 
#define RS_BIT GPIO_PIN_1
//读写
#define E GPIOB 
#define E_BIT GPIO_PIN_0 
//Data0
#define D0 GPIOA  
#define D0_BIT GPIO_PIN_7 
//Data1
#define D1 GPIOA
#define D1_BIT GPIO_PIN_6 
//Data2
#define D2 GPIOA  
#define D2_BIT GPIO_PIN_5 
//Data3
#define D3 GPIOA  
#define D3_BIT GPIO_PIN_4 
//Data4
#define D4 GPIOA  
#define D4_BIT GPIO_PIN_3 
//Data5
#define D5 GPIOA  
#define D5_BIT GPIO_PIN_2  
//Data6
#define D6 GPIOA 
#define D6_BIT GPIO_PIN_1 
//Data7
#define D7 GPIOA  
#define D7_BIT GPIO_PIN_0  
extern const char show_1[];
extern const char err[];
extern void LCD1602_Init();
extern void LCD1602_ShowChar(unsigned char xpos,unsigned char ypos,char xsz);
extern void LCD1602_Show_String(unsigned char l,const char *buf);
extern void LCD1602_Show_Clear_Line(unsigned char l);
#endif

4.lcd1602.c:

#include "lcd1602.h"
#include "gpio.h"
#include "string.h"
const char show_1[]=" Welcome home !";
const char err[]="Please try !";
//=========写数据部分
//指令一般在配置时使用
void Data_Cpy(unsigned char Data)
{
	HAL_GPIO_WritePin(D0, D0_BIT, Data&0x01);	
	HAL_GPIO_WritePin(D1, D1_BIT, (Data&0x02)>>1);	
	HAL_GPIO_WritePin(D2, D2_BIT, (Data&0x04)>>2);	
	HAL_GPIO_WritePin(D3, D3_BIT, (Data&0x08)>>3);	
	HAL_GPIO_WritePin(D4, D4_BIT, (Data&0x10)>>4);	
	HAL_GPIO_WritePin(D5, D5_BIT, (Data&0x20)>>5);	
	HAL_GPIO_WritePin(D6, D6_BIT, (Data&0x40)>>6);	
	HAL_GPIO_WritePin(D7, D7_BIT, (Data&0x80)>>7);	
}
void LCD1602_write_cmd(unsigned char Data)  //写命令
{

	HAL_GPIO_WritePin(RS, RS_BIT, GPIO_PIN_RESET);	
	Data_Cpy(Data);
	HAL_Delay(1);		//此处需要延时给LCD处理时间
	HAL_GPIO_WritePin(E, E_BIT, GPIO_PIN_SET);	
	HAL_Delay(10);		//此处需要延时给LCD处理时间 
	HAL_GPIO_WritePin(E, E_BIT, GPIO_PIN_RESET);
}

void LCD1602_write_data(unsigned char Data)	//写数据
{
	HAL_GPIO_WritePin(RS, RS_BIT, GPIO_PIN_SET);	
	Data_Cpy(Data);
	HAL_Delay(1);		//此处需要延时给LCD处理时间
	HAL_GPIO_WritePin(E, E_BIT, GPIO_PIN_SET);	
	HAL_Delay(10);		//此处需要延时给LCD处理时间 
	HAL_GPIO_WritePin(E, E_BIT, GPIO_PIN_RESET);
}
void LCD1602_Show_Clear_Line(unsigned char l)
{
	l%=2;
	unsigned char i=0;
	for(i=0;i<16;i++)
	LCD1602_ShowChar(i,l,0x20);
}
void LCD1602_ShowChar(unsigned char xpos,unsigned char ypos,char xsz)	
{
	ypos%=2;
	if(ypos==0)
	{
		LCD1602_write_cmd(0x80+xpos);
	}
	else
	{
		LCD1602_write_cmd(0x80+0x40+xpos);
	}
	LCD1602_write_data(xsz);
}
void LCD1602_Show_String(unsigned char l,const char *buf)
{
	unsigned char i=0;
	for(i=0;i<strlen(buf);i++)
	{
		LCD1602_ShowChar(i,l%2,buf[i]);
	}
}
void LCD1602_Init()
{
	LCD1602_write_cmd( 0x38 );      //显示模式设置
	HAL_Delay( 5 );
	LCD1602_write_cmd( 0x0c );      //显示开及光标设置
	HAL_Delay( 5 );
	LCD1602_write_cmd( 0x06 );      //显示光标移动位置
	HAL_Delay( 5 );
	LCD1602_write_cmd( 0x01 );      //显示清屏
	HAL_Delay( 5 );	
	LCD1602_Show_String(0,show_1);
}

2.按键模块:

1.引脚:

7根IO口

2.原理图

1.

将1,2,3设置为IO输入,4,5,6,7设置为IO输出,当有按键被按下,我们知道在哪一行,此时将1,2,3设置为输出,4,5,6,7设置为输入,即可知道是哪一列,通过映射即可知道按的是那个数字。

2.gpio.h

#ifndef __GPIO_H__
#define __GPIO_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* USER CODE BEGIN Private defines */
#define Key_Y_0_BIT GPIO_PIN_3
#define Key_Y_1_BIT GPIO_PIN_4
#define Key_Y_2_BIT GPIO_PIN_5
#define Key_Y_3_BIT GPIO_PIN_6
#define Key_X_0_BIT GPIO_PIN_7
#define Key_X_1_BIT GPIO_PIN_8
#define Key_X_2_BIT GPIO_PIN_9
extern unsigned char key;//按钮坐标
extern unsigned char key_buf[6];//按钮缓冲
extern unsigned char key_buf_len;//缓冲长度
/* USER CODE END Private defines */

void MX_GPIO_Init(void);

/* USER CODE BEGIN Prototypes */
void SCAN_H_INIT(void);
void SCAN_L_INIT(void);
void Scanf_Key();
/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif
#endif /*__ GPIO_H__ */


2.gpio.c

#include "gpio.h"

/* USER CODE BEGIN 0 */
unsigned char key_buf[6]={'\0'};
unsigned char key_buf_len=0;
/* USER CODE END 0 */

/*----------------------------------------------------------------------------*/
/* Configure GPIO                                                             */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
unsigned char key=0xff;
/* USER CODE END 1 */

/** Configure pins as
        * Analog
        * Input
        * Output
        * EVENT_OUT
        * EXTI
*/
void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
                          |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_15, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9, GPIO_PIN_SET);

  /*Configure GPIO pins : PC13 PC14 */
  GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PC15 */
  GPIO_InitStruct.Pin = GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pins : PA0 PA1 PA2 PA3
                           PA4 PA5 PA6 PA7 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
                          |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PB0 PB1 PB15 PB7
                           PB8 PB9 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_15|GPIO_PIN_7
                          |GPIO_PIN_8|GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pins : PB3 PB4 PB5 PB6 */
  GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

/* USER CODE BEGIN 2 */
void SCAN_H_INIT(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
	
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, Key_X_0_BIT|Key_X_1_BIT|Key_X_2_BIT, GPIO_PIN_SET);

  /*Configure GPIO pins : PB7 PB8 PB9 */
  GPIO_InitStruct.Pin = Key_X_0_BIT|Key_X_1_BIT|Key_X_2_BIT;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pins : PB3 PB4 PB5 PB6 */
  GPIO_InitStruct.Pin = Key_Y_0_BIT|Key_Y_1_BIT|Key_Y_2_BIT|Key_Y_3_BIT;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}
void SCAN_L_INIT(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
	
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, Key_Y_0_BIT|Key_Y_1_BIT|Key_Y_2_BIT|Key_Y_3_BIT, GPIO_PIN_SET);

	/*Configure GPIO pins : PB3 PB4 PB5 PB6 */
  GPIO_InitStruct.Pin = Key_Y_0_BIT|Key_Y_1_BIT|Key_Y_2_BIT|Key_Y_3_BIT;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pins : PB7 PB8 PB9 */
  GPIO_InitStruct.Pin = Key_X_0_BIT|Key_X_1_BIT|Key_X_2_BIT;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
	
}

void Scanf_Key()
{
	if(HAL_GPIO_ReadPin(GPIOB,Key_Y_0_BIT))
	{
		HAL_Delay(10);
		SCAN_L_INIT();
		if(HAL_GPIO_ReadPin(GPIOB,Key_X_0_BIT))
		{
			key='1';
		}
		if(HAL_GPIO_ReadPin(GPIOB,Key_X_1_BIT))
		{
			key='2';
		}
		if(HAL_GPIO_ReadPin(GPIOB,Key_X_2_BIT))
		{
			key='3';		
		}	
		SCAN_H_INIT();
		return;
	}
	if(HAL_GPIO_ReadPin(GPIOB,Key_Y_1_BIT))
	{
		HAL_Delay(10);
		SCAN_L_INIT();
		if(HAL_GPIO_ReadPin(GPIOB,Key_X_0_BIT))
		{
			key='4';
		}
		if(HAL_GPIO_ReadPin(GPIOB,Key_X_1_BIT))
		{
			key='5';
		}
		if(HAL_GPIO_ReadPin(GPIOB,Key_X_2_BIT))
		{
			key='6';		
		}	
     SCAN_H_INIT();		
		return;
	}
	if(HAL_GPIO_ReadPin(GPIOB,Key_Y_2_BIT))
	{
		HAL_Delay(10);
		SCAN_L_INIT();
		if(HAL_GPIO_ReadPin(GPIOB,Key_X_0_BIT))
		{
			key='7';
		}
		if(HAL_GPIO_ReadPin(GPIOB,Key_X_1_BIT))
		{
			key='8';
		}
		if(HAL_GPIO_ReadPin(GPIOB,Key_X_2_BIT))
		{
			key='9';		
		}	
		SCAN_H_INIT();
		return;
	}
	if(HAL_GPIO_ReadPin(GPIOB,Key_Y_3_BIT))
	{
		HAL_Delay(10);
		SCAN_L_INIT();
		if(HAL_GPIO_ReadPin(GPIOB,Key_X_0_BIT))
		{
			key='*';
		}
		if(HAL_GPIO_ReadPin(GPIOB,Key_X_1_BIT))
		{
			key='0';
		}
		if(HAL_GPIO_ReadPin(GPIOB,Key_X_2_BIT))
		{
			key='#';		
		}	
		SCAN_H_INIT();
		return;
	}
	
}

3.NB模块:

1.引脚:

电源口,串口

2.原理图

此处主要是AT指令

unsigned char AT[]="AT\r\n";//AT指令,唤醒NB
unsigned char ECRST[]="AT+ECRST\r\n";//复位
unsigned char CREG[]="AT+CREG=1\r\n";
unsigned char CFUN[]="AT+CFUN=1\r\n";//运行模式
unsigned char CTM2MREG[]="AT+CTM2MREG\r\n"; 
unsigned char SKTSTATUS[]="AT+SKTSTATUS=?\r\n";
unsigned char SKTCREATE[]="AT+SKTCREATE=1,1,6\r\n";//创建套接
unsigned char SKTCONNECT[]="AT+SKTCONNECT=1,112.74.172.135,6666\r\n";//第一个代表Ipv4,第二个ip地址,第三个端口号
unsigned char OPENOK[]="AT+SKTSEND=1,1,30\r\n";//打开成功
unsigned char PASSERR[]="AT+SKTSEND=1,1,31\r\n";//密码错误
unsigned char AS608ERR[]="AT+SKTSEND=1,1,32\r\n";//指纹错误

3.main.h

#ifndef __MAIN_H
#define __MAIN_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
extern unsigned char revb1[1];
extern unsigned char buf1[64];
extern unsigned char revb3[1];
extern unsigned char buf3[64];
extern unsigned char isrev1;
extern unsigned char isrev3;
/* USER CODE END ET */

/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */

/* USER CODE END EC */

/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */

/* USER CODE END EM */

/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);

/* USER CODE BEGIN EFP */

/* USER CODE END EFP */

/* Private defines -----------------------------------------------------------*/

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H */

4. main.c

#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
#include "lcd1602.h"
#include "as608.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
unsigned char revb1[1];//指纹串口数据接收
unsigned char buf1[64];//指纹的缓冲数据
unsigned char revb3[1];//NB模组串口接收
unsigned char buf3[64]={0};//NB模组的缓冲数据
unsigned char isrev1=0;//指纹是否有数据接收
unsigned char isrev3=0;//NB是否有数据接收
unsigned char AT[]="AT\r\n";//AT指令,唤醒NB
unsigned char ECRST[]="AT+ECRST\r\n";//复位
unsigned char CREG[]="AT+CREG=1\r\n";
unsigned char CFUN[]="AT+CFUN=1\r\n";//运行模式
unsigned char CTM2MREG[]="AT+CTM2MREG\r\n"; 
unsigned char SKTSTATUS[]="AT+SKTSTATUS=?\r\n";
unsigned char SKTCREATE[]="AT+SKTCREATE=1,1,6\r\n";//创建套接
unsigned char SKTCONNECT[]="AT+SKTCONNECT=1,112.74.172.135,6666\r\n";//第一个代表Ipv4,第二个ip地址,第三个端口号
unsigned char OPENOK[]="AT+SKTSEND=1,1,30\r\n";//打开成功
unsigned char PASSERR[]="AT+SKTSEND=1,1,31\r\n";//密码错误
unsigned char AS608ERR[]="AT+SKTSEND=1,1,32\r\n";//指纹错误
unsigned short ValidN=0;	
int Get_Data = 0;
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart==&huart1)
	{
		static unsigned char g=0,len=0;
		if(g<9)
		{
			buf1[g++]=revb1[0];
		}
		else 
		{
			len=buf1[7]*256+buf1[8];
			if(buf1[0]==0xEF&&buf1[1]==0x01)
			{
				buf1[g++]=revb1[0];			
				if(g==len+9)
				{
					isrev1=1;
					g=0;
				}

			}
			else 
			{
				g=0;				
			}
		}
		HAL_UART_Receive_IT(&huart1,revb1,1);		
	}
	if(huart==&huart3)//NB有数据来
	{
		static unsigned char t=0;
		if(revb3[0]!='\n')//NB没有接收完数据
	  {
		  buf3[t++]=revb3[0];
	  }
	  else//接收到完整数据
	  {
	  	buf3[t]='\0';//便于字符串的操作
			isrev3=1;
	  	t=0;//初始化长度
	  }  
    HAL_UART_Receive_IT(&huart3,revb3,1);		
	}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	
}
int press_FR(void)
{
	SearchResult seach;
	uint8_t ensure;
	ensure = PS_GetImage();
	if (ensure == 0x00) 
	{
		ensure = PS_GenChar(CharBuffer1);
		if (ensure == 0x00) 
		{
			ensure = PS_Search(CharBuffer1, 0, 300, &seach);
			if (ensure == 0x00)	
				return seach.pageID; 
			else if (ensure == 9)
				return -2;
		}
			
	}
	return -1;
}
void open()
{
	LCD1602_Show_String(1,"Please Wait!");
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_SET);
	HAL_Delay(1000);
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_RESET);
	LCD1602_Show_String(1,"Open Success !");
	HAL_Delay(1000);
	key_buf_len=0;
	LCD1602_Init();
}
void scan_run()
{
	Scanf_Key();
	if(key!=0xff)
	{
		if(key=='*')
		{
			key_buf_len=key_buf_len>0?key_buf_len-1:0;
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
			LCD1602_ShowChar(key_buf_len,1,0x20);
			HAL_Delay(200);
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
		}
		else if(key=='#')
		{
			key_buf_len=0;
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
			LCD1602_Show_Clear_Line(1);
			HAL_Delay(200);
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);		
 		}
		else
		{
	  	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
	  	key_buf[key_buf_len]=key;
		  LCD1602_ShowChar(key_buf_len,1,key);
		  HAL_Delay(200);
		  HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
		  LCD1602_ShowChar(key_buf_len,1,'*');
		  key_buf_len++;
		  if(key_buf_len==6)
		  {
			  if(strstr((const char *)key_buf,"123456"))
			  {
          open();					
			  }
			else
			{
				key_buf_len=0;
			  HAL_UART_Transmit_IT(&huart3,PASSERR,strlen((char *)PASSERR));
				LCD1602_Show_String(1,err);
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET);
				HAL_Delay(1000);
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_SET);
				LCD1602_Init();
			}			
		}
	}
		htim2.Instance->CNT=0;//定时器计数器清空
		key=0xff;
	}	
	if(timeout==1)
	{
		key_buf_len=0;
		LCD1602_Init();
		timeout=0;
	}
}
void as608_run()
{
  if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_15)==1) 
		{
			Get_Data = press_FR();									  
			if (Get_Data >= 0)										  
			{
				LCD1602_Show_Clear_Line(1);
				LCD1602_Show_String(1,"Get");
				open();
			}
			else if(Get_Data == -2)//指纹识别错误
			{
				LCD1602_Show_String(1,err);
				HAL_UART_Transmit_IT(&huart3,AS608ERR,strlen((char *)AS608ERR));
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET);
				HAL_Delay(1000);
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_SET);
				LCD1602_Init();			
			}			
		}
}
void nb_run()
{
	if(isrev3)//接收到数据
	{
		unsigned char i=0;
		/*
		for(i=0;i<16;i++)
		{
			LCD1602_ShowChar(i,0,revb3[i]);
		}	
		for(i=0;i<16;i++)
		{
      LCD1602_ShowChar(i,1,revb3[i+16]);
		}*/
		if(strstr((char *)revb3,"SKTERR")!=NULL||
			strstr((char *)revb3,"NO FIND CLIENT")!=NULL||
			strstr((char *)revb3,"CONNECT FAILED")!=NULL||
			strstr((char *)revb3,"107")!=NULL||
			strstr((char *)revb3,"104")
			)//异常重连
		{
			HAL_Delay(100);
			HAL_UART_Transmit_IT(&huart3,SKTCREATE,strlen((char *)SKTCREATE));//创建套接字
			HAL_Delay(100);
	    HAL_UART_Transmit_IT(&huart3,SKTCONNECT,strlen((char *)SKTCONNECT));//连接服务器		
			HAL_Delay(100);
	   // HAL_UART_Transmit_IT(&huart3,SKTSTATUS,strlen((char *)SKTSTATUS));//状态			
		}
		if(strstr((char *)revb3,"SKTRECV")!=NULL)//接收到数据
		{
		//	HAL_Delay(1000);
			unsigned char len = (unsigned char )revb3[13]-48;//获取数据的长度
			for(i=0;i<len;i++)
			{				
				//LCD1602_ShowChar(i,0,revb3[2*i+17]);//数据显示
				revb3[i]=revb3[2*i+17];
			}
			revb3[i]='\0';
			if(strstr((char *)revb3,"1111111"))
			{
				open();
				HAL_UART_Transmit_IT(&huart3,OPENOK,strlen((char *)OPENOK));//发送打开成功
			}
		}
		for(i=0;i<64;i++)
		{
      revb3[i]=0x00;
		}
		isrev3=0;
	}	
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_USART3_UART_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
  LCD1602_Init();
	MX_TIM2_Init();
  HAL_TIM_Base_Start_IT(&htim2);
	HAL_UART_Receive_IT(&huart1,revb1,1);	
	while (PS_HandShake(&AS608Addr))						
	{
		HAL_Delay(500);
	}
	LCD1602_Show_Clear_Line(0);
	LCD1602_Show_String(0,"AS608 OK !");
	LCD1602_Show_Clear_Line(0);
	LCD1602_Show_String(0,"Wait...");
	HAL_UART_Transmit_IT(&huart3,ECRST,strlen((char *)ECRST));//重启模块
	HAL_Delay(100);//延时100ms
	while(strstr((char *)buf3,"CREG: 6")==NULL)
	{
		HAL_UART_Receive(&huart3,buf3,10,5000);
  	HAL_Delay(100);//延时100ms		
	}
	HAL_UART_Transmit_IT(&huart3,AT,strlen((char *)AT));//发AT唤醒4g模块
	HAL_Delay(100);
	HAL_UART_Transmit_IT(&huart3,CFUN,strlen((char *)CFUN));//网络进入运行模式 
	HAL_Delay(100);
	HAL_UART_Transmit_IT(&huart3,SKTCREATE,strlen((char *)SKTCREATE));//创建套
	HAL_Delay(100);
	HAL_UART_Transmit_IT(&huart3,SKTCONNECT,strlen((char *)SKTCONNECT));//连接服务
	HAL_Delay(100);
  while(strstr((char *)buf3,"OK")==NULL)
	{
		HAL_UART_Receive(&huart3,buf3,10,5000);
  	HAL_Delay(100);//延时100ms	
	}		
	LCD1602_Show_String(0,"Init OK !");
  HAL_Delay(1000);//延时1s		
	LCD1602_Show_String(0,show_1); 	
	HAL_UART_Receive_IT(&huart3,revb3,1);	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
while (1)
{
	scan_run();//按键扫描
	nb_run();
	as608_run();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
}
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
	 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

3.AS608模块:

1.引脚:

1个串口,1个usb口,一个感应信号IO口

2.原理图

1.

as608主要是通过串口通信,此次是通过usb操作指纹,串口用于处理指纹识别。

2.as608.h

	#ifndef __AS608_H
	#define __AS608_H
	#include <stdio.h>
  #include "stm32f1xx_hal.h"
	#define CharBuffer1 0x01
	#define CharBuffer2 0x02

	extern unsigned int AS608Addr;

	typedef struct  
	{
		unsigned short pageID;
		unsigned short mathscore;
	}SearchResult;

	typedef struct
	{
		unsigned short PS_max;
		unsigned char  PS_level;
		unsigned int PS_addr;
		unsigned char  PS_size;
		unsigned char  PS_N;
	}SysPara;

extern	void PS_StaGPIO_Init(void);
		
extern	unsigned char PS_GetImage(void); 
	 
extern	unsigned char PS_GenChar(unsigned char BufferID);
extern	unsigned char PS_Match(void);

extern	unsigned char PS_Search(unsigned char BufferID,unsigned short StartPage,unsigned short PageNum,SearchResult *p);
	 
extern	unsigned char PS_RegModel(void);
	 
extern	unsigned char PS_StoreChar(unsigned char BufferID,unsigned short PageID);

extern	unsigned char PS_DeletChar(unsigned short PageID,unsigned short N);

extern	unsigned char PS_Empty(void);
extern	unsigned char PS_WriteReg(unsigned char RegNum,unsigned char DATA);
	 
extern	unsigned char PS_ReadSysPara(SysPara *p); 

extern	unsigned char PS_SetAddr(unsigned int addr);  

extern	unsigned char PS_WriteNotepad(unsigned char NotePageNum,unsigned char *content);

extern	unsigned char PS_ReadNotepad(unsigned char NotePageNum,unsigned char *note);

extern	unsigned char PS_HighSpeedSearch(unsigned char BufferID,unsigned short StartPage,unsigned short PageNum,SearchResult *p);
		
extern	unsigned char PS_ValidTempleteNum(unsigned short *ValidN);

extern	unsigned char PS_HandShake(unsigned int *PS_Addr); 

	const char *EnsureMessage(unsigned char ensure);

	#endif


2.as608.c

#include <string.h>
#include "as608.h"
//#include "stm32f10x.h"
#include "stm32f1xx_hal.h"
#include "usart.h"
#include "main.h"
unsigned int AS608Addr = 0XFFFFFFFF; //默认
/*
//初始化PA6为下拉输入		    
//读摸出感应状态(触摸感应时输出高电平信号)
void PS_StaGPIO_Init(void)
{   
	RCC->APB1ENR |= 1<<2;//使能PORTA时钟
	GPIOA->CRL &=0XF0FFFFFF;//复位PA6
	GPIOA->CRL |=0X08000000;//输入模式,默认下拉
	GPIOA->ODR &=~(1<<6);//下拉
}*/
//串口发送一个字节
static void MYUSART_SendData(unsigned char data)
{
	while((USART1->SR&0X40)==0); 
	USART1->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(unsigned char flag)
{
	MYUSART_SendData(flag);
}
//发送包长度
static void SendLength(int length)
{
	MYUSART_SendData(length>>8);
	MYUSART_SendData(length);
}
//发送指令码
static void Sendcmd(unsigned char cmd)
{
	MYUSART_SendData(cmd);
}
//发送校验和
static void SendCheck(unsigned short check)
{
	MYUSART_SendData(check>>8);
	MYUSART_SendData(check);
}
//判断中断接收的数组有没有应答包
//waittime为等待中断接收数据的时间(单位1ms)
//返回值:数据包首地址
static unsigned char *JudgeStr(unsigned short waittime)
{
	char *data;
	unsigned char 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';
	isrev1=0;
	while(--waittime)
	{
		HAL_Delay(1);
		if(isrev1)//接收到一次数据
		{
			isrev1=0;
			data=strstr((const char*)buf1,(const char*)str);
			if(data)
				return (unsigned char*)data;	
		}
	}
	return 0;
}
//录入图像 PS_GetImage
//功能:探测手指,探测到后录入指纹图像存于ImageBuffer。 
//模块返回确认字
unsigned char PS_GetImage(void)
{
  unsigned short temp;
  unsigned char  ensure;
	unsigned char  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包标识
	SendLength(0x03);
	Sendcmd(0x01);
  temp =  0x01+0x03+0x01;
	SendCheck(temp);
	data=JudgeStr(2000);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;
	return ensure;
}
//生成特征 PS_GenChar
//功能:将ImageBuffer中的原始图像生成指纹特征文件存于CharBuffer1或CharBuffer2			 
//参数:BufferID --> charBuffer1:0x01	charBuffer1:0x02												
//模块返回确认字
unsigned char PS_GenChar(unsigned char BufferID)
{
	unsigned short temp;
  unsigned char  ensure;
	unsigned char  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包标识
	SendLength(0x04);
	Sendcmd(0x02);
	MYUSART_SendData(BufferID);
	temp = 0x01+0x04+0x02+BufferID;
	SendCheck(temp);
	data=JudgeStr(2000);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;
	return ensure;
}
//精确比对两枚指纹特征 PS_Match
//功能:精确比对CharBuffer1 与CharBuffer2 中的特征文件 
//模块返回确认字
unsigned char PS_Match(void)
{
	unsigned short temp;
  unsigned char  ensure;
	unsigned char  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包标识
	SendLength(0x03);
	Sendcmd(0x03);
	temp = 0x01+0x03+0x03;
	SendCheck(temp);
	data=JudgeStr(2000);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;
	return ensure;
}
//搜索指纹 PS_Search
//功能:以CharBuffer1或CharBuffer2中的特征文件搜索整个或部分指纹库.若搜索到,则返回页码。			
//参数:  BufferID @ref CharBuffer1	CharBuffer2
//说明:  模块返回确认字,页码(相配指纹模板)
unsigned char PS_Search(unsigned char BufferID,unsigned short StartPage,unsigned short PageNum,SearchResult *p)
{
	unsigned short temp;
  unsigned char  ensure;
	unsigned char  *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)+(unsigned char)StartPage
	+(PageNum>>8)+(unsigned char)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中的特征文件合并生成 模板,结果存于CharBuffer1与CharBuffer2	
//说明:  模块返回确认字
unsigned char PS_RegModel(void)
{
	unsigned short temp;
  unsigned char  ensure;
	unsigned char  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包标识
	SendLength(0x03);
	Sendcmd(0x05);
	temp = 0x01+0x03+0x05;
	SendCheck(temp);
	data=JudgeStr(2000);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;
	return ensure;		
}
//储存模板 PS_StoreChar
//功能:将 CharBuffer1 或 CharBuffer2 中的模板文件存到 PageID 号flash数据库位置。			
//参数:  BufferID @ref charBuffer1:0x01	charBuffer1:0x02
//       PageID(指纹库位置号)
//说明:  模块返回确认字
unsigned char PS_StoreChar(unsigned char BufferID,unsigned short PageID)
{
	unsigned short temp;
  unsigned char  ensure;
	unsigned char  *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)+(unsigned char)PageID;
	SendCheck(temp);
	data=JudgeStr(2000);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;
	return ensure;	
}
//删除模板 PS_DeletChar
//功能:  删除flash数据库中指定ID号开始的N个指纹模板
//参数:  PageID(指纹库模板号),N删除的模板个数。
//说明:  模块返回确认字
unsigned char PS_DeletChar(unsigned short PageID,unsigned short N)
{
	unsigned short temp;
  unsigned char  ensure;
	unsigned char  *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)+(unsigned char)PageID
	+(N>>8)+(unsigned char)N;
	SendCheck(temp);
	data=JudgeStr(2000);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;
	return ensure;
}
//清空指纹库 PS_Empty
//功能:  删除flash数据库中所有指纹模板
//参数:  无
//说明:  模块返回确认字
unsigned char PS_Empty(void)
{
	unsigned short temp;
  unsigned char  ensure;
	unsigned char  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包标识
	SendLength(0x03);
	Sendcmd(0x0D);
	temp = 0x01+0x03+0x0D;
	SendCheck(temp);
	data=JudgeStr(2000);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;
	return ensure;
}
//写系统寄存器 PS_WriteReg
//功能:  写模块寄存器
//参数:  寄存器序号RegNum:4\5\6
//说明:  模块返回确认字
unsigned char PS_WriteReg(unsigned char RegNum,unsigned char DATA)
{
	unsigned short temp;
  unsigned char  ensure;
	unsigned char  *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];
	else
		ensure=0xff;
	if(ensure==0)
		printf("\r\n设置参数成功!");
	else
		printf("\r\n%s",EnsureMessage(ensure));
	return ensure;
}
//读系统基本参数 PS_ReadSysPara
//功能:  读取模块的基本参数(波特率,包大小等)
//参数:  无
//说明:  模块返回确认字 + 基本参数(16bytes)
unsigned char PS_ReadSysPara(SysPara *p)
{
	unsigned short temp;
  unsigned char  ensure;
	unsigned char  *data;
	SendHead();
	SendAddr();
	SendFlag(0x01);//命令包标识
	SendLength(0x03);
	Sendcmd(0x0F);
	temp = 0x01+0x03+0x0F;
	SendCheck(temp);
	data=JudgeStr(1000);
	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("\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
//说明:  模块返回确认字
unsigned char PS_SetAddr(unsigned int PS_addr)
{
	unsigned short temp;
  unsigned char  ensure;
	unsigned char  *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
	+(unsigned char)(PS_addr>>24)+(unsigned char)(PS_addr>>16)
	+(unsigned char)(PS_addr>>8) +(unsigned char)PS_addr;				
	SendCheck(temp);
	AS608Addr=PS_addr;//发送完指令,更换地址
  data=JudgeStr(2000);
	if(data)
		ensure=data[9];
	else
		ensure=0xff;	
		AS608Addr = PS_addr;
	if(ensure==0x00)
		printf("\r\n设置地址成功!");
	else
		printf("\r\n%s",EnsureMessage(ensure));
	return ensure;
}
//功能: 模块内部为用户开辟了256bytes的FLASH空间用于存用户记事本,
//	该记事本逻辑上被分成 16 个页。
//参数:  NotePageNum(0~15),Byte32(要写入内容,32个字节)
//说明:  模块返回确认字
unsigned char PS_WriteNotepad(unsigned char NotePageNum,unsigned char *Byte32)
{
	unsigned short temp;
  unsigned char  ensure,i;
	unsigned char  *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];
	else
		ensure=0xff;
	return ensure;
}
//读记事PS_ReadNotepad
//功能:  读取FLASH用户区的128bytes数据
//参数:  NotePageNum(0~15)
//说明:  模块返回确认字+用户信息
unsigned char PS_ReadNotepad(unsigned char NotePageNum,unsigned char *Byte32)
{
	unsigned short temp;
  unsigned char  ensure,i;
	unsigned char  *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];
		}
	}
	else
		ensure=0xff;
	return ensure;
}
//高速搜索PS_HighSpeedSearch
//功能:以 CharBuffer1或CharBuffer2中的特征文件高速搜索整个或部分指纹库。
//		  若搜索到,则返回页码,该指令对于的确存在于指纹库中 ,且登录时质量
//		  很好的指纹,会很快给出搜索结果。
//参数:  BufferID, StartPage(起始页),PageNum(页数)
//说明:  模块返回确认字+页码(相配指纹模板)
unsigned char PS_HighSpeedSearch(unsigned char BufferID,unsigned short StartPage,unsigned short PageNum,SearchResult *p)
{
	unsigned short temp;
  unsigned char  ensure;
	unsigned char  *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)+(unsigned char)StartPage
	+(PageNum>>8)+(unsigned char)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_ValidTempleteNum
//功能:读有效模板个数
//参数: 无
//说明: 模块返回确认字+有效模板个数ValidN
unsigned char PS_ValidTempleteNum(unsigned short *ValidN)
{
	unsigned short temp;
  unsigned char  ensure;
	unsigned char  *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];
	}		
	else
		ensure=0xff;
	
	if(ensure==0x00)
	{
		printf("\r\n有效指纹个数=%d",(data[10]<<8)+data[11]);
	}
	else
		printf("\r\n%s",EnsureMessage(ensure));
	return ensure;
}
//与AS608握手 PS_HandShake
//参数: PS_Addr地址指针
//说明: 模块返新地址(正确地址)	
unsigned char PS_HandShake(unsigned int *PS_Addr)
{	
	SendHead();
	SendAddr();
	MYUSART_SendData(0X01);
	MYUSART_SendData(0X00);
	MYUSART_SendData(0X00);
	HAL_Delay(200);
	if(isrev1)//接收到数据
	{		
		if(//判断是不是模块返回的应答包				
					buf1[0]==0XEF
				&&buf1[1]==0X01
				&&buf1[6]==0X07
			)
			{
				*PS_Addr=(buf1[2]<<24) + (buf1[3]<<16)
								+(buf1[4]<<8) + (buf1[5]);
				isrev1=0;
				return 0;
			}
		isrev1=0;					
	}
	return 1;		
}
//模块应答包确认码信息解析
//功能:解析确认码错误信息返回信息
//参数: ensure
const char *EnsureMessage(unsigned char 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;	
}

4.服务器java端:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Service {
    public static ServerSocket server_nb=null;
    public static Socket sock_nb=null;
    public static InputStream in_nb=null;
    public static OutputStream out_nb=null;
    public static ServerSocket server_phone=null;
    public static ArrayList<Socket> sockets_phone=null;
    public static ArrayList<InputStream> in_phone=null;
    public static ArrayList<OutputStream> out_phone=null;
    public static void init_socket() {
        try {
            server_nb = new ServerSocket(6666);
            server_phone = new ServerSocket(8888);
            sockets_phone=new ArrayList<>();
            in_phone=new ArrayList<>();
            out_phone=new ArrayList<>();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void connect_nb() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        sock_nb = server_nb.accept();
                        System.out.println("connect:"+sock_nb.getInetAddress());
                        in_nb = sock_nb.getInputStream();
                        out_nb = sock_nb.getOutputStream();
                        System.out.println("nb init ok");
                        nb_rev();
                    } catch (IOException e) {
                        System.out.println("42");
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
    public static void connect_phone() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Socket phone = server_phone.accept();
                        InputStream inputStream = phone.getInputStream();
                        OutputStream outputStream = phone.getOutputStream();
                        sockets_phone.add(phone);
                        System.out.println("connect:"+phone.getInetAddress());
                        in_phone.add(inputStream);
                        out_phone.add(outputStream);
                        System.out.println("phone init ok");
                        if(out_nb!=null&&in_nb!=null)
                        {
                            new Thread(new Runnable() {
                                @Override
                                public void run() {
                                        if(phone!=null)
                                        {
                                            try {
                                                int len=0;
                                                byte[]bytes=new byte[1024];
                                                while ((len=inputStream.read(bytes))!=-1)
                                                {
                                                    nb_send(bytes,0,len);
                                                }
                                                close_phone();
                                            }catch (Exception e)
                                            {
                                                System.out.println("80");
                                                System.out.println(e.getMessage());
                                                close_phone();
                                            }
                                        }


                                }
                            }).start();
                        }
                        else
                        {
                            System.out.println("is null");
                            close_phone();
                        }
                    } catch (IOException e) {
                        System.out.println("95");
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
    public static void close_nb()
    {
        try
        {
            close_phone();
            out_nb.close();
            in_nb.close();
        }catch (Exception e)
        {
            System.out.println("110");
        }
        out_nb=null;
        in_nb=null;
        System.out.println("nb close ok!");
    }
    public static void close_phone()
    {
        try {
            for (Socket socket : sockets_phone) {
                socket.close();
            }
            sockets_phone.clear();
        }catch (Exception e)
        {
            System.out.println(e.getMessage());
            System.out.println("126");
        }
        try {
            for (InputStream inputStream : in_phone) {
                inputStream.close();
            }
            in_phone.clear();
        }catch (Exception e)
        {
            System.out.println(e.getMessage());
            System.out.println("136");
        }
        try {
            for (OutputStream outputStream : out_phone) {
                outputStream.close();
            }
            out_phone.clear();
        }catch (Exception e)
        {
            System.out.println(e.getMessage());
            System.out.println("146");
        }
        System.out.println("phone close ok!");
    }
    public static void nb_send(byte[] bytes,int start,int stop)
    {
        if(out_nb!=null)
        {
            try {
                out_nb.write(bytes,start,stop);
            } catch (IOException e) {
                close_nb();
                System.out.println("159");
                System.out.println(e.getMessage());
            }
        }
    }
    public static void nb_rev() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    if (in_nb != null) {
                        try {
                            int len = 0;
                            byte[] bytes = new byte[1024];
                            while ((len = in_nb.read(bytes)) != -1) {
                                for (OutputStream outputStream : out_phone) {
                                    outputStream.write(bytes,0,len);
                                }
                            }
                            close_nb();
                            close_phone();
                        } catch (Exception e) {
                            System.out.println("182");
                            System.out.println(e.getMessage());
                            close_nb();
                            close_phone();
                        }
                    }
                }
            }
        }).start();
    }

    public static void main(String[] args) {
        init_socket();
        connect_nb();
        connect_phone();
    }
}

5.Android源码

end