基于STM32单片机设计指纹考勤机+上位机管理

1. 前言

随着信息科学技术的不断进步,信息科学技术已进入到了当今生活的方方面面,尤其是每个行业的经管领域,这类智能化信息技术处理是提高效率、从严管制、公平审查较为有效的方法。考勤登记,作为企业职工的基本管理,是对职工每日出勤管理的根本根据。但是,目前我国绝大多数企业在考勤登记时,依然利用的是古板的考勤方法,比如: 人工注册、打卡、机器打卡等,不光考勤速度较为缓慢,并且在考勤登记时候要专门职员在一边进行记载、统计数据、制成EXCEL表,而报表做完后最终交到主管手里时,有时候时间已过了好几天,根本不行,也不可以施展考勤真实的监视作用。并且还有可能呈现考勤数据不准确,考勤职员纪录犯错,乃至卖弄虚假的这种现象,极度破坏了企业对职工的日常管制。如今使用电脑来管制考勤的事情,很大程度上降低了就业人员的任务量,促使作事效率得以升高,使本来繁杂、索然无味的工作变的简单。提高中小型企业的考勤效率、体现现代化考勤的气氛。

设计总结:

(1)单片机采集指纹数据。将指纹ID传递给上位机进行管理。

(2)考勤记录、打卡全部在上位机完成。 单片机只是完成指纹的采集。

image-20220427101331395

image-20220427101419140

image-20220427101548703

image-20220427101653029

image-20220427101730939

image-20220427100346181

image-20220427100110644

image-20220427100135627

image-20220427100151748

image-20220427100212981

image-20220427100247351

2. 硬件选型

2.1 STM32系统板

主控CPU采用STM32F103RCT6,这颗芯片包括48 KB SRAM、256 KB Flash、2个基本定时器、4个通用定时器、2个高级定时器、51个通用IO口、5个串口、2个DMA控制器、3个SPI、2个I2C、1个USB、1个CAN、3个12位ADC、1个12位DAC、1个SDIO接口,芯片属于大容量类型,配置较高,整体符合硬件选型设计。当前选择的这款开发板自带了一个1.4寸的TFT-LCD彩屏,可以显示当前传感器数据以及一些运行状态信息。

image-20220319202557220

2.2 指纹模块

AS608指纹识别模块是⼀款⾼性能的光学指纹识别模块。AS608模块采⽤了国内著名指纹识别芯⽚公司杭州晟元芯⽚技术有限公司(Synochip)的 AS608指纹识别芯⽚。芯⽚内置DSP运算单元,集成了指纹识别算法,能⾼效快速采集图像并识别指纹特征。模块配备了串⼝、USB通讯接⼝,⽤户⽆需研究复杂的图像处理及指纹识别算法,只需通过简单的串⼝、USB 按照通讯协议便可控制模块。本模块可应⽤于各种考勤机、保险箱柜、指纹门禁系统、指纹锁等场合。

供电电压:3.3V(切勿接5V,容易烧毁芯片)
供电电流:< 60mA
指纹图像录入时间:< 1s
搜索时间:< 1.0s(1:500时,均值)
可录入指纹数量:300
通讯接口:USB/USART

image-20220417220251999

image-20220421164759567

image-20220421164814904

3. 上位机程序设计

3.1 开发环境

上位机软件采用Qt框架设计,Qt是一个跨平台的C++图形用户界面应用程序框架。Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。简单来说,QT可以很轻松的帮你做带界面的软件,甚至不需要你投入很大精力。

QT官网: https://www.qt.io/

image-20220314143105032

QT学习入门实战专栏文章: https://blog.csdn.net/xiaolong1126626497/category_11400392.html

QT5.12.6的下载地址:
https://download.qt.io/archive/qt/5.12/5.12.6/

打开下载链接后选择下面的版本进行下载:

qt-opensource-windows-x86-5.12.6.exe 13-Nov-2019 07:28 3.7G Details

软件安装时断网安装,否则会提示输入账户。

安装的时候,第一个复选框里勾选一个mingw 32编译器即可,其他的不管默认就行,直接点击下一步继续安装。

image-20220417145923643

选择MinGW 32-bit 编译器:

image-20220417150002770

选择MinGW 32-bit 编译器:

image-20220417150031913

3.2 设计效果

image-20220421173414325

image-20220427100009358

4. STM32程序设计

如果需要完整的资料,可以去这里下载:
https://download.csdn.net/download/xiaolong1126626497/85896720

这是本项目演示视频:

基于STM32设计指纹考勤机+上位机管理

4.1 程序下载

点击下载编程之后,按下开发板上的复位键,启动下载。

image-20220427095346961

4.2 硬件接线

硬件连接方式:
1. 指纹模块接线
PA2(TX)---指纹模块的RX(白线)
PA3(RX)---指纹模块的TX(黄线)
VCC---3.3v(红线)
GND---GND(黑线)
VCC---3.3V(绿线)--触摸感应电源线
PA6---触摸感应线-高电平有效(蓝线)


2. 板载LED灯接线
LED1---PA8
LED2---PD2

3. 板载按键接线
K0---PA0 
K1---PC5 
K2---PA15

4.3 keil工程

image-20220427095823393

4.4 通信协议约定

上位机下发指令:

//录入指纹 1表示ID
$dev_cmd_lu_ru_zhi_wen:1

//删除指纹
$dev_cmd_del_zhi_wen:1



设备上传指令:

//录入OK
$update_lu_ru_ok,

//录入error
$update_lu_ru_error,

//查找成功ID--指纹查找成功
$update_find,1,

4.5 main.c代码

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include <string.h>
#include "timer.h"
#include <string.h>
#include <stdlib.h>
#include "as608.h"



u16 ValidN;//模块内有效模板个数
SysPara AS608Para;//指纹模块AS608参数


void Add_FR(int ID);	//录指纹
void Del_FR(int num);	//删除指纹
void press_FR(void);//刷指纹
void ShowErrMessage(u8 ensure);

int ID=0;
char *data_p;
int main()
{
    
    
    u8 ensure;
    u32 i=0;
    u8 key=0;
    u32 time_cnt=0;
    JTAG_Set(JTAG_SWD_DISABLE); //释放PA15
    LED_Init();  //LED灯初始化
    KEY_Init();  //按键初始化

    delay_init(72);
    USART1_Init(115200);   //串口1初始化-打印调试信息
    TIMER1_Init(72,20000); //定时器2初始化
    USART2_Init(57600);     //串口2初始化-打印调试信息  
    TIMER2_Init(72,20000); //定时器2初始化
    PS_StaGPIO_Init();	   //初始化FR读状态引脚	
  
    printf("系统正常运行!\r\n");
    
    //与AS608模块握手
    while(PS_HandShake(&AS608Addr))
    {
    
    
      printf("连接指纹模块失败....\r\n");
      delay_ms(1000);	  
    }    
    printf("指纹模块连接成功.....\r\n");
    
    printf("开始读库指纹个数.\r\n");
    ensure=PS_ValidTempleteNum(&ValidN);//读库指纹个数
    if(ensure!=0x00)
    {
    
    
        printf("ensure:%s\r\n",ensure);//显示确认码错误信息	
    }

     printf("开始读AS608模块参数 .\r\n");
    ensure=PS_ReadSysPara(&AS608Para);  //读AS608模块参数 
    if(ensure==0x00)
    {
    
    
        printf("RemainNum:%d    Level:%d\r\n",AS608Para.PS_max-ValidN,AS608Para.PS_level);//显示剩余指纹数量和安全等级
    }
    else
    {
    
    
        printf("ensure:%s\r\n",ensure);	
    }
      
    
    //如果第一次使用,有必要全部清除之后再使用
    //PS_Empty();//清空指纹库
    

  
   // printf("开始删除指纹 .\r\n");
    //Del_FR();
    
    while(1)
    {
    
    
      
      if(USART1_RX_FLAG)
      {
    
    
          USART1_RX_BUFFER[USART1_RX_CNT]='\0';
          printf("RX:%s\r\n",USART1_RX_BUFFER);
          
          //如果是录入指纹
          if(strstr((char*)USART1_RX_BUFFER,"$dev_cmd_lu_ru_zhi_wen:"))
          {
    
    
                printf("开始录指纹 .\r\n");
                
                 data_p=strstr((char*)USART1_RX_BUFFER,"$dev_cmd_lu_ru_zhi_wen:");
                  
                  if(data_p)
                  {
    
    
                      data_p+=strlen("$dev_cmd_lu_ru_zhi_wen:");
                      ID=atoi(data_p);
                      printf("ID=%d\r\n",ID);
                      if(ID>=0)
                      {
    
    
                          //录指纹
                          Add_FR(ID);  
                      }
                  }
                  else
                  {
    
    
                      printf("指纹ID解析失败.\r\n");
                  }   
          }
        
          //如果是删除指纹
          if(strstr((char*)USART1_RX_BUFFER,"$dev_cmd_del_zhi_wen:"))
          {
    
    
                printf("开始录指纹 .\r\n");
                
                 data_p=strstr((char*)USART1_RX_BUFFER,"$dev_cmd_del_zhi_wen:");
                  
                  if(data_p)
                  {
    
    
                      data_p+=strlen("$dev_cmd_del_zhi_wen:");
                      ID=atoi(data_p);
                      printf("ID=%d\r\n",ID);
                      if(ID>=0)
                      {
    
    
                          //删除指纹
                          Del_FR(ID);  
                      }
                  }
                  else
                  {
    
    
                      printf("指纹ID解析失败.\r\n");
                  }   
          }
          
        
          USART1_RX_FLAG=0;
          USART1_RX_CNT=0;
          memset(USART1_RX_BUFFER,0,sizeof(USART1_RX_BUFFER));
      }
      
          
         //刷指纹
        press_FR();
    
      
        LED1=!LED1;
        delay_ms(100);
    }
}


//录指纹
void Add_FR(int ID)
{
    
    
	u8 i=0,ensure,processnum=0;
	while(1)
	{
    
    
		switch (processnum)
		{
    
    
			case 0:
				i++;
        printf("请按下手指.\r\n");
				ensure=PS_GetImage();
				if(ensure==0x00) 
				{
    
    
					ensure=PS_GenChar(CharBuffer1);//生成特征
					if(ensure==0x00)
					{
    
    
            printf("指纹正确.\r\n");
						i=0;
						processnum=1;//跳到第二步						
					}else ShowErrMessage(ensure);				
				}else ShowErrMessage(ensure);						
				break;
			
			case 1:
				i++;
				printf("再按一次手指.\r\n");
				ensure=PS_GetImage();
				if(ensure==0x00) 
				{
    
    
					ensure=PS_GenChar(CharBuffer2);//生成特征			
					if(ensure==0x00)
					{
    
    
						printf("指纹正确.\r\n");
						i=0;
						processnum=2;//跳到第三步
					}else ShowErrMessage(ensure);	
				}else ShowErrMessage(ensure);		
				break;

			case 2:
				printf("对比两次指纹.\r\n");
				ensure=PS_Match();
				if(ensure==0x00) 
				{
    
    
					printf("两次指纹是一样的.\r\n");
					processnum=3;//跳到第四步
				}
				else 
				{
    
    
					printf("对比失败,请重新按手指.\r\n");
          ShowErrMessage(ensure);
					i=0;
					processnum=0;//跳回第一步		
				}
				delay_ms(1000);
				break;

			case 3:
				printf("产生一个指纹模板.\r\n");
				ensure=PS_RegModel();
				if(ensure==0x00) 
				{
    
    
					printf("生成指纹模板成功.\r\n");//生成指纹模板成功
					processnum=4;//跳到第五步
				}else {
    
    processnum=0;ShowErrMessage(ensure);}
				delay_ms(1000);
				break;
				
			case 4:	
				ensure=PS_StoreChar(CharBuffer2,ID);//储存模板
				if(ensure==0x00) 
				{
    
    		
          printf("$update_lu_ru_ok,\r\n");
					printf("添加指纹成功.\r\n");
					PS_ValidTempleteNum(&ValidN);//读库指纹个数
					printf("显示剩余指纹个数.\r\n");
					return ;
				}else {
    
    processnum=0;ShowErrMessage(ensure);}					
				break;				
		}
		delay_ms(1000);
    LED2=!LED2;
    
		if(i==10)//超过10次没有按手指则退出
		{
    
    
      printf("超过10次没有按手指---退出...\r\n");
       printf("$update_lu_ru_error,\r\n");
			break;	
		}				
	}
}


//显示确认码错误信息
void ShowErrMessage(u8 ensure)
{
    
    
	printf("%s\r\n",(u8*)EnsureMessage(ensure));
}


//刷指纹
void press_FR(void)
{
    
    
	SearchResult seach;
	u8 ensure;
	char *str;
	ensure=PS_GetImage();
	if(ensure==0x00)//获取图像成功 
	{
    
    	
		ensure=PS_GenChar(CharBuffer1);
		if(ensure==0x00) //生成特征成功
		{
    
    		
			ensure=PS_HighSpeedSearch(CharBuffer1,0,300,&seach);
			if(ensure==0x00)//搜索成功
			{
    
    		
        // $find,1,  //告诉主机签到成功.    ID为1的指纹用户   
        printf("$update_find,%d,\r\n",seach.pageID);
        
				printf("搜索指纹成功	.\r\n");
				printf("Match ID:%d  Match score:%d",seach.pageID,seach.mathscore);//显示匹配指纹的ID和分数
			}
			else 
				ShowErrMessage(ensure);					
	  }
		else
			ShowErrMessage(ensure);
	 delay_ms(1000);//延时后清除显示
	}
}


//删除指纹
void Del_FR(int num)
{
    
    
	u8  ensure;
	printf("显示删除指纹: %d.\r\n",num);
  
	printf("0=< ID <=299\r\n");
	delay_ms(50);
  
	num=1;//这个1测试。--删除指纹的ID。
   if(num==0xFF00)
		ensure=PS_Empty();//清空指纹库
	else 
		ensure=PS_DeletChar(num,1);//删除单个指纹
	if(ensure==0)
	{
    
    
		printf("删除指纹成功.\r\n");
	}
  else
		ShowErrMessage(ensure);	
	delay_ms(1500);//延时后清除显示
	PS_ValidTempleteNum(&ValidN);//读库指纹个数
  
  printf("显示剩余指纹个数:%d\r\n",AS608Para.PS_max-ValidN);
}

猜你喜欢

转载自blog.csdn.net/xiaolong1126626497/article/details/126172383