STM32 AS608 optical fingerprint module driver (common to HAL library and standard library)

Posted by munuindra on Sun, 26 Dec 2021 01:51:31 +0100

working principle:

If you want to look at the code directly, you can skip the principle, turn down directly, and then the code at the end
AS608 mainly communicates through serial port
1. Buffer and fingerprint database
The system is equipped with a 72K byte image buffer and two 512 bytes feature file buffers, named ImageBuffer, CharBuffer1 and CharBuffer2 respectively. Users can read and write any buffer through instructions.
CharBuffer1 or CharBuffer2 can be used to store both normal feature files and template feature files. When uploading or downloading images through UART port, in order to speed up the speed, only the high 4 bits of pixel bytes are used, that is, the two pixels are combined
Transmitted as a byte. Through the USB port, it is the whole 8-bit pixel.
The fingerprint library capacity changes according to the attached FLASH capacity, and the system will automatically judge. The fingerprint template is stored according to the serial number, which is defined as: 0 - (N-1) (N is the capacity of the fingerprint database). Users can only access the contents of the fingerprint database according to the serial number.

2. User Notepad
The system opens up a 512 byte storage area in FLASH as a user Notepad. The Notepad is logically divided into 16 pages, 32 bytes per page. The upper computer can pass PS_WriteNotepad instruction and PS_ReadNotepad instruction
Access any page. Note that when writing a page in Notepad, the 32 byte content of the page is written as a whole, and the original content is overwritten.
3. Random number generator
The hardware 32-bit random number generator is integrated in the system (no random number seed is required). Users can command the module to generate a random number and upload it to the upper computer.
4. Module address (size: 4bytes, attribute: read / write)
The default address of the module is 0xFFFFFFFF, which can be modified by instructions. The address field of the data packet must match the address before the command packet / data packet is received by the system. Note: the communication with the upper computer must be the default address 0xFFFFFF!
5. Module password (size: 4bytes, attribute: write)
The default password of the system is 0, which can be modified by instructions. If the default password is not modified, the system does not require password verification,
The upper computer and MCU communicate with the chip; If the password is modified, the first instruction of communication between the upper computer and the chip must be authentication
Password. Only after the password is verified, the chip can receive other instructions. Note: it is not recommended to change the password!
6. Packet size setting (size: 1bytes, attribute: read / write)
The length of sending and receiving packets is set according to this value.
7. Baud rate coefficient N setting (size: 1bytes, attribute: read / write)
USART baud rate = n × 9600,N=1~12.
8. Security level setting (size: 1bytes, attribute: read / write)
The system sets the comparison threshold according to the safety level, level=1~5. When the security level is 1, the false recognition rate is the highest and the rejection rate is the lowest.
When the security level is 5, the false recognition rate is the lowest and the rejection rate is the highest.

Fingerprint sending instruction flow: obtain fingerprint image instruction - > generate fingerprint feature instruction - > search and verify fingerprint instruction

Instruction diagram:

Input image instruction:

Search fingerprint command:

Generate fingerprint feature instruction:

Fingerprint communication protocol format:
The above are some instructions for fingerprint communication. According to these pictures, you can write code.

Code part:

I use serial port 2 here. I need to change it myself:
In the code part, I mainly talk about simply porting the official code of the standard library into the code that can also be used in the HAL library, and the code of the standard library will be attached at the end
as608.c

#include <string.h>
#include <stdio.h>
#include "usart.h"
#include "as608.h"
#include "oled.h"
#include "key.h"

uint32_t AS608Addr = 0XFFFFFFFF; //default
char str2[6] = {0};

//Serial port receiving buffer 	
uint8_t USART2_RX_BUF[USART2_MAX_RECV_LEN]; 				//Receive buffer, maximum USART2_MAX_RECV_LEN bytes
uint8_t USART2_TX_BUF[USART2_MAX_SEND_LEN]; 			  //Transmit buffer, maximum USART2_MAX_SEND_LEN byte

//Determine whether it is continuous data at one time by judging that the time difference between two consecutive characters is no more than 10ms
//If the reception interval of two characters exceeds 10ms, it is considered that it is not a continuous data That is, it is not received for more than 10ms
//Any data indicates that the reception is completed
//Received data status
//[15] : 0, no data received; 1. Received a batch of data
//[14:0]: received data length
__IO uint16_t USART2_RX_STA=0;



//Serial port sends a byte
static void MYUSART_SendData(uint8_t data)
{
  while((USART2->SR & 0X40) == 0);
  USART2->DR = data;
}
//Send packet header
static void SendHead(void)
{
  MYUSART_SendData(0xEF);
  MYUSART_SendData(0x01);
}
//Sending address
static void SendAddr(void)
{
  MYUSART_SendData(AS608Addr >> 24);
  MYUSART_SendData(AS608Addr >> 16);
  MYUSART_SendData(AS608Addr >> 8);
  MYUSART_SendData(AS608Addr);
}
//Send packet ID,
static void SendFlag(uint8_t flag)
{
  MYUSART_SendData(flag);
}
//Sending packet length
static void SendLength(int length)
{
  MYUSART_SendData(length >> 8);
  MYUSART_SendData(length);
}
//Send instruction code
static void Sendcmd(uint8_t cmd)
{
  MYUSART_SendData(cmd);
}
//Send checksum
static void SendCheck(uint16_t check)
{
  MYUSART_SendData(check >> 8);
  MYUSART_SendData(check);
}
//Judge whether there is a reply packet in the array received by the interrupt
//waittime is the time to wait for interrupt to receive data (unit: 1ms)
//Return value: packet header address
static uint8_t *JudgeStr(uint16_t waittime)
{
  char *data;
  uint8_t 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';
//  USART2_RX_STA = 0;
		//Writing method of HAL Library
	HAL_UART_Receive(&huart2,(uint8_t *)USART2_RX_BUF,USART2_MAX_RECV_LEN,waittime/4);//Serial port 3 receives data
	if(!memcmp(str,USART2_RX_BUF,7))//Comparison data
	{
		  data = strstr((const char*)USART2_RX_BUF, (const char*)str);
      if(data)
        return (uint8_t*)data;
	}
	//
//  while(--waittime)
//  {
//    HAL_Delay(1);
//    If (usart2_rx_sta & 0x8000) / / data received once
//    {
//      USART2_RX_STA = 0;
//      data = strstr((const char*)USART2_RX_BUF, (const char*)str);
//      if(data)
//        return (uint8_t*)data;
//    }
//  }
  return 0;
}
//Input image PS_GetImage
//Function: detect the finger, input the fingerprint image and save it in ImageBuffer.
//Module return confirmation word
uint8_t PS_GetImage(void)
{
  uint16_t temp;
  uint8_t  ensure;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  SendLength(0x03);
  Sendcmd(0x01);
  temp =  0x01 + 0x03 + 0x01;
  SendCheck(temp);
  data = JudgeStr(2000);
  if(data)
    ensure = data[9];
  else
    ensure = 0xff;
  return ensure;
}
//Generate feature PS_GenChar
//Function: store the fingerprint feature file generated from the original image in ImageBuffer in CharBuffer1 or CharBuffer2
//Parameter: bufferid -- > charbuffer1:0x01 	 charBuffer1:0x02
//Module return confirmation word
uint8_t PS_GenChar(uint8_t BufferID)
{
  uint16_t temp;
  uint8_t  ensure;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  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;
}
//Accurate comparison of two fingerprint features_ Match
//Function: accurately compare the characteristic files in CharBuffer1 and CharBuffer2
//Module return confirmation word
uint8_t PS_Match(void)
{
  uint16_t temp;
  uint8_t  ensure;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  SendLength(0x03);
  Sendcmd(0x03);
  temp = 0x01 + 0x03 + 0x03;
  SendCheck(temp);
  data = JudgeStr(2000);
  if(data)
    ensure = data[9];
  else
    ensure = 0xff;
  return ensure;
}
//Search fingerprint PS_Search
//Function: search the whole or part of fingerprint database with the characteristic files in CharBuffer1 or CharBuffer2 If found, the page number is returned.
//Parameter: BufferID @ref CharBuffer1 	 CharBuffer2
//Description: module returns confirmation word and page number (matching fingerprint template)
uint8_t PS_Search(uint8_t BufferID, uint16_t StartPage, uint16_t PageNum, SearchResult *p)
{
  uint16_t temp;
  uint8_t  ensure;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  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) + (uint8_t)StartPage
         + (PageNum >> 8) + (uint8_t)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;
}
//Merge feature (generate template) PS_RegModel
//Function: merge the feature files in CharBuffer1 and CharBuffer2 to generate a template, and store the results in CharBuffer1 and CharBuffer2
//Description: the module returns the confirmation word
uint8_t PS_RegModel(void)
{
  uint16_t temp;
  uint8_t  ensure;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  SendLength(0x03);
  Sendcmd(0x05);
  temp = 0x01 + 0x03 + 0x05;
  SendCheck(temp);
  data = JudgeStr(2000);
  if(data)
    ensure = data[9];
  else
    ensure = 0xff;
  return ensure;
}
//Save template PS_StoreChar
//Function: save the template file in CharBuffer1 or CharBuffer2 to the flash database location with PageID number.
//Parameter: BufferID @ref charBuffer1:0x01 	 charBuffer1:0x02
//       PageID (fingerprint library location number)
//Description: the module returns the confirmation word
uint8_t PS_StoreChar(uint8_t BufferID, uint16_t PageID)
{
  uint16_t temp;
  uint8_t  ensure;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  SendLength(0x06);
  Sendcmd(0x06);
  MYUSART_SendData(BufferID);
  MYUSART_SendData(PageID >> 8);
  MYUSART_SendData(PageID);
  temp = 0x01 + 0x06 + 0x06 + BufferID
         + (PageID >> 8) + (uint8_t)PageID;
  SendCheck(temp);
  data = JudgeStr(2000);
  if(data)
    ensure = data[9];
  else
    ensure = 0xff;
  return ensure;
}
//Delete template PS_DeletChar
//Function: delete N fingerprint templates starting with the specified ID number in the flash database
//Parameter: pageid (fingerprint database template number), N number of deleted templates.
//Description: the module returns the confirmation word
uint8_t PS_DeletChar(uint16_t PageID, uint16_t N)
{
  uint16_t temp;
  uint8_t  ensure;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  SendLength(0x07);
  Sendcmd(0x0C);
  MYUSART_SendData(PageID >> 8);
  MYUSART_SendData(PageID);
  MYUSART_SendData(N >> 8);
  MYUSART_SendData(N);
  temp = 0x01 + 0x07 + 0x0C
         + (PageID >> 8) + (uint8_t)PageID
         + (N >> 8) + (uint8_t)N;
  SendCheck(temp);
  data = JudgeStr(2000);
  if(data)
    ensure = data[9];
  else
    ensure = 0xff;
  return ensure;
}
//Empty fingerprint library PS_Empty
//Function: delete all fingerprint templates in flash database
//Parameter: None
//Description: the module returns the confirmation word
uint8_t PS_Empty(void)
{
  uint16_t temp;
  uint8_t  ensure;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  SendLength(0x03);
  Sendcmd(0x0D);
  temp = 0x01 + 0x03 + 0x0D;
  SendCheck(temp);
  data = JudgeStr(2000);
  if(data)
    ensure = data[9];
  else
    ensure = 0xff;
  return ensure;
}
//Write system register PS_WriteReg
//Function: write module register
//Parameter: register sequence number RegNum:4
//Description: the module returns the confirmation word
uint8_t PS_WriteReg(uint8_t RegNum, uint8_t DATA)
{
  uint16_t temp;
  uint8_t  ensure;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  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 Parameter setting succeeded!");
  else
    printf("\r\n%s", EnsureMessage(ensure));
  return ensure;
}
//Read system basic parameters PS_ReadSysPara
//Function: read the basic parameters of the module (baud rate, packet size, etc.)
//Parameter: None
//Description: module returns confirmation word + basic parameters (16bytes)
uint8_t PS_ReadSysPara(SysPara *p)
{
  uint16_t temp;
  uint8_t  ensure;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  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 Module maximum fingerprint capacity=%d", p->PS_max);
    printf("\r\n Contrast level=%d", p->PS_level);
    printf("\r\n address=%x", p->PS_addr);
    printf("\r\n Baud rate=%d", p->PS_N * 9600);
  }
  else
    printf("\r\n%s", EnsureMessage(ensure));
  return ensure;
}
//Set module address PS_SetAddr
//Function: set module address
//Parameter: PS_addr
//Description: the module returns the confirmation word
uint8_t PS_SetAddr(uint32_t PS_addr)
{
  uint16_t temp;
  uint8_t  ensure;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  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
         + (uint8_t)(PS_addr >> 24) + (uint8_t)(PS_addr >> 16)
         + (uint8_t)(PS_addr >> 8) + (uint8_t)PS_addr;
  SendCheck(temp);
  AS608Addr = PS_addr; //After sending the instruction, change the address
  data = JudgeStr(2000);
  if(data)
    ensure = data[9];
  else
    ensure = 0xff;
  AS608Addr = PS_addr;
  if(ensure == 0x00)
    printf("\r\n Address setting succeeded!");
  else
    printf("\r\n%s", EnsureMessage(ensure));
  return ensure;
}
//Function: 256 bytes of FLASH space is opened for users in the module to store user Notepad,
//	The Notepad is logically divided into 16 pages.
//Parameters: notepagenum (0 ~ 15), byte32 (content to be written, 32 bytes)
//Description: the module returns the confirmation word
uint8_t PS_WriteNotepad(uint8_t NotePageNum, uint8_t *Byte32)
{
  uint16_t temp;
  uint8_t  ensure, i;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  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;
}
//Reading notes PS_ReadNotepad
//Function: read 128bytes data of FLASH user area
//Parameter: NotePageNum(0~15)
//Description: the module returns confirmation word + user information
uint8_t PS_ReadNotepad(uint8_t NotePageNum, uint8_t *Byte32)
{
  uint16_t temp;
  uint8_t  ensure, i;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  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;
}
//High speed search PS_HighSpeedSearch
//Function: search the whole or part of fingerprint database at high speed with the characteristic files in CharBuffer1 or CharBuffer2.
//		  If it is found, the page number will be returned. The instruction is indeed stored in the fingerprint database and the quality at login
//		  A good fingerprint will give search results soon.
//Parameters: BufferID, startpage, PageNum
//Description: module returns confirmation word + page number (matching fingerprint template)
uint8_t PS_HighSpeedSearch(uint8_t BufferID, uint16_t StartPage, uint16_t PageNum, SearchResult *p)
{
  uint16_t temp;
  uint8_t  ensure;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  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) + (uint8_t)StartPage
         + (PageNum >> 8) + (uint8_t)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;
}
//Number of valid templates read PS_ValidTempleteNum
//Function: read the number of valid templates
//Parameter: None
//Description: module returns confirmation word + number of valid templates ValidN
uint8_t PS_ValidTempleteNum(uint16_t *ValidN)
{
  uint16_t temp;
  uint8_t  ensure;
  uint8_t  *data;
  SendHead();
  SendAddr();
  SendFlag(0x01);//Command package ID
  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 Number of effective fingerprints=%d", (data[10] << 8) + data[11]);
  }
  else
    printf("\r\n%s", EnsureMessage(ensure));
  return ensure;
}
//Shake hands with AS608 PS_HandShake
//Parameter: PS_Addr address pointer
//Description: module return new address (correct address)
uint8_t PS_HandShake(uint32_t *PS_Addr)
{
  SendHead();
  SendAddr();
  MYUSART_SendData(0X01);
  MYUSART_SendData(0X00);
  MYUSART_SendData(0X00);
  HAL_Delay(200);
  if(USART2_RX_STA & 0X8000) //Data received
  {
    if(//Determine whether it is the response packet returned by the module
      USART2_RX_BUF[0] == 0XEF
      && USART2_RX_BUF[1] == 0X01
      && USART2_RX_BUF[6] == 0X07
    )
    {
      *PS_Addr = (USART2_RX_BUF[2] << 24) + (USART2_RX_BUF[3] << 16)
                 + (USART2_RX_BUF[4] << 8) + (USART2_RX_BUF[5]);
      USART2_RX_STA = 0;
      return 0;
    }
    USART2_RX_STA = 0;
  }
  return 1;
}
//Module response packet confirmation code information analysis
//Function: parse confirmation code error information and return information
//Parameters: ensure
const char *EnsureMessage(uint8_t ensure)
{
  const char *p;
  switch(ensure)
  {
  case  0x00:
    p = "       OK       ";
    break;
  case  0x01:
    p = " Packet receiving error ";
    break;
  case  0x02:
    p = "There are no fingers on the sensor";
    break;
  case  0x03:
    p = "Failed to enter fingerprint image";
    break;
  case  0x04:
    p = " Fingerprints too dry or too light ";
    break;
  case  0x05:
    p = " The fingerprint is too wet or too sticky ";
    break;
  case  0x06:
    p = "  The fingerprint image is too messy  ";
    break;
  case  0x07:
    p = " Too few fingerprint feature points ";
    break;
  case  0x08:
    p = "  Fingerprint mismatch    ";
    break;
  case  0x09:
    p = " No fingerprints were found ";
    break;
  case  0x0a:
    p = "   Feature merge failed ";
    break;
  case  0x0b:
    p = "Address sequence number out of range";
  case  0x10:
    p = "  Failed to delete template  ";
    break;
  case  0x11:
    p = " Failed to empty fingerprint database ";
    break;
  case  0x15:
    p = "No valid map in buffer";
    break;
  case  0x18:
    p = " Reading and writing FLASH error  ";
    break;
  case  0x19:
    p = "   Undefined error   ";
    break;
  case  0x1a:
    p = "  Invalid register number  ";
    break;
  case  0x1b:
    p = " Register content error ";
    break;
  case  0x1c:
    p = " Notepad page number error ";
    break;
  case  0x1f:
    p = "    Fingerprint library full    ";
    break;
  case  0x20:
    p = "    Address error    ";
    break;
  default :
    p = " Error in return confirmation code ";
    break;
  }
  return p;
}

//Display confirmation code error message
void ShowErrMessage(uint8_t ensure)
{
  //OLED_ShowMixedCH(5,0,(uint8_t*)EnsureMessage(ensure));
}


//Record fingerprint
void Add_FR(void)
{
  uint8_t i, ensure, processnum = 0;
  uint8_t ID_NUM = 0;
	uint8_t key_num = 0;
  while(1)
  {
    switch (processnum)
    {
    case 0:
      i++;
			OLED_FullyClear();
      OLED_ShowMixedCH(0, 16, "    Please press your finger    ");
			OLED_RefreshRAM();
      ensure = PS_GetImage();
      if(ensure == 0x00)
      {
        ensure = PS_GenChar(CharBuffer1); //Generating features
        if(ensure == 0x00)
        {
          OLED_ShowMixedCH(0, 16, "    Normal fingerprint    ");
          OLED_ShowMixedCH(0, 16, "                ");
					OLED_RefreshRAM();
          i = 0;
          processnum = 1; //Skip to step two
        }
        else ShowErrMessage(ensure);
      }
      else ShowErrMessage(ensure);
      break;

    case 1:
      i++;
      OLED_ShowMixedCH(0, 16, "   Please press again   ");
      OLED_ShowMixedCH(0, 16, "                ");
	  	OLED_RefreshRAM();
      ensure = PS_GetImage();
      if(ensure == 0x00)
      {
        ensure = PS_GenChar(CharBuffer2); //Generating features
        if(ensure == 0x00)
        {
          OLED_ShowMixedCH(0, 16, "    Normal fingerprint    ");
          OLED_ShowMixedCH(0, 32, "                ");
					OLED_RefreshRAM();
          i = 0;
          processnum = 2; //Skip to step 3
        }
        else ShowErrMessage(ensure);
      }
      else ShowErrMessage(ensure);
      break;

    case 2:
      OLED_ShowMixedCH(0, 16, "  Compare the fingerprints twice  ");
      OLED_ShowMixedCH(0, 32, "                ");
			OLED_RefreshRAM();
      ensure = PS_Match();
      if(ensure == 0x00)
      {
        OLED_ShowMixedCH(0, 16, "    Successful comparison    ");
        OLED_ShowMixedCH(0, 32, "                ");
				OLED_RefreshRAM();
        processnum = 3; //Skip to step 4
      }
      else
      {
        OLED_ShowMixedCH(0, 16, "    Comparison failed    ");
        OLED_ShowMixedCH(0, 32, "                ");
				OLED_RefreshRAM();
        ShowErrMessage(ensure);
        i = 0;
        processnum = 0; //Jump back to the first step
      }
      HAL_Delay(500);
      break;

    case 3:
      OLED_ShowMixedCH(0, 16, "  Generate fingerprint template  ");
      OLED_ShowMixedCH(0, 32, "                ");
			OLED_RefreshRAM();
      HAL_Delay(500);
      ensure = PS_RegModel();
      if(ensure == 0x00)
      {
        OLED_ShowMixedCH(0, 16, "Fingerprint template generated successfully");
        OLED_ShowMixedCH(0, 32, "                ");
				OLED_RefreshRAM();
        processnum = 4; //Skip to step 5
      }
      else
      {
        processnum = 0;
        ShowErrMessage(ensure);
      }
      HAL_Delay(1000);
      break;

    case 4:
			OLED_FullyClear();
      OLED_ShowMixedCH(0, 0, " Press K4 plus,Press K2 reduce ");
      OLED_ShowMixedCH(0, 16, "    Press K3 preservation    ");
      OLED_ShowMixedCH(0, 32, "  0=< ID <=99   ");
			OLED_RefreshRAM();
      while(key_num != KEYENTER_PRES)
      {
        key_num = key_scan();
        if(key_num == KEYDOWN_PRES)
        {
          key_num = 0;
          if(ID_NUM > 0)
            ID_NUM--;
        }
        if(key_num == KEYUP_PRES)
        {
          key_num = 0;
          if(ID_NUM < 99)
            ID_NUM++;
        }
				show_ID(40,48,ID_NUM);
      }
      key_num = 0;
      ensure = PS_StoreChar(CharBuffer2, ID_NUM); //Save template
      if(ensure == 0x00)
      {
        OLED_FullyClear();
        OLED_ShowMixedCH(0, 16, "  Fingerprint entered successfully  ");
        OLED_ShowMixedCH(0, 32, "                ");
				OLED_RefreshRAM();
        HAL_Delay(1500);
        OLED_FullyClear();
        OLED_ShowMixedCH(0, 0, "Fingerprint module test procedure");
        OLED_ShowMixedCH(16, 16, "K1 Key to add fingerprint");
        OLED_ShowMixedCH(16, 32, "K3 Key to delete fingerprint");
        OLED_ShowMixedCH(16, 48, "K5 Key verification fingerprint");
				OLED_RefreshRAM();
        return ;
      }
      else
      {
        OLED_FullyClear();
        processnum = 0;
        ShowErrMessage(ensure);
      }
      break;
    }
    HAL_Delay(400);
    if(i == 10) //If you don't press your finger more than 5 times, exit
    {
      break;
    }
  }
}

SysPara AS608Para;//Fingerprint module AS608 parameters
//Brush fingerprint
void press_FR(void)
{
  SearchResult seach;
  uint8_t ensure;
  char str[20];
	uint8_t key_num = 0;
  while(key_num != KEYBACK_PRES)
  {
    key_num = key_scan();
    ensure = PS_GetImage();
    if(ensure == 0x00) //Image acquisition succeeded
    {
      ensure = PS_GenChar(CharBuffer1);
      if(ensure == 0x00) //Feature generation succeeded
      {
        ensure = PS_HighSpeedSearch(CharBuffer1, 0, 99, &seach);
        if(ensure == 0x00) //Search succeeded
        {
					OLED_FullyClear();
          OLED_ShowMixedCH(0, 16, "  Fingerprint verification succeeded  ");
          sprintf(str, " ID:%d score:%d ", seach.pageID, seach.mathscore);
          OLED_ShowMixedCH(0, 32, (uint8_t*)str);
					OLED_RefreshRAM();
          HAL_Delay(1500);
          HAL_Delay(1500);
        }
        else
        {
          OLED_ShowMixedCH(32, 16, "Validation failed");
					OLED_RefreshRAM();
          HAL_Delay(1500);
        }
      }
      else
			{};
      OLED_FullyClear();
      OLED_ShowMixedCH(32, 16, "Please press your finger");
			OLED_RefreshRAM();
    }
  }
  OLED_FullyClear();
  OLED_ShowMixedCH(0, 0, "Fingerprint module test procedure");
  OLED_ShowMixedCH(16, 16, "K1 Key to add fingerprint");
  OLED_ShowMixedCH(16, 32, "K3 Key to delete fingerprint");
  OLED_ShowMixedCH(16, 48, "K5 Key verification fingerprint");
	OLED_RefreshRAM();
}

//Delete fingerprint
void Del_FR(void)
{
  uint8_t  ensure;
  uint16_t ID_NUM = 0;
	uint8_t key_num = 0;
	OLED_FullyClear();
  OLED_ShowMixedCH(0, 16, "K4 plus K2 reduce K3 confirm");
  OLED_ShowMixedCH(0, 32, "K1 Return 0=<ID<=99");
	OLED_RefreshRAM();
  while(key_num != KEYENTER_PRES)
  {
    key_num = key_scan();
    if(key_num == KEYDOWN_PRES)
    {
      key_num = 0;
      if(ID_NUM > 0)
        ID_NUM--;
    }
    if(key_num == KEYUP_PRES)
    {
      key_num = 0;
      if(ID_NUM < 99)
        ID_NUM++;
    }
    if(key_num == KEYBACK_PRES)
      goto MENU ; //Return to main page
		show_ID(40,48,ID_NUM);
  }
  ensure = PS_DeletChar(ID_NUM, 1); //Delete single fingerprint
  if(ensure == 0)
  {
    OLED_FullyClear();
    OLED_ShowMixedCH(0, 16, "  Fingerprint deleted successfully  ");
		OLED_RefreshRAM();
  }
  else
    ShowErrMessage(ensure);
  HAL_Delay(1500);
MENU:
  OLED_FullyClear();
  OLED_ShowMixedCH(0, 0, "Fingerprint module test procedure");
  OLED_ShowMixedCH(16, 16, "K1 Key to add fingerprint");
  OLED_ShowMixedCH(16, 32, "K3 Key to delete fingerprint");
  OLED_ShowMixedCH(16, 48, "K5 Key verification fingerprint");
	OLED_RefreshRAM();
  key_num = 0;
}

void delete_ALL(void)
{
		uint8_t ensure;
   ensure = PS_Empty(); //Empty fingerprint Library
   if(ensure == 0)
   {
     OLED_FullyClear();
     OLED_ShowMixedCH(0, 16, " Fingerprint library emptied successfully ");
		 OLED_RefreshRAM();
   }
   else
	 {
      ShowErrMessage(ensure);
      HAL_Delay(1500);
   }
}

The above is the official code. I made some modifications. There are many shift operations in the code. Those are the instructions in the above figures. If you are interested, you can calculate the shift.
Modified function:

//Judge whether there is a reply packet in the array received by the interrupt
//waittime is the time to wait for interrupt to receive data (unit: 1ms)
//Return value: packet header address
static uint8_t *JudgeStr(uint16_t waittime)
{
  char *data;
  uint8_t 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';

		//Writing method of HAL Library
	HAL_UART_Receive(&huart2,(uint8_t *)USART2_RX_BUF,USART2_MAX_RECV_LEN,waittime/4);//Serial port 3 receives data
	if(!memcmp(str,USART2_RX_BUF,7))//Comparison data
	{
		  data = strstr((const char*)USART2_RX_BUF, (const char*)str);
      if(data)
        return (uint8_t*)data;
	}
//  USART2_RX_STA = 0;
//  while(--waittime)
//  {
//    HAL_Delay(1);
//    If (usart2_rx_sta & 0x8000) / / data received once
//    {
//      USART2_RX_STA = 0;
//      data = strstr((const char*)USART2_RX_BUF, (const char*)str);
//      if(data)
//        return (uint8_t*)data;
//    }
//  }
  return 0;
}

The HAL library is needed in the whole code. You only need to change this part to use it. Because the interrupt used by the official code serial port reception, when using the HAL library, I changed it to block the reception and deleted the interrupt given by the original official
as608.h:

#ifndef __AS608_H
#define __AS608_H
#include <stdio.h>
#include "stm32f1xx_hal.h"

//#define PS_ Sta pain (6) / / read the fingerprint module status pin
#define CharBuffer1 0x01
#define CharBuffer2 0x02

#define USART2_MAX_RECV_LEN 		 four hundred 					// Maximum receive cache bytes
#define USART2_MAX_SEND_LEN 		 four hundred 					// Maximum send cache bytes
#define USART2_RX_EN  			 one 					// 0, not received; 1. Receive

extern uint32_t AS608Addr;//Module address

typedef struct  
{
	uint16_t pageID;//Fingerprint ID
	uint16_t mathscore;//Match score
}SearchResult;

typedef struct
{
	uint16_t PS_max;//Maximum fingerprint capacity
	uint8_t  PS_level;//Safety level
	uint32_t PS_addr;
	uint8_t  PS_size;//Communication packet size
	uint8_t  PS_N;//Baud rate base N
}SysPara;

void PS_StaGPIO_Init(void);//Initialize PA6 read status pin
	
uint8_t PS_GetImage(void); //Input image 
 
uint8_t PS_GenChar(uint8_t BufferID);//Generating features 

uint8_t PS_Match(void);//Accurately compare the characteristics of two fingerprints 

uint8_t PS_Search(uint8_t BufferID,uint16_t StartPage,uint16_t PageNum,SearchResult *p);//Search for fingerprints 
 
uint8_t PS_RegModel(void);//Merge features (generate template) 
 
uint8_t PS_StoreChar(uint8_t BufferID,uint16_t PageID);//Save template 

uint8_t PS_DeletChar(uint16_t PageID,uint16_t N);//Delete template 

uint8_t PS_Empty(void);//Empty fingerprint Library 

uint8_t PS_WriteReg(uint8_t RegNum,uint8_t DATA);//Write system register 
 
uint8_t PS_ReadSysPara(SysPara *p); //Read system basic parameters 

uint8_t PS_SetAddr(uint32_t addr);  //Set module address 

uint8_t PS_WriteNotepad(uint8_t NotePageNum,uint8_t *content);//Write Notepad 

uint8_t PS_ReadNotepad(uint8_t NotePageNum,uint8_t *note);//Reading notes 

uint8_t PS_HighSpeedSearch(uint8_t BufferID,uint16_t StartPage,uint16_t PageNum,SearchResult *p);//High speed search 
  
uint8_t PS_ValidTempleteNum(uint16_t *ValidN);//Number of valid templates read 

uint8_t PS_HandShake(uint32_t *PS_Addr); //Handshake with AS608 module

const char *EnsureMessage(uint8_t ensure);//Analysis of confirmation code error information

void Add_FR(void);

void press_FR(void);

void Del_FR(void);

void delete_ALL(void);

#endif


The above is the code after migrating from the standard library to the HAL library

Standard library code link: https://pan.baidu.com/s/1t5-VQ0BpBHGaw2MuOF7azA Extraction code: rbwe

Topics: Embedded system Single-Chip Microcomputer stm32 ARM