光学指纹识别传感器采用了国内著名指纹识别芯片公司杭州晟元芯片技术有限公司(Synochip) 的 AS608 指纹识别芯片。芯片内置 DSP 运算单元,集成了指纹识别算法,能高效快速采集 图像并识别指纹特征。模块配备了串口、USB 通讯接口,用户无需研究复杂的图像处理及及指纹识别算法,只需通过简单的串口、USB 按照通讯协议便可控制模块。本模块可应用于各种考勤机、保险箱柜、指纹门禁系统、指纹锁等场合。
01、模块来源
模块实物展示:
资料下载链接:
https://pan.baidu.com/s/1mCDdiU5nwtooxmHiPfYTFA
资料提取码:kj8o
2、规格参数
工作电压:3.0-3.6V
工作电流:30~60mA
指纹存容量:300 枚(ID:0~299)
认假率:<0.001%
搜索时间:<0.3(S)
控制方式:串口或USB
管脚数量:8 Pin(2.54mm间距排针)
以上信息见厂家资料文件
03、移植过程
我们的目标是将例程移植至CW32F030C8T6开发板上【实现添加指纹、删除指纹和搜索指纹的功能】。首先要获取资料,查看数据手册应如何实现读取数据,再移植至我们的工程。
3.1查看资料
系统内设有一个72K字节的图像缓冲区与二个512bytes大小的特征文件缓冲区,名字分别称为:lmageBuffer,CharBuffer1和CharBuffer2。用户可以通过指令读写任意一个缓冲区。CharBufferl或 CharBuffer2既可以用于存放普通特征文件也可以用于存放模板特征文件。通过UART 口上传或下载图像时为了加快速度,只用到像素字节的高4位,即将两个像素合成一个字节传送。通过USB口则是整8位像素。
指纹库容量根据挂接的FLASH容量不同而改变,系统会自动判别。指纹模板按照序号存放,序号定义为:0—(N-1)(N为指纹库容量)。用户只能根据序号访问指纹库内容。
这里我们使用的是串口控制方式,USB的接口我们可以悬空不接。
1脚(红线):模块主电源,接3.3V供电(请勿接3.3V以上电源,否则烧毁模块!);
2脚(黄线):模块串口TX(发送端),接MCU或TTL串口的RX(接收端);
3脚(白线):模块串口RX(接收端),接MCU或TTL串口的TX(发送端);
4脚(黑线):模块电源地,接3.3V电源地(负极);
5脚(蓝线):模块触摸感应信号输出(高电平为检测到触摸),需接VTI到3.3V。
6脚(绿线):模块触摸感应电路电源(3.3V),可以与1脚(红线)并接。
7脚,8脚为USB信号线,使用串口控制模块时可以悬空不用。
3.2引脚选择
想要使用uart串口,需要确定使用的引脚是否有串口外设功能,可以通过用户手册进行查看。在用户手册的第146页。
这里选择使用PA2和PA3的附加串口2功能。
有串口功能的引脚
接线表
3.3移植至工程
移植步骤中的导入.c和.h文件与【CW32模块使用】DHT11温湿度传感器相同,只是将.c和.h文件更改为bsp_as608.c与bsp_as608.h。这里不再过多讲述,移植完成后面修改相关代码。
将bsp_uart.c修改为下面的代码:
/*
* Change Logs:
* Date Author Notes
* 2024-06-12 LCKFB-LP first version
*/
#include "bsp_uart.h"
#include "stdio.h"
uint8_t u1_recv_buff[512]; // 接收缓冲区
uint16_t u1_recv_length; // 接收数据长度
uint8_t u1_recv_flag; // 接收完成标志位
/******************************************************************
* 函 数 名 称:uart1_init
* 函 数 说 明:初始化USART1的串口收发功能
* 函 数 形 参:__rate:波特率
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void uart1_init(uint32_t __rate)
{
//配置RCC
RCC_AHBPeriphClk_Enable(DEBUG_USART_GPIO_CLK, ENABLE); // 使能GPIO时钟
DEBUG_USART_APBClkENx(DEBUG_USART_CLK, ENABLE); // 使能串口时钟
// 配置GPIO
GPIO_InitTypeDef GPIO_InitStructure;
//UART TX RX 复用
DEBUG_USART_AFTX;
DEBUG_USART_AFRX;
GPIO_InitStructure.Pins = DEBUG_USART_TX_GPIO_PIN; // 引脚
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; // 输出速度高
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure); // 初始化GPIO
GPIO_InitStructure.Pins = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP; // 上拉输入
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
// 配置UART
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = __rate; // 波特率
USART_InitStructure.USART_Over = USART_Over_16; // 配置USART的过采样率。
USART_InitStructure.USART_Source = USART_Source_PCLK; // 设置时钟源
USART_InitStructure.USART_UclkFreq = DEBUG_USART_UclkFreq; //设置USART时钟频率(和主频一致即可)
USART_InitStructure.USART_StartBit = USART_StartBit_FE; //RXD下降沿开始
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 停止位1
USART_InitStructure.USART_Parity = USART_Parity_No ; // 不使用校验
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 不使用流控
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 收发模式
USART_Init(DEBUG_USARTx, &USART_InitStructure);
//优先级,无优先级分组
NVIC_SetPriority(DEBUG_USART_IRQ, 0);
//UARTx中断使能
NVIC_EnableIRQ(DEBUG_USART_IRQ);
//使能UARTx RC中断
USART_ITConfig(DEBUG_USARTx, USART_IT_RC, ENABLE);
}
#if !defined(__MICROLIB)
//不使用微库的话就需要添加下面的函数
#if (__ARMCLIB_VERSION <= 6000000)
//如果编译器是AC5 就定义下面这个结构体
struct __FILE
{
int handle;
};
#endif
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
#endif
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
// 发送一个字节
USART_SendData(DEBUG_USARTx, (uint8_t)ch);
// 等待发送完成
while( RESET == USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) ){}
return ch;
}
void uart1_receive_clear(void)
{
for(int i = 0; i < 512; i++)
{
u1_recv_buff[i] = 0;
}
u1_recv_length = 0;
u1_recv_flag = 0;
}
/******************************************************************
* 函 数 名 称:UART1_IRQHandler
* 函 数 说 明:串口1中断服务函数
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void UART1_IRQHandler(void)
{
uint8_t TxRxBuffer;
if (USART_GetITStatus(CW_UART1, USART_IT_RC) != RESET)
{
// 接收一个字节
TxRxBuffer = USART_ReceiveData_8bit(CW_UART1);
u1_recv_buff[u1_recv_length++] = TxRxBuffer;
u1_recv_flag = 1;
// USART_SendData_8bit(CW_UART1, TxRxBuffer); // 将数据发回用于验证
// 清除标志位
USART_ClearITPendingBit(CW_UART1, USART_IT_RC);
}
}
将bsp_uart.h修改为下面的代码:
/*
* Change Logs:
* Date Author Notes
* 2024-06-12 LCKFB-LP first version
*/
#include "board.h"
//UARTx
#define DEBUG_USARTx CW_UART1
#define DEBUG_USART_CLK RCC_APB2_PERIPH_UART1
#define DEBUG_USART_APBClkENx RCC_APBPeriphClk_Enable2
#define DEBUG_USART_UclkFreq 64000000
//UARTx GPIO
#define DEBUG_USART_GPIO_CLK RCC_AHB_PERIPH_GPIOA
#define DEBUG_USART_TX_GPIO_PORT CW_GPIOA
#define DEBUG_USART_TX_GPIO_PIN GPIO_PIN_8
#define DEBUG_USART_RX_GPIO_PORT CW_GPIOA
#define DEBUG_USART_RX_GPIO_PIN GPIO_PIN_9
//GPIO AF
#define DEBUG_USART_AFTX PA08_AFx_UART1TXD()
#define DEBUG_USART_AFRX PA09_AFx_UART1RXD()
//中断
#define DEBUG_USART_IRQ UART1_IRQn
extern uint8_t u1_recv_buff[512]; // 接收缓冲区
extern uint16_t u1_recv_length; // 接收数据长度
extern uint8_t u1_recv_flag; // 接收完成标志位
void uart1_receive_clear(void);
void uart1_init(uint32_t __rate);
在文件bsp_as608.c中,编写如下代码。
/*
* Change Logs:
* Date Author Notes
* 2024-06-19 LCKFB-LP first version
*/
#include "bsp_as608.h"
#include "stdio.h"
#include "string.h"
#include "bsp_uart.h"
volatile unsigned char FPM10A_RECEICE_BUFFER[32];
unsigned int finger_id = 0;
const unsigned char FPM10A_Get_Device[10] ={0x01,0x00,0x07,0x13,0x00,0x00,0x00,0x00,0x00,0x1b};//口令验证
const unsigned char FPM10A_Pack_Head[6] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF}; //协议包头
const unsigned char FPM10A_Get_Img[6] = {0x01,0x00,0x03,0x01,0x00,0x05}; //获得指纹图像
const unsigned char FPM10A_Get_Templete_Count[6] ={0x01,0x00,0x03,0x1D,0x00,0x21 }; //获得模版总数
const unsigned char FPM10A_Search[11]={0x01,0x00,0x08,0x04,0x01,0x00,0x00,0x03,0xE7,0x00,0xF8}; //搜索指纹搜索范围0 - 999,使用BUFFER1中的特征码搜索
const unsigned char FPM10A_Search_0_9[11]={0x01,0x00,0x08,0x04,0x01,0x00,0x00,0x00,0x13,0x00,0x21}; //搜索0-9号指纹
const unsigned char FPM10A_Img_To_Buffer1[7]={0x01,0x00,0x04,0x02,0x01,0x00,0x08}; //将图像放入到BUFFER1
const unsigned char FPM10A_Img_To_Buffer2[7]={0x01,0x00,0x04,0x02,0x02,0x00,0x09}; //将图像放入到BUFFER2
const unsigned char FPM10A_Reg_Model[6]={0x01,0x00,0x03,0x05,0x00,0x09}; //将BUFFER1跟BUFFER2合成特征模版
const unsigned char FPM10A_Delete_All_Model[6]={0x01,0x00,0x03,0x0d,0x00,0x11};//删除指纹模块里所有的模版
volatile unsigned char FPM10A_Save_Finger[9]={0x01,0x00,0x06,0x06,0x01,0x00,0x0B,0x00,0x19};//将BUFFER1中的特征码存放到指定的位置
uint8_t u2_recv_buff[USART2_RECEIVE_LENGTH]; // 接收缓冲区
uint16_t u2_recv_length; // 接收数据长度
uint8_t u2_recv_flag; // 接收完成标志位
/******************************************************************
* 函 数 名 称:as608_gpio_config
* 函 数 说 明:初始化as608引脚
* 函 数 形 参:设置波特率 as608的默认波特率是57600
* 函 数 返 回:无
* 作 者:LC
* 备 注:as608的默认波特率是57600
******************************************************************/
void as608_gpio_config(uint32_t band_rate)
{
GPIO_InitTypeDef GPIO_InitStruct; // GPIO初始化结构体
AS608_GPIO_RCC_ENABLE(); // 使能GPIO时钟
AS608_UART_RCC_ENABLE(); // 使能UART时钟
GPIO_InitStruct.Pins = AS608_TX_PIN; // GPIO引脚
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; // 输出速度高
GPIO_Init(AS608_GPIO_PORT, &GPIO_InitStruct); // 初始化
GPIO_InitStruct.Pins = AS608_RX_PIN; // GPIO引脚
GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLUP; // 上拉输入
GPIO_Init(AS608_GPIO_PORT, &GPIO_InitStruct); // 初始化
GPIO_InitStruct.Pins = AS608_TOUCH_PIN; // GPIO引脚
GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLDOWN;// 下拉输入
GPIO_Init(AS608_GPIO_PORT, &GPIO_InitStruct); // 初始化
AS608_AF_UART_TX(); // UART_TX复用
AS608_AF_UART_RX(); // UART_RX复用
// 配置UART
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = band_rate; // 波特率
USART_InitStructure.USART_Over = USART_Over_16; // 配置USART的过采样率。
USART_InitStructure.USART_Source = USART_Source_PCLK; // 设置时钟源
USART_InitStructure.USART_UclkFreq = 64000000; //设置USART时钟频率(和主频一致即可)
USART_InitStructure.USART_StartBit = USART_StartBit_FE; //RXD下降沿开始
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 停止位1
USART_InitStructure.USART_Parity = USART_Parity_No ; // 不使用校验
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 不使用流控
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 收发模式
USART_Init(AS608_UART, &USART_InitStructure); // 初始化串口1
// 优先级,无优先级分组
NVIC_SetPriority(AS608_UART_IRQ, 0);
// UARTx中断使能
NVIC_EnableIRQ(AS608_UART_IRQ);
// 使能UARTx RC中断
USART_ITConfig(AS608_UART, USART_IT_RC, ENABLE);
}
/************************************************
函数名称 : uart2_send_byte
功 能 : 串口发送一个字节
参 数 : ucch:要发送的字节
返 回 值 :
作 者 : LC
*************************************************/
void uart2_send_byte(uint8_t ucch)
{
// 发送一个字节
USART_SendData_8bit(AS608_UART, (uint8_t)ucch);
// 等待发送完成
while( RESET == USART_GetFlagStatus(AS608_UART, USART_FLAG_TXE) ){}
}
/************************************************
函数名称 : uart2_receive_clear
功 能 : 清除串口接收的全部数据
参 数 : 无
返 回 值 : 无
作 者 : LC
*************************************************/
void uart2_receive_clear(void)
{
unsigned int i = 0;
for( i = 0; i < USART2_RECEIVE_LENGTH; i++ )
{
u2_recv_buff[ i ] = 0;
}
u2_recv_length = 0;
u2_recv_flag = 0;
}
/******************************************************************
* 函 数 名 称:get_as608_touch
* 函 数 说 明:获取是否有手指触摸识别区
* 函 数 形 参:无
* 函 数 返 回:0没有触摸 1有触摸
* 作 者:LC
* 备 注:无
******************************************************************/
char get_as608_touch(void)
{
if( TOUCH_IN == 1 )//触摸为1
{
//printf("Touch-1rn");
return 1;
}
else
{
//printf("Touch-0rn");
}
return 0;
}
/******************************************************************
* 函 数 名 称:FPM10A_Cmd_Send_Pack_Head
* 函 数 说 明:发送包头
* 函 数 形 参:无
* 函 数 返 回:wu
* 作 者:LC
* 备 注:无
******************************************************************/
void FPM10A_Cmd_Send_Pack_Head(void)
{
int i;
for(i=0;i<6;i++) //包头
{
uart2_send_byte(FPM10A_Pack_Head[i]);
}
}
/******************************************************************
* 函 数 名 称:FPM10A_Cmd_Check
* 函 数 说 明:发送指令
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void FPM10A_Cmd_Check(void)
{
int i=0;
FPM10A_Cmd_Send_Pack_Head(); //发送通信协议包头
for(i=0;i<10;i++)
{
uart2_send_byte(FPM10A_Get_Device[i]);
}
}
/******************************************************************
* 函 数 名 称:FPM10A_Receive_Data
* 函 数 说 明:接收反馈数据缓冲
* 函 数 形 参:ucLength 接收长度
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void FPM10A_Receive_Data(unsigned char ucLength)
{
unsigned char i = 0;
unsigned int timeout = 1000;//超时时间,单位Ms
//等待数据接收完毕
while(u2_recv_flag==0 && timeout > 0 )
{
delay_ms(1);
timeout--;
}
delay_ms(100); // 一定要加延时!!!
if( u2_recv_flag == 1 )
{
u2_recv_flag = 0;
for (i=0;i<ucLength;i++)
{
FPM10A_RECEICE_BUFFER[i] = u2_recv_buff[i];
}
uart2_receive_clear();
}
else
{
//Error, no data received
}
}
/******************************************************************
* 函 数 名 称:FPM10A_Cmd_Get_Img
* 函 数 说 明:获得指纹图像命令
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void FPM10A_Cmd_Get_Img(void)
{
unsigned char i;
FPM10A_Cmd_Send_Pack_Head(); //发送通信协议包头
for(i=0;i<6;i++) //发送命令 0x1d
{
uart2_send_byte(FPM10A_Get_Img[i]);
}
}
/******************************************************************
* 函 数 名 称:FINGERPRINT_Cmd_Img_To_Buffer1
* 函 数 说 明:将图像转换成特征码存放在Buffer1中
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void FINGERPRINT_Cmd_Img_To_Buffer1(void)
{
unsigned char i;
FPM10A_Cmd_Send_Pack_Head(); //发送通信协议包头
for(i=0;i<7;i++) //发送命令 将图像转换成 特征码 存放在 CHAR_buffer1
{
uart2_send_byte(FPM10A_Img_To_Buffer1[i]);
}
}
/******************************************************************
* 函 数 名 称:FINGERPRINT_Cmd_Img_To_Buffer2
* 函 数 说 明:将图像转换成特征码存放在Buffer2中
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void FINGERPRINT_Cmd_Img_To_Buffer2(void)
{
unsigned char i;
for(i=0;i<6;i++) //发送包头
{
uart2_send_byte(FPM10A_Pack_Head[i]);
}
for(i=0;i<7;i++) //发送命令 将图像转换成 特征码 存放在 CHAR_buffer1
{
uart2_send_byte(FPM10A_Img_To_Buffer2[i]);
}
}
/******************************************************************
* 函 数 名 称:FPM10A_Cmd_Search_Finger
* 函 数 说 明:搜索全部用户999枚
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void FPM10A_Cmd_Search_Finger(void)
{
unsigned char i;
FPM10A_Cmd_Send_Pack_Head(); //发送通信协议包头
for(i=0;i<11;i++)
{
uart2_send_byte(FPM10A_Search[i]);
}
}
/******************************************************************
* 函 数 名 称:FPM10A_Cmd_Reg_Model
* 函 数 说 明:将BUFFER1跟BUFFER2合成特征模版
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void FPM10A_Cmd_Reg_Model(void)
{
unsigned char i;
FPM10A_Cmd_Send_Pack_Head(); //发送通信协议包头
for(i=0;i<6;i++)
{
uart2_send_byte(FPM10A_Reg_Model[i]);
}
}
/******************************************************************
* 函 数 名 称:FINGERPRINT_Cmd_Delete_All_Model
* 函 数 说 明:删除指纹模块里的所有指纹模版
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void FINGERPRINT_Cmd_Delete_All_Model(void)
{
unsigned char i;
for(i=0;i<6;i++) //包头
{
uart2_send_byte(FPM10A_Pack_Head[i]);
}
for(i=0;i<6;i++) //命令合并指纹模版
{
uart2_send_byte(FPM10A_Delete_All_Model[i]);
}
}
/******************************************************************
* 函 数 名 称:FPM10A_Cmd_Save_Finger
* 函 数 说 明:保存指纹
* 函 数 形 参:保存指纹的位置(ID号)
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void FPM10A_Cmd_Save_Finger( unsigned int storeID )
{
unsigned long temp = 0;
unsigned char i;
FPM10A_Save_Finger[5] =(storeID&0xFF00)>>8;
FPM10A_Save_Finger[6] = (storeID&0x00FF);
for(i=0;i<7;i++) //计算校验和
{
temp = temp + FPM10A_Save_Finger[i];
}
FPM10A_Save_Finger[7]=(temp & 0x00FF00) >> 8; //存放校验数据
FPM10A_Save_Finger[8]= temp & 0x0000FF;
FPM10A_Cmd_Send_Pack_Head(); //发送通信协议包头
for(i=0;i<9;i++)
{
//发送命令 将图像转换成 特征码 存放在 CHAR_buffer1
uart2_send_byte(FPM10A_Save_Finger[i]);
}
}
/******************************************************************
* 函 数 名 称:key_scanf
* 函 数 说 明:按键功能 确定-取消
* 函 数 形 参:
* 函 数 返 回:0=未动作 1=确定 2=取消
* 作 者:LC
* 备 注:当前是使用串口来模拟按键,如果你有按键请自行修改
* 修改要求:按下确定键时返回1;按下取消键时,返回2。
******************************************************************/
char key_scanf(void)
{
/*************** 你的代码 ***************/
if(strstr( (const char*)u1_recv_buff, "Yes") != NULL )
{
uart1_receive_clear();
printf("key_scanf-YESrn");
return 1;//返回 确定键被按下
}
if(strstr( (const char*)u1_recv_buff, "No") != NULL )
{
uart1_receive_clear();
printf("key_scanf-NOrn");
return 2;//返回 取消键被按下
}
/*************** 你的代码 ***************/
return 0;
}
/******************************************************************
* 函 数 名 称:FPM10A_Add_Fingerprint
* 函 数 说 明:添加指纹
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void FPM10A_Add_Fingerprint(void)
{
// unsigned char id_show[3]={0,0,0};
unsigned char key_num= key_scanf();
finger_id=0;
printf("Do you want to add fingerprints? [Yes/No]rn");
while( key_num != 2 )//按返回键直接回到主菜单
{
key_num= key_scanf();
//按确认键开始录入指纹信息
if( key_num == 1 )
{
printf("start addrn");
while( key_num != 2 )//按下返回键退出录入返回fingerID调整状态
{
key_num= key_scanf();
FPM10A_Cmd_Get_Img(); //获得指纹图像
FPM10A_Receive_Data(12);
//判断接收到的确认码,等于0指纹获取成功
if(FPM10A_RECEICE_BUFFER[9]==0)
{
delay_ms(100);
FINGERPRINT_Cmd_Img_To_Buffer1();
FPM10A_Receive_Data(12);
delay_ms(1000);
while( key_num != 2 )
{
key_num= key_scanf();
FPM10A_Cmd_Get_Img(); //获得指纹图像
FPM10A_Receive_Data(12);
//判断接收到的确认码,等于0指纹获取成功
if(FPM10A_RECEICE_BUFFER[9]==0)
{
delay_ms(200);
printf("successfully added, ID = %drn",finger_id);
FINGERPRINT_Cmd_Img_To_Buffer2();
FPM10A_Receive_Data(12);
FPM10A_Cmd_Reg_Model();//转换成特征码
FPM10A_Receive_Data(12);
//保存指纹
FPM10A_Cmd_Save_Finger(finger_id);
FPM10A_Receive_Data(12);
delay_ms(1000);
finger_id=finger_id+1;
break;
}
}
break;
}
}
}
}
}
/******************************************************************
* 函 数 名 称:FPM10A_Find_Fingerprint
* 函 数 说 明:搜索指纹
* 函 数 形 参:无
* 函 数 返 回:指纹ID号
* 作 者:LC
* 备 注:255:未查到 其他:查找到了
******************************************************************/
unsigned int FPM10A_Find_Fingerprint(void)
{
unsigned int find_fingerid = 255;
// printf("Please put your finger inrn");
if( get_as608_touch() == 1 )//有手指触摸识别区
{
FPM10A_Cmd_Get_Img(); //获得指纹图像
FPM10A_Receive_Data(12);
//判断接收到的确认码,等于0指纹获取成功
if(FPM10A_RECEICE_BUFFER[9]==0)
{
delay_ms(100);
FINGERPRINT_Cmd_Img_To_Buffer1();
FPM10A_Receive_Data(12);
FPM10A_Cmd_Search_Finger();
FPM10A_Receive_Data(16);
if(FPM10A_RECEICE_BUFFER[9] == 0) //搜索成功
{
//拼接指纹ID数
find_fingerid = FPM10A_RECEICE_BUFFER[10]*256 + FPM10A_RECEICE_BUFFER[11];
printf("ID = %drn",find_fingerid);
delay_ms(500);
}
else //没有找到
{
printf("not foundrn");
}
}
}
return find_fingerid;
}
/******************************************************************
* 函 数 名 称:FPM10A_Delete_All_Fingerprint
* 函 数 说 明:删除所有存贮的指纹库
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void FPM10A_Delete_All_Fingerprint(void)
{
unsigned char key_num=0;
printf("Whether to delete fingerprint ? [Yes/No]rn");
do
{
key_num = key_scanf();
if(key_num == 1 )//点击确定键
{
printf("deletingrn");
delay_ms(300);
FINGERPRINT_Cmd_Delete_All_Model();
FPM10A_Receive_Data(12);
printf("Have all been clearedrn");
break;
}
if( u2_recv_flag == 1 )
{
u2_recv_flag = 0;
printf("rev = %srn", u2_recv_buff);
}
}while( key_num != 2 );//没有点击取消键,则继续循环
}
/******************************************************************
* 函 数 名 称:Device_Check
* 函 数 说 明:模块检查
* 函 数 形 参:无
* 函 数 返 回:0未检测到模块或者模块异常 1检测到模块并且通信成功
* 作 者:LC
* 备 注:返回0时要注意接线是否正确、串口配置是否可用
******************************************************************/
char Device_Check(void)
{
FPM10A_RECEICE_BUFFER[9]=1; //串口数组第九位可判断是否通信正常
FPM10A_Cmd_Check(); //单片机向指纹模块发送校对命令
FPM10A_Receive_Data(12); //将串口接收到的数据转存
if(FPM10A_RECEICE_BUFFER[9] == 0) //判断数据低第9位是否接收到0
{
return 1;
}
return 0;
}
/******************************************************************
* 函 数 名 称:AS608_UART_IRQHandler
* 函 数 说 明:串口2中断服务函数
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void AS608_UART_IRQHandler(void)
{
if(USART_GetITStatus(AS608_UART, USART_IT_RC) == SET)//判断是不是真的有中断发生
{
u2_recv_buff[u2_recv_length++] = USART_ReceiveData(AS608_UART);// 把接收到的数据放到缓冲区中
u2_recv_buff[u2_recv_length] = ''; // 数据接收完毕,数组结束标志
u2_recv_flag = 1;
USART_ClearITPendingBit(AS608_UART, USART_IT_RC); //已经处理就清楚标志位
}
}
在文件bsp_as608.h中,编写如下代码。
/*
* Change Logs:
* Date Author Notes
* 2024-06-19 LCKFB-LP first version
*/
#ifndef _BSP_AS608_H_
#define _BSP_AS608_H_
#include "board.h"
#define AS608_GPIO_RCC_ENABLE() __RCC_GPIOA_CLK_ENABLE() // GPIO时钟
#define AS608_UART_RCC_ENABLE() __RCC_UART2_CLK_ENABLE() // 串口2的时钟
#define AS608_AF_UART_TX() PA02_AFx_UART2TXD()
#define AS608_AF_UART_RX() PA03_AFx_UART2RXD()
#define AS608_GPIO_PORT CW_GPIOA // GPIO端口
#define AS608_TX_PIN GPIO_PIN_2 // 串口TX的引脚
#define AS608_RX_PIN GPIO_PIN_3 // 串口RX的引脚
#define AS608_TOUCH_PIN GPIO_PIN_1 // TOUCH的引脚
#define AS608_UART CW_UART2 // 串口2
#define AS608_UART_IRQ UART2_IRQn // 串口2中断
#define AS608_UART_IRQHandler UART2_IRQHandler // 串口2中断服务函数
#define TOUCH_IN GPIO_ReadPin( AS608_GPIO_PORT, AS608_TOUCH_PIN )
/* 串口缓冲区的数据长度 */
#define USART2_RECEIVE_LENGTH 1024
extern uint8_t u2_recv_buff[USART2_RECEIVE_LENGTH]; // 接收缓冲区
extern uint16_t u2_recv_length; // 接收数据长度
extern uint8_t u2_recv_flag; // 接收完成标志位
void as608_gpio_config(uint32_t band_rate);
char get_as608_touch(void);
void uart2_receive_clear(void);
char Device_Check(void);
void FPM10A_Add_Fingerprint(void);//添加指纹
unsigned int FPM10A_Find_Fingerprint(void);//查找指纹
void FPM10A_Delete_All_Fingerprint(void);
#endif
04、移植验证
在自己工程中的main主函数中,编写如下。
/*
* Change Logs:
* Date Author Notes
* 2024-06-19 LCKFB-LP first version
*/
#include "board.h"
#include "stdio.h"
#include "bsp_uart.h"
#include "bsp_as608.h"
int32_t main(void)
{
board_init(); // 开发板初始化
uart1_init(57600U); // 串口1波特率115200
as608_gpio_config(57600U);
printf("AS608 demo startrn");
Device_Check();//模块检测
FPM10A_Delete_All_Fingerprint(); //是否删除全部指纹
FPM10A_Add_Fingerprint();//是否添加指纹
while(1)
{
FPM10A_Find_Fingerprint();//查找指纹
}
}
上电现象:
模块移植成功案例代码:
链接:https://pan.baidu.com/s/13OYXBko_GfKrS4aRVg1VLg?pwd=LCKF
提取码:LCKF