一、系统架构与硬件选型1.1 硬件连接表以AS608光学指纹模块为例指纹模块引脚STM32F103C8T6引脚说明VCC3.3V / 5VAS608支持3.3V-5V建议5V供电以保证LED亮度GNDGND共地TXDPA3 (USART2_RX)模块发送STM32接收RXDPA2 (USART2_TX)模块接收STM32发送TouchPA0触摸感应输出高电平有效可选1.2 系统工作流程[用户触摸] - [STM32唤醒] - [发送“采集指纹”指令] - [模块采集图像] - [生成特征值] - [搜索指纹库] - [返回结果] - [控制继电器/LED显示]二、核心代码实现2.1 指纹模块协议定义fingerprint.h#ifndef__FINGERPRINT_H#define__FINGERPRINT_H#includestm32f10x.h#includestring.h// AS608 指令定义#defineFP_HEAD0xEF01#defineFP_ADDR0xFFFFFFFF// 指令包标识#defineCMD_GENIMG0x01// 采集图像#defineCMD_GENCHAR0x02// 生成特征#defineCMD_MATCH0x03// 精确比对1:1#defineCMD_SEARCH0x04// 搜索指纹1:N#defineCMD_REG_MODEL0x05// 合并特征生成模板#defineCMD_STORE0x06// 储存模板#defineCMD_DELETE0x0C// 删除模板#defineCMD_UP_CHAR0x08// 上传特征#defineCMD_DOWN_CHAR0x09// 下载特征#defineCMD_UP_IMAGE0x0A// 上传图像#defineCMD_DOWN_IMAGE0x0B// 下载图像#defineCMD_EMPTY0x0D// 清空指纹库#defineCMD_READ_CONF0x0E// 读系统参数// 确认码返回值#defineACK_OK0x00// 指令执行完毕或OK#defineACK_FAIL0x01// 数据包接收错误#defineACK_NO_FINGER0x02// 没有手指#defineACK_ENTRY_FAIL0x03// 录入指纹图像失败#defineACK_DISORDER0x06// 指纹库满#defineACK_NOT_FOUND0x09// 没搜索到// 缓冲区定义#defineCHAR_BUFFER_A0x01#defineCHAR_BUFFER_B0x02// 全局变量externuint8_tfp_rx_buffer[64];externuint8_tfp_tx_buffer[64];externuint8_tfp_rx_flag;// 函数声明voidFP_Init(uint32_tbaudrate);voidFP_SendCmd(uint8_tcmd,uint8_t*data,uint8_tlen);uint8_tFP_GetResponse(void);uint8_tFP_GetImage(void);uint8_tFP_GenChar(uint8_tbuffer_id);uint8_tFP_Search(uint8_tbuffer_id,uint16_tstart_page,uint16_tpage_num);uint8_tFP_Store(uint8_tbuffer_id,uint16_tpage_id);uint8_tFP_Delete(uint16_tpage_id,uint16_tnum);uint8_tFP_Empty(void);voidFP_ShowSystemParams(void);#endif2.2 串口驱动与指令发送fingerprint.c#includefingerprint.h#includeusart.h#includedelay.huint8_tfp_rx_buffer[64];uint8_tfp_rx_flag0;staticuint8_trx_cnt0;/** * brief 指纹模块串口初始化 */voidFP_Init(uint32_tbaudrate){USART_InitTypeDef USART_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);// PA2 - TX, PA3 - RXGPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_PinGPIO_Pin_2;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF_PP;GPIO_Init(GPIOA,GPIO_InitStructure);GPIO_InitStructure.GPIO_PinGPIO_Pin_3;GPIO_InitStructure.GPIO_ModeGPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA,GPIO_InitStructure);USART_InitStructure.USART_BaudRatebaudrate;USART_InitStructure.USART_WordLengthUSART_WordLength_8b;USART_InitStructure.USART_StopBitsUSART_StopBits_1;USART_InitStructure.USART_ParityUSART_Parity_No;USART_InitStructure.USART_HardwareFlowControlUSART_HardwareFlowControl_None;USART_InitStructure.USART_ModeUSART_Mode_Rx|USART_Mode_Tx;USART_Init(USART2,USART_InitStructure);USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);USART_Cmd(USART2,ENABLE);printf(Fingerprint Module Init OK\r\n);}/** * brief 发送指令包 * param cmd: 指令码 * param data: 附加数据 * param len: 数据长度 */voidFP_SendCmd(uint8_tcmd,uint8_t*data,uint8_tlen){uint16_tchecksum0;uint8_ti;// 包头USART_SendData(USART2,0xEF);while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);USART_SendData(USART2,0x01);while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);// 地址USART_SendData(USART2,0xFF);while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);USART_SendData(USART2,0xFF);while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);USART_SendData(USART2,0xFF);while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);USART_SendData(USART2,0xFF);while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);// 包标识 (0x01 命令包)USART_SendData(USART2,0x01);while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);// 包长度 (指令码1字节 数据长度 校验和2字节)uint16_tpkg_len1len2;USART_SendData(USART2,pkg_len8);while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);USART_SendData(USART2,pkg_len0xFF);while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);// 指令码USART_SendData(USART2,cmd);while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);checksumcmd;// 数据for(i0;ilen;i){USART_SendData(USART2,data[i]);while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);checksumdata[i];}// 校验和USART_SendData(USART2,checksum8);while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);USART_SendData(USART2,checksum0xFF);while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);}/** * brief 获取图像 */uint8_tFP_GetImage(void){FP_SendCmd(CMD_GENIMG,NULL,0);returnFP_GetResponse();}/** * brief 生成特征 * param buffer_id: 缓冲区号 (1 or 2) */uint8_tFP_GenChar(uint8_tbuffer_id){uint8_tdata[1]{buffer_id};FP_SendCmd(CMD_GENCHAR,data,1);returnFP_GetResponse();}/** * brief 搜索指纹 * param buffer_id: 缓冲区号 * param start_page: 起始页 * param page_num: 页数 */uint8_tFP_Search(uint8_tbuffer_id,uint16_tstart_page,uint16_tpage_num){uint8_tdata[5];data[0]buffer_id;data[1]start_page8;data[2]start_page0xFF;data[3]page_num8;data[4]page_num0xFF;FP_SendCmd(CMD_SEARCH,data,5);returnFP_GetResponse();}/** * brief 存储模板 */uint8_tFP_Store(uint8_tbuffer_id,uint16_tpage_id){uint8_tdata[3];data[0]buffer_id;data[1]page_id8;data[2]page_id0xFF;FP_SendCmd(CMD_STORE,data,3);returnFP_GetResponse();}/** * brief 删除指纹 */uint8_tFP_Delete(uint16_tpage_id,uint16_tnum){uint8_tdata[4];data[0]page_id8;data[1]page_id0xFF;data[2]num8;data[3]num0xFF;FP_SendCmd(CMD_DELETE,data,4);returnFP_GetResponse();}/** * brief 清空指纹库 */uint8_tFP_Empty(void){FP_SendCmd(CMD_EMPTY,NULL,0);returnFP_GetResponse();}/** * brief 获取系统参数 */voidFP_ShowSystemParams(void){FP_SendCmd(CMD_READ_CONF,NULL,0);Delay_ms(200);// 解析fp_rx_buffer中的状态寄存器、容量等信息printf(Status: 0x%02X\r\n,fp_rx_buffer[7]);}/** * brief 获取响应 */uint8_tFP_GetResponse(void){uint32_ttimeout0;while(fp_rx_flag0){Delay_ms(10);timeout;if(timeout200)// 2秒超时{printf(FP Response Timeout!\r\n);return0xFF;}}fp_rx_flag0;returnfp_rx_buffer[7];// 返回确认码}2.3 中断接收stm32f10x_it.c#includefingerprint.hvoidUSART2_IRQHandler(void){if(USART_GetITStatus(USART2,USART_IT_RXNE)!RESET){uint8_tdataUSART_ReceiveData(USART2);if(rx_cntsizeof(fp_rx_buffer)){fp_rx_buffer[rx_cnt]data;}// 简单判断是否接收完成通常看最后两个字节校验和这里简化为固定长度if(rx_cnt12)// 假设最小包长度为12{fp_rx_flag1;rx_cnt0;}}}2.4 主程序逻辑main.c#includestm32f10x.h#includefingerprint.h#includeusart.h#includedelay.h#includeled.h#includerelay.hintmain(void){SystemInit();Delay_Init();USART1_Init(115200);// 调试串口LED_Init();Relay_Init();// 初始化指纹模块波特率57600AS608默认FP_Init(57600);uint8_tresult;uint16_tuser_id0;while(1){printf(Place your finger...\r\n);LED_Blink(500);// LED闪烁提示// 1. 采集图像resultFP_GetImage();if(result!ACK_OK){if(resultACK_NO_FINGER)printf(No finger detected.\r\n);elseprintf(Get Image Failed: 0x%02X\r\n,result);Delay_ms(1000);continue;}printf(Image captured.\r\n);// 2. 生成特征resultFP_GenChar(CHAR_BUFFER_A);if(result!ACK_OK){printf(Generate Char Failed: 0x%02X\r\n,result);Delay_ms(1000);continue;}// 3. 搜索指纹库printf(Searching...\r\n);resultFP_Search(CHAR_BUFFER_A,0,100);// 搜索前100个指纹if(resultACK_OK){// 搜索成功fp_rx_buffer中包含页码和匹配度user_id(fp_rx_buffer[8]8)|fp_rx_buffer[9];printf(Match Found! User ID: %d, Score: %d\r\n,user_id,fp_rx_buffer[10]);// 控制继电器开门Relay_ON();LED_ON();Delay_ms(3000);Relay_OFF();LED_OFF();}elseif(resultACK_NOT_FOUND){printf(No Match Found.\r\n);LED_Blink(100);// 快闪表示拒绝}else{printf(Search Error: 0x%02X\r\n,result);}Delay_ms(2000);// 防止重复识别}}三、指纹录入流程需在上位机或按键触发录入通常需要两步录入两次以确认uint8_tEnroll_Fingerprint(uint16_tuser_id){uint8_tres;printf(Enroll: Place finger first time\r\n);resFP_GetImage();if(res!ACK_OK)returnres;resFP_GenChar(CHAR_BUFFER_A);if(res!ACK_OK)returnres;printf(Remove finger\r\n);Delay_ms(2000);printf(Enroll: Place finger second time\r\n);resFP_GetImage();if(res!ACK_OK)returnres;resFP_GenChar(CHAR_BUFFER_B);if(res!ACK_OK)returnres;// 精确比对两次特征是否一致// 这里省略精确比对指令直接存储resFP_Store(CHAR_BUFFER_A,user_id);if(resACK_OK)printf(Enroll Success! ID: %d\r\n,user_id);returnres;}参考代码 基于STM32的指纹识别www.youwenfan.com/contentcsu/56232.html四、调试与避坑指南4.1 常见问题排查现象原因解决方案无响应波特率不匹配AS608默认57600STM32串口初始化需一致图像采集失败手指太干/太湿提示用户湿润手指或擦拭传感器搜索速度慢搜索范围过大缩小搜索页码范围或升级为1:N搜索算法误识率高指纹质量差增加录入时的图像质量检测录入时旋转手指4.2 硬件优化建议电源稳定性指纹模块工作时电流较大100mA建议在VCC并联100uF电容。抗干扰指纹模块尽量远离电机、继电器等强干扰源。触摸唤醒使用模块的Touch引脚连接STM32外部中断平时STM32休眠触摸时唤醒降低功耗。五、总结这套方案实现了基于STM32的指纹录入、存储、1:N搜索全流程。核心在于串口协议的正确封装和对返回状态码的严谨处理。应用场景智能门锁考勤打卡机保险柜/枪柜身份授权终端