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源码