• 基于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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    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,
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    4.5 main.c代码

    #include "stm32f10x.h"
    #include "led.h"
    #include "delay.h"
    #include "key.h"
    #include "usart.h"
    #include 
    #include "timer.h"
    #include 
    #include 
    #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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
  • 相关阅读:
    Node.js的入门及模块化
    第三章:最新版零基础学习 PYTHON 教程(第二节 - Python 运算符—Python 算术运算符)
    SQL-方法论
    【Maven教程】(九):使用 Maven 进行测试 ~
    【Log日志】springboot项目中集成Log日志详解
    java计算机毕业设计ssm的KTV点歌系统(源码+系统+mysql数据库+Lw文档)
    算法进阶-2sat-cf-1385G
    python 中指定GPU乱序解决方案
    CloudCompare——泊松重建
    架构风格相关内容
  • 原文地址:https://blog.csdn.net/xiaolong1126626497/article/details/126172383