基于STM32指纹识别模块(TFS-M64)的学习

    之前的同学想用指纹模块做个东西,便让我帮他看看。收到之后了解了一下,最终是通过串口做通信的。这款产品是深圳十指科技的指纹模块,不过两年前就已经停产了。现在的新版的模块通信方式是完全一样的(串口通信),通信协议的变动也很少,不管是新模块还是老模块操作方式还是兼容的。

                                        

开始的时候用STM32的板子和它通信,忽略了响应时间的问题导致串口一直没有收到响应消息,后面找到这个原因之后便可完整的通过串口通信操作指纹模块了,为了方便后续使用封装了一份操作函数库:

头文件:

#ifndef __TFS_M64_H
#define __TFS_M64_H

#include "stm32f10x.h"

#define TRUE  1
#define FALSE 0

//基本应答信息定义
#define ACK_SUCCESS    0x00 //操作成功
#define ACK_FAIL       0x01 //操作失败
#define ACK_FULL       0x04 //指纹数据库已满
#define ACK_NOUSER     0x05 //无此用户
#define ACK_USER_EXIST 0x07 //用户已存在
#define ACK_TIMEOUT    0x08 //采集超时

#define ACK_GO_OUT		    0x0F
//用户信息定义
#define ACK_ALL_USER      0x00
#define ACK_GUEST_USER 	  0x01
#define ACK_NORMAL_USER 	0x02
#define ACK_MASTER_USER   0x03

#define USER_MAX_CNT	   50

//位置定义
#define HEAD 0
#define CMD  1
#define CHK  6
#define TAIL 7

#define P1   2
#define P2   3
#define P3   4
#define Q1   2
#define Q2   3
#define Q3   4

//命令定义
#define CMD_HEAD		  0xF5
#define CMD_TAIL		  0xF5
#define CMD_ADD_1  		0x01
#define CMD_ADD_2 		0x02
#define CMD_ADD_3	  	0x03
#define CMD_MATCH		  0x0C
#define CMD_DEL			  0x04
#define CMD_DEL_ALL		0x05
#define CMD_USER_CNT  0x09
#define CMD_SLEEP_MODE		0x2C
#define CMD_ADD_MODE  0x2D

#define CMD_FINGER_DETECTED 0x14

extern uint8_t gFpmTxBuf[9];
extern uint8_t gFpmRxBuf[9];
extern uint8_t gFpmRxCnt;


uint8_t fpm_sendAndReceive(uint16_t delayMs);
uint8_t fpm_sleep(void);
uint8_t fpm_setAddMode(uint8_t mode);
uint8_t fpm_readAddMode(void);
uint16_t fpm_getUserNum(void);
uint8_t fpm_deleteAllUser(void);
uint8_t fpm_deleteUser(uint8_t userNum);
uint8_t fpm_addUser(uint8_t userNum, uint8_t userPermission);
uint8_t fpm_compareFinger(void);



#endif /* __TFS-M64_H */



 源文件:

#include "tfs-m64.h"
#include "usart2.h"
#include "delay.h"
#include "usart.h"
///指纹模块 :Fingerprint module

uint8_t gFpmTxBuf[9];
uint8_t gFpmRxBuf[9];
uint8_t gFpmRxCnt;


/**
  * @brief  通过串口向指纹模块发送命令并接收响应指令
  * @param  timeOut:超时时间(单位:ms),在此时间内如果仍未接收到响应指令按超时处理
  * @retval 应答信息
  */
uint8_t fpm_sendAndReceive(uint16_t timeout)
{
  uint8_t  i, j;
  uint8_t checkSum = 0;  //校验码
	 
  gFpmRxCnt = 0; //接收计数清零,相当于清空缓冲区
	gFpmTxBuf[5] = 0; //命令数据的第六位始终为零
  
  /*发送8位数据包*/
  usart2_sendByte(CMD_HEAD);		//数据头
  for (i = 1; i < 6; i++)       //中间数据段
  {
    usart2_sendByte(gFpmTxBuf[i]);		 
    checkSum ^= gFpmTxBuf[i];
  }
  usart2_sendByte(checkSum);    //校验码
  usart2_sendByte(CMD_TAIL);    //数据尾

  while (gFpmRxCnt < 8 && timeout > 0)
  {
    delay_ms(1);
    timeout--;		   
  }
  
  if (gFpmRxCnt != 8) return ACK_TIMEOUT;
  if (gFpmRxBuf[HEAD] != CMD_HEAD) return ACK_FAIL;
  if (gFpmRxBuf[TAIL] != CMD_TAIL) return ACK_FAIL;
  if (gFpmRxBuf[CMD] != (gFpmTxBuf[CMD])) return ACK_FAIL;

  checkSum = 0;
  for (j = 1; j < CHK; j++) {   
    checkSum ^= gFpmRxBuf[j];
  }
	if (checkSum != gFpmRxBuf[CHK]) {
    return ACK_FAIL;
  }
	 return ACK_SUCCESS;
}	 

/**
  * @brief  使指纹模块进入休眠模式
  * @param  none
  * @retval 应答信息(ACK_SUCCESS  ACK_FAIL)
  */
uint8_t fpm_sleep(void)
{
  uint8_t res;
  
  gFpmTxBuf[CMD] = CMD_SLEEP_MODE;
  gFpmTxBuf[P1] = 0;
  gFpmTxBuf[P2] = 0;
  gFpmTxBuf[P3] = 0;
  
  res = fpm_sendAndReceive(500);
  
  if(res == ACK_SUCCESS) {
    return ACK_SUCCESS;
  }
  else {
    return ACK_FAIL;
  }
  
}

/**
  * @brief  设置指纹的添加模式
  * @param  mode:指纹的添加模式(0:允许重复 1:禁止重复)
  * @retval 应答信息(ACK_SUCCESS  ACK_FAIL)
  */
uint8_t fpm_setAddMode(uint8_t mode)
{
  uint8_t res;
  
  gFpmTxBuf[CMD] = CMD_ADD_MODE;
  gFpmTxBuf[P1] = 0;
  gFpmTxBuf[P2] = mode;
  gFpmTxBuf[P3] = 0;
  
  res = fpm_sendAndReceive(200);
  
  if(res == ACK_SUCCESS && gFpmRxBuf[Q3] == ACK_SUCCESS) {
    return ACK_SUCCESS;
  }
  else {
    return ACK_FAIL;
  }
}

/**
  * @brief  读取指纹的添加模式
  * @param  none
  * @retval 应答信息(0:允许重复 1:禁止重复)
  */
uint8_t fpm_readAddMode(void)
{ 
  gFpmTxBuf[CMD] = CMD_ADD_MODE;
  gFpmTxBuf[P1] = 0;
  gFpmTxBuf[P2] = 0;
  gFpmTxBuf[P3] = 0X01;
  
  fpm_sendAndReceive(200);
  
  return gFpmRxBuf[Q2];
}

/**
  * @brief  获取用户数(实际上应该是指纹数,这里用用户数表示是为了与通信协议表述一致)
  * @param  none
  * @retval 应答信息(指纹的数目)
  */
uint16_t fpm_getUserNum(void)
{
  uint8_t res;
  
  gFpmTxBuf[CMD] = CMD_USER_CNT;
  gFpmTxBuf[P1] = 0;
  gFpmTxBuf[P2] = 0;
  gFpmTxBuf[P3] = 0;
  
  res = fpm_sendAndReceive(200);
  
  if(res == ACK_SUCCESS && gFpmRxBuf[Q3] == ACK_SUCCESS) {
    return gFpmRxBuf[Q2];
  }
  else {
    return 0XFF;
  }
  
}

/**
  * @brief  删除所有的指纹
  * @param  none
  * @retval 应答信息(ACK_SUCCESS  ACK_FAIL)
  */
uint8_t fpm_deleteAllUser(void)
{
  uint8_t res;
  
  gFpmTxBuf[CMD] = CMD_DEL_ALL;
  gFpmTxBuf[P1] = 0;
  gFpmTxBuf[P2] = 0;
  gFpmTxBuf[P3] = 0;
  
  res = fpm_sendAndReceive(200);
  
  if(res == ACK_SUCCESS && gFpmRxBuf[Q3] == ACK_SUCCESS) {
    return ACK_SUCCESS;
  }
  else {
    return ACK_FAIL;
  }
}

/**
  * @brief  删除制定位置的指纹
  * @param  userNum:指纹的位置(1-255)
  * @retval 应答信息(ACK_SUCCESS  ACK_FAIL)
  */
uint8_t fpm_deleteUser(uint8_t userNum)
{
  uint8_t res;
  
  gFpmTxBuf[CMD] = CMD_DEL;
  gFpmTxBuf[P1] = 0;
  gFpmTxBuf[P2] = userNum;
  gFpmTxBuf[P3] = 0;
  
  res = fpm_sendAndReceive(200);
  
  if(res == ACK_SUCCESS && gFpmRxBuf[Q3] == ACK_SUCCESS) {
    return ACK_SUCCESS;
  }
  else {
    return ACK_FAIL;
  }
}

/**
  * @brief  录入指纹
  * @param  userNum:指纹存入的位置(1-255)
  * @param  userPermission:用户权限(1-3),具体含义自行定义。
  * @retval 应答信息(ACK_SUCCESS  ACK_FAIL  ACK_USER_EXIST  ACK_TIMEOUT)
  */
uint8_t fpm_addUser(uint8_t userNum, uint8_t userPermission)
{
  uint8_t res;
  
  gFpmTxBuf[CMD] = CMD_ADD_1;
  gFpmTxBuf[P1] = 0;
  gFpmTxBuf[P2] = userNum;
  gFpmTxBuf[P3] = userPermission;
  
  res = fpm_sendAndReceive(30000);

  if(res == ACK_SUCCESS) {
    if(gFpmRxBuf[Q3] == ACK_SUCCESS) {
      gFpmTxBuf[CMD] = CMD_ADD_2;
      
      res = fpm_sendAndReceive(30000);
      
      if(res == ACK_SUCCESS) {
        if(gFpmRxBuf[Q3] == ACK_SUCCESS) {
          gFpmTxBuf[CMD] = CMD_ADD_3;
          
          res = fpm_sendAndReceive(30000);
          
          if(res == ACK_SUCCESS) {
            return gFpmRxBuf[Q3];
          }  
        }
      }
    }
  }
  return res;
 
}

/**
  * @brief  通过1:N的方式比较指纹
  * @param  none
  * @retval 匹配指纹的信息
  */
uint8_t fpm_compareFinger(void)
{
  uint8_t res;
  
  gFpmTxBuf[CMD] = CMD_MATCH;
  gFpmTxBuf[P1] = 0;
  gFpmTxBuf[P2] = 0;
  gFpmTxBuf[P3] = 0;
  
  res = fpm_sendAndReceive(30000);
  
  if(res == ACK_SUCCESS) 
  {
    if(gFpmRxBuf[Q3] == ACK_NOUSER) {
      return ACK_NOUSER;
    }
    if(gFpmRxBuf[Q3] == ACK_TIMEOUT) {
      return ACK_TIMEOUT;
    }
    if((gFpmRxBuf[Q2] != 0) && (gFpmRxBuf[Q3] == 1 || gFpmRxBuf[Q3] == 2 || gFpmRxBuf[Q3] == 3)) {
      return ACK_SUCCESS;
    }
  }
  return res;
}


上面的这两个文件中的代码便是主要的封装函数,其中实现了使指纹模块进入休眠模式、设置指纹的增加方式、增加用户指纹、比对用户指纹、删除所有用户指纹、删除特定用户指纹等功能。 所有的函数都经过测试,可以实现相应的功能。在函数返回值信息部分的代码感觉处理的不是特别好,如果谁有更好的方式欢迎赐教!

最后附上在测试实验过程中所用的工程下载链接:https://download.csdn.net/download/xiaoyuanwuhui/10605561

测试实验是在STM32平台上完成的,为了方便直接用了原子的例程,在其中增加了该指纹函数库。在main.c文件中保留的许多函数测试的样例。

猜你喜欢

转载自blog.csdn.net/xiaoyuanwuhui/article/details/81697420