找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2397|回复: 1
收起左侧

单片机指纹识别程序+PCB文件设计

[复制链接]
ID:363250 发表于 2020-2-16 11:25 | 显示全部楼层 |阅读模式
本指纹识别设计包含资料、程序、PCB等
制作出来的实物图如下:
IMG_4524.JPG 实物照片.JPG

Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
原理图.png PCB图.png

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #include"lcd1602.h"


  4. sbit buzzer=P2^0;  //蜂鸣器        低电平打开蜂鸣器

  5. sbit red=   P1^0;  //红色灯 表示录入模式
  6. sbit green= P1^1;  //绿色灯 表示识别模式

  7. sbit k2=P3^4; //录入一次指纹
  8. sbit k1=P3^3; //模式识别转换
  9. sbit k3=P3^2; //清除所有指纹(10个指纹清除)

  10. #define Max_User 10
  11. #define error 2
  12.    
  13. unsigned char         SaveNumber=0,searchnum=0;
  14. unsigned int          SearchNumber=0;               
  15. unsigned int         clk0=0;

  16. unsigned char str[3]={0,'\0','\0'};

  17. unsigned char code Identify[16]="Lock:   Idenfity";
  18. unsigned char code Input[16]   ="Lock:   Input   ";

  19. bit modeflag=0,clearallflag=0,changeflag=0;

  20. // modeflag=0 为识别模式 modeflag=1为录入指纹模式
  21. //每成功录入一次指纹 SaveNumber++

  22. //////////////////////////////////////常用指令定义/////////////////////////////

  23. //Verify  Password   :验证设备握手口令
  24. unsigned char code VPWD[16]={16,0X01 ,0Xff,0xff,0xff,0xff, 0x01,0,7,0x13,0x00,0x00,0x00,0x00,0x00,0x1b};         //回送12个

  25. //设置设备握手口令
  26. unsigned char code STWD[16]={16,0X01 ,0Xff,0xff,0xff,0xff, 0x01,0,7,0x12,0x00,0x00,0x00,0x00,0x00,0x1a};         //回送12个

  27. //GetImage           :探测手指并从传感器上读入图像
  28. unsigned char code GIMG[14]={12, 0X01 ,0Xff,0xff,0xff,0xff, 0x01, 0,3,1,0x00,0x05};        //回送12个

  29. //Gen Templet1        :根据原始图像生成指纹特征1
  30. unsigned char code GENT1[14]={13,0X01 ,0Xff,0xff,0xff,0xff,0x01,0,4,2,1,0x00,0x08};        //回送12个

  31. //Gen Templet2        :根据原始图像生成指纹特征2
  32. unsigned char code GENT2[14]={13,0X01 ,0Xff,0xff,0xff,0xff,0x01,0,4,2,2,0x00,0x09}; //回送12个        

  33.         
  34. //Search Finger      :以CharBufferA或CharBufferB中的特征文件搜索整个或部分指纹库
  35. unsigned char code SEAT[18]={17,  0X01 ,0Xff,0xff,0xff,0xff, 0x01,   0,8, 4,1,0,0,    0,0x65,  0x00,0x73};        //回送16个


  36. //Merge Templet      ;将CharBufferA与CharBufferB中的特征文件合并生成模板,结果存于ModelBuffer。
  37. unsigned char code MERG[14]={12,  0X01 ,0Xff,0xff,0xff,0xff, 0x01,  0,3,5 , 0x00,0x09};//回送12个        

  38. //Store Templet      :将ModelBuffer中的文件储存到flash指纹库中
  39. unsigned char code STOR[16]={15,  0X01 ,0Xff,0xff,0xff,0xff, 0x01,  0,6,6,2,     0x00,0x00,     0x00,0x0f}; //回送12个

  40. //Read Note
  41. unsigned char code RDNT[14]={13,0X01 ,0Xff,0xff,0xff,0xff, 0x01, 0,4,0x19,  0, 0x00,0x1e};

  42. //Clear Note
  43. unsigned char code DENT[46]={45,0X01 ,0Xff,0xff,0xff,0xff, 0x01, 0,36,0x18,0,0,0,
  44. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x00,0x3d};

  45. //DEL one templet
  46. unsigned char code DELE_one[16]={16, 0X01 ,0Xff,0xff,0xff,0xff, 0x01,   0,7,  0x0c,    0x00,0x00, 0,1, 0x00,0x15};

  47. //DEL templet      ;清空指纹库
  48. unsigned char code DELE_all[12]={12,0X01 ,0Xff,0xff,0xff,0xff, 0x01, 0,3,  0x0d,0x00,0x11};

  49. //////////////////////////////////////常用指令定义-------结束///////////////////////////////////////////////////////////////////////////////////////


  50. //////////////////////////////////////宏定义////////////////////////////////////////////////////////////////////////
  51. #define FALSE 0
  52. #define TURE  1

  53. //状态定义表
  54. #define on            1
  55. #define off           0

  56. #define MAX_NUMBER    63
  57. #define _Nop()  _nop_()


  58. //////////////////////////////////////宏定义------------结束////////////////////////////////////////////////////////

  59. unsigned char                   FifoNumber=0;
  60. xdata unsigned char   FIFO[MAX_NUMBER+1]={0};

  61. /*********1毫秒延时程序**********/
  62. void delay1ms(unsigned int t)
  63. {
  64.         unsigned int i,j;
  65.         for(i=0;i<t;i++)
  66.            for(j=0;j<120;j++)
  67.            ;
  68. }


  69. void TxdByte(unsigned char dat)//串口发送信息,通过查询方式发送一个字符
  70. {
  71.     TI = 0;                 //让TI=0
  72.     SBUF = dat;         //读入数据
  73.     while(!TI);         //等待发送完毕
  74.     TI = 0;                 //清零
  75. }

  76. bit Command(unsigned char *p,unsigned char MaxTime) //命令解析,给模块发送一个命令
  77. {
  78.           unsigned char count=0,tmpdat=0,temp=0,i=0,package=0,flag=0,checksum=0;
  79.                   
  80.         bit result=0, start=0,stop=0;

  81.           TxdByte(0xef);//数据包包头识别码
  82.            TxdByte(0x01);//数据包包头识别码
  83.           i=*p;         //数组的第“0”个元素、里面存放了本数组的长度,把这个长度给变量i,方便进行操作
  84.           p++;
  85.         p++;
  86.           for (count=i-1; count!=1;count--)  //Sent command String
  87.                   {
  88.                          temp=*p++;//取第个“1”个元素的内容,然后发送
  89.                     TxdByte(temp);//将数据发送出去
  90.                 }  
  91.           result=TURE;//发送完成,结果为真 (真为1)           
  92.           FifoNumber=0;
  93.           for (count=MAX_NUMBER+1; count!=0; count--)//清空所有FIFO[]数组里面的内容,写入0X00
  94.                  FIFO[count-1]=0x00;  
  95.         
  96.           if (result)   
  97.            {               
  98.              result=FALSE;
  99.               start =FALSE;
  100.                    stop  =FALSE;
  101.                count=0;
  102.                clk0=0;        //清零CL0计数
  103.                
  104.                do /////////////////////////////do的内容////////////////////////////////
  105.                 {        
  106.                         restart0:                                
  107.                          if (RI==1)//如果接收到数据
  108.                               {                                 
  109.                                           tmpdat=SBUF;//先把接收到的数据放到tmpdat中
  110.                             RI=0;
  111.                             if ((tmpdat==0xef)&&(start==FALSE))//这个数据为第一个传回来的数据,也就是“指令应答”的第一个字节
  112.                                     {
  113.                                                         count=0;
  114.                                                     FIFO[0]=tmpdat;//读入第一个应答字节(0XEF),存在第“0”个元素中   
  115.                                                         flag=1;        
  116.                                                         goto
  117.                                                                 restart0;//可以用中断方式进行                        
  118.                                                 
  119.                                      }
  120.                                         if(flag==1)//第一个字节已经回来,所以flag==1成立
  121.                                                 {  
  122.                                                         if(tmpdat!=0x01)  //接收数据错误,将重新从缓冲区接收数据
  123.                                                         {         
  124.                                                                 flag=0;//接收应答失败
  125.                                                                 result=FALSE;
  126.                                                               start =FALSE;
  127.                                                                    stop=FALSE;
  128.                                                                count=0;
  129.                                                                 goto
  130.                                                                         restart0;                                       
  131.                                                         
  132.                                                         }
  133.                                                         //如果成功接收到0xef01,可以开始接收数据
  134.                                                         flag=2;//flag=2;表示应答成功,可以开始接收数据了
  135.                                                         count++;//现在count=1;
  136.                                                         FIFO[count]=tmpdat;//读入第二个应答字节(0X01),存在第“1”个元素中   
  137.                                                         start=TURE;        //应答成功可以开始接收数据
  138.                                                             goto
  139.                                                                         restart0;        
  140.                                                 }                  
  141.                              if((flag==2)&&(start==TURE))//flag=2;表示应答成功,可以开始接收数据了
  142.                                      {                                                              
  143.                                                            count++; //数据元素下标++
  144.                                             FIFO[count]=tmpdat;//存入数据
  145.                                                         if(count>=6)
  146.                                                                 {
  147.                                                                         checksum=FIFO[count]+checksum; //计算校验和
  148.                                                                 }
  149.                                                         if(count==8)
  150.                                                                 {
  151.                                                                         package=FIFO[7]*0X100+FIFO[8];        //计算包长度                                                        
  152.                                                                         stop= TURE;
  153.                                                                 }
  154.                                                         if(stop)
  155.                                                                 {                                                
  156.                                                                         if(count==package+8)
  157.                                                                         {
  158.                                                                                 checksum=checksum-FIFO[count-1];
  159.                                                                                 if(checksum!=FIFO[count]&0xff)
  160.                                                                                         result=FALSE; //校验失败,置结果标志为0                                                        
  161.                                                                                 else
  162.                                                                                         result=TURE;
  163.                                                                                 flag=0;
  164.                                                                                 break;
  165.                                                                         }
  166.                                                                 }
  167.                                      }
  168.                                 }
  169.           }/////////////////////////////do的内容----------------结束////////////////////////////////
  170.                   
  171.                 while ((clk0<=MaxTime)&&(count<=MAX_NUMBER)); //由定时器以及最大接收数据来控制,保证不会在此一直循环
  172.                   
  173.         FifoNumber=count;        //保存接收到的数据个数
  174.          }
  175.    return (result);
  176. }

  177. bit VefPSW(void)//验证设备握手口令,成功返回1     
  178. {
  179.          unsigned char  count=0;
  180.         while (1)
  181.            {
  182.              if(Command(VPWD,20) && (FifoNumber==11) && (FIFO[9]==0x00))  
  183.                         return(1);
  184.              count++;
  185.                      if (count>=2)//如果不成功,再验证一次,如果两次不成功,返回失败
  186.                 {  
  187.                     return(0);   
  188.                       }
  189.         }
  190. }


  191. void Clear_All(void) //清空所有指纹信息,清空前首先验证和指纹模块通讯是否正常  
  192. {
  193.         if(VefPSW()!=1)//验证失败
  194.         {                        
  195.                  
  196.         }
  197.         else                  //验证成功
  198.         {                        
  199.                    Command(DELE_all,50); //清空指纹库
  200.                    Command(DENT,20);           //清空用户记事本
  201.         }
  202. }

  203. unsigned char ImgProcess(unsigned char BUFID)  //发获取图像并生成特征文件,存入BUFID中//输入参数为缓冲区号  
  204. {        
  205.     if(Command(GIMG,89) && (FifoNumber==11) && (FIFO[9]==0x00))  
  206.     {
  207.                 if(BUFID==1)      
  208.                 {                                   
  209.                       if(Command(GENT1,60) && (FifoNumber==11) && (FIFO[9]==0x00))  
  210.                 {                                                        
  211.                                 return 1;
  212.                         }  
  213.                 else
  214.                 {
  215.                                   return 0;
  216.                  }
  217.                  }
  218.                 else if(BUFID==2)
  219.                 {
  220.                           if(Command(GENT2,60) && (FifoNumber==11) && (FIFO[9]==0x00))  
  221.                 {                                
  222.                                 return 1;
  223.                         }  
  224.                 else
  225.                 {
  226.                                   return 0;
  227.                  }                        
  228.                 }
  229.     }
  230.     else
  231.     {
  232.       return 0;      
  233.     }
  234.         return 0;            
  235. }

  236. bit Searchfinger(void)//搜索指纹(发送搜索命令、以及根据返回值确定是否存在)        
  237. {               
  238.            if(Command(SEAT,60) && (FifoNumber==15) && (FIFO[9]==0x00) )  
  239.     {
  240.                 SearchNumber=FIFO[10]*0x100+FIFO[11];//搜索到的页码
  241.                 //MatchScore=FIFO[12]*0x100+FIFO[13]   可以在此计算得分,从而进行安全级别设定,本程序忽略
  242.                    return 1;
  243.         }     
  244.     else            
  245.     {
  246.                return 0;
  247.     }  
  248. }


  249. unsigned char search(void)//搜索用户
  250. {
  251.          unsigned char SearchBuf=0,i=0;
  252.           while (i<20)
  253.     {
  254.            if(modeflag==0)//在识别模式下
  255.            {
  256.                     if (ImgProcess(1)==1)//首先读入一次指纹  
  257.                 {
  258.                        SearchBuf=Searchfinger();//进行指纹比对,如果搜索到,返回搜索到的指纹序号
  259.                        if(SearchBuf==1)         //成功搜索到指纹号
  260.                        {
  261.                                return SearchNumber;
  262.                        }
  263.                        else  //如果没有搜索到指纹号
  264.                         {
  265.                            return 255; //由于只能录入162个指纹,这时候如果返回255表示识别错误,或者这个指纹没有登记
  266.                         }     
  267.                }
  268.           }
  269.           else
  270.            {
  271.                    break;
  272.                    return 0;
  273.                 }
  274.                 i++;        
  275.     }
  276.    return 255;//这里其实是超时了,由于只能录入162个指纹,这时候如果返回255表示识别错误,或者这个指纹没有登记
  277. }

  278. bit savefingure(unsigned char ID)//保存指纹
  279. {
  280.          unsigned char i=0;
  281.          //现在开始进行存储指纹模板的操作
  282.      for (i=0;i<16;i++)        //保存指纹信息
  283.                  {
  284.                         FIFO[i]=STOR[i];
  285.                 }  
  286.      FIFO[12]=ID; //把指纹模板存放的PAGE_ID也就是FLASH的位置
  287.      FIFO[14]=FIFO[14]+ID;        //校验和
  288.      if (Command(FIFO,70)==1)//不成功返回0        //此处进行存放指纹模板的命令
  289.                  {return(1);}  //成功返回1
  290.      else
  291.                  {return(0);} //不成功返回0
  292. }



  293. unsigned char enroll(void) //采集两次指纹,生成1个 指纹模板
  294. {
  295.          unsigned char temp=0,count=0;
  296.           while(1)
  297.           {
  298.                    temp=ImgProcess(1); //生成特征1   
  299.                    if (temp==1)//生成特征文件成功            
  300.               {                        
  301.                 break;
  302.                }
  303.              else                  
  304.                {
  305.                 if (temp==0)//采集指纹没有成功
  306.                   {
  307.                                 count++;
  308.                     if (count>=40)//如果采集了40次,还不成功,直接采集失败,直接退出enroll函数----返回0  
  309.                                         return(0);
  310.             }
  311.         }
  312.            }
  313.         //采集第一个特征成功
  314.            count=0;  
  315.           buzzer=0;delay1ms(100);        buzzer=1;  //蜂鸣器提醒第一个特征采集成功

  316.         delay1ms(2000);//延时2S开始采集下一个特征

  317.         //开始采集第二个特征
  318.          while(1)
  319.           {
  320.                    temp=ImgProcess(2); //生成特征2   
  321.                    if (temp==1)//生成特征文件2成功
  322.               {
  323.                 if (  (Command(MERG,40)&& (FifoNumber==11) && (FIFO[9]==0x00))==0  ) //合并不成功返回0,成功返回1
  324.                         {
  325.                                 return 0;        //合并不成功
  326.                         }        
  327.                         else//特征文件合并生成模板,结果存于ModelBuffer
  328.                         {
  329.                                  buzzer=0;
  330.                      delay1ms(100);
  331.                      buzzer=1;
  332.                                  delay1ms(100);
  333.                                  buzzer=0;
  334.                      delay1ms(100);        //响两声,表示生成一个模板成功
  335.                      buzzer=1;
  336.                      return 1;        //合并成功
  337.                         }        
  338.         }
  339.               else      
  340.                {        
  341.                                 count++;                                 
  342.                                 if (count>=25)         return(0);                       
  343.              }
  344.            }
  345. }


  346. void shownum(unsigned char dat)        //显示指纹编号
  347. {
  348.         unsigned char numdat=0;
  349.         numdat=dat;
  350.         GotoXY(0,1);//x,y
  351.         Print("Finger:");
  352.         GotoXY(0,8);//x,y
  353.         str[0]=0x30+numdat/10;
  354.         str[1]=0x30+numdat%10;
  355.         Print(str);
  356. }

  357. void changeState(void)//显示状态转换
  358. {
  359.         if(changeflag==1)        //模式识别键按下
  360.         {
  361.            GotoXY(0,0);//x,y
  362.            if(modeflag==0)
  363.            {
  364.                            Print(Identify);//显示 识别模式  Indentity
  365.            }
  366.            else
  367.            {
  368.                            Print(Input);   //显示  输入模式 Input
  369.            }
  370.            changeflag=0;               
  371.         }
  372.                
  373. }




  374. void main(void)//主函数
  375. {
  376.         unsigned char i=0;

  377.         ET0=1;     //定时器0开中断
  378.         TL0=0x97;  //17ms的初值
  379.         TH0=0xBD;
  380.    delay1ms(5);
  381.    LcdRw=0;      //只对液晶进行写操作,不进行读操作
  382.    delay1ms(5);
  383.    LCD_Initial();//液晶初始化
  384.    delay1ms(5);
  385.    GotoXY(0,0);//x,y
  386.    Print(Identify);

  387.     //串口初始化
  388.     SCON=0x50;   //UART方式1:8位UART;   REN=1:允许接收
  389.     PCON=0x00;   //SMOD=0:波特率不加倍
  390.     TMOD=0x21;   //T1方式2,用于UART波特率
  391.     TH1=0xFD;
  392.     TL1=0xFD;   //UART波特率设置:9600
  393.     TR1=1;
  394.     TR0=1;// 开定时器0
  395.         
  396.         IT0=0;//中断0低电平中断
  397.         IT1=1;//中断1低电平中断
  398.         EX0=1;//开中断0
  399.         EX1=1;//开中断1
  400.     EA=1;

  401.         

  402.         for(i=0;i<6;i++)//开始握手6次,如果没有一次成功,表示模块通信不正常。只要成功就跳出此循环
  403.         {
  404.                 if(VefPSW())//与模块握手通过,绿灯亮起。进入识别模式
  405.                   {
  406.                                 green=0; //读一次
  407.                                 buzzer=0;
  408.                                 shownum(0);
  409.                         delay1ms(300);
  410.                         buzzer=1;
  411.                                 break;        
  412.                   }
  413.             else   //通信握手失败
  414.                  {
  415.                         red=1;           //红灯亮
  416.                         green=1;
  417.                         break;

  418.                  }
  419.         }

  420.     while(1)
  421.         {
  422.                
  423.                 if(k2==0)//录入一个指纹
  424.                         {
  425.                                   delay1ms(10);        
  426.                                   if(k2==0)//如果仍为低电平,表示按键有效
  427.                                           {
  428.                                             while(k2==0);//等待松手
  429.                                           if(VefPSW()==1&&modeflag==1&&SaveNumber<10)//与模块握手通过
  430.                                                   {
  431.                                                             if(enroll()==1)//采集两次,生成1个指纹模板成功
  432.                                                                   {
  433.                                                                    if(savefingure(SaveNumber+1)==1)//保存也成功
  434.                                                                            {
  435.                                                                                 SaveNumber++;//加一次
  436.                                                                                 shownum(SaveNumber);
  437.                                                                         }
  438.                         
  439.                                                                 }
  440.                                                   }
  441.                                                 else
  442.                                                 {
  443.                                                                 buzzer=0;
  444.                                                                 for(i=0;i<8;i++)
  445.                                                                 {
  446.                                                                   delay1ms(100);
  447.                                                                   red=~red;
  448.                                                                 }
  449.                                                                 red=0;
  450.                                                                 buzzer=1;               
  451.                                                 }         
  452.                                           }
  453.                                        
  454.                         }        //k2==0

  455.                 if(modeflag==0)//为识别模式
  456.                 {
  457.                           searchnum=search();
  458.                           if(searchnum>=1&&searchnum<=162)//最多只能存储162个指纹
  459.                           {
  460.                                       //显示搜索到的指纹号
  461.                                         shownum(searchnum);
  462.                                        
  463.                                //蜂鸣器响一声
  464.                                buzzer=0;
  465.                                delay1ms(100);
  466.                                buzzer=1;
  467.                           }
  468.                           if(searchnum==255)//表示放上了没有登记的指纹或者识别错误
  469.                           {
  470.                             ;//用户可以自己处理,比如显示 指纹是非法的 或者蜂鸣器响三声,表示错误等
  471.                           }
  472.                 }

  473.                 if(clearallflag==1)
  474.                 {
  475.                         clearallflag=0;
  476.                         Clear_All();
  477.                     red=0;             //红色灯亮
  478.                     green=1;
  479.                         //蜂鸣器长响一次,表示清除所有指纹结束
  480.                         modeflag=1;//进入录入指纹模式
  481.                         GotoXY(0,0);//x,y
  482.                         Print(Input);
  483.                         shownum(0);
  484.                         buzzer=0;
  485.                         delay1ms(800);
  486.                         buzzer=1;
  487.                         SaveNumber=0;
  488.                 }

  489.         }////////////////////////////while(1)结束////////////////////////////////
  490.         
  491. }


  492. void int0(void) interrupt 0//中断0,清除所有指纹
  493. {
  494.         if(k3==0) //清除所有指纹
  495.                 {
  496.                         delay1ms(10);
  497.                         if(k3==0)//如果仍为低电平,表示按键有效
  498.                         {
  499.                                 while(k3==0);//等待松手        
  500.                                 clearallflag=1;
  501.                         }        
  502.                 }        
  503. }

  504. void  Timer0(void) interrupt 1//定时器0中断函数
  505. {
  506.          TL0=0x97;
  507.         TH0=0xBD;
  508.         clk0++;   //延时17ms
  509. }


  510. void int1(void) interrupt 2//外部中断1,模式转换键按下
  511. {
  512.         if(k1==0)//模式转换 其中用modeflag 来标志,默认从第1个指纹开始录入
  513.         {
  514.           delay1ms(10);        
  515.           if(k1==0)//如果仍为低电平,表示按键有效
  516.                   {
  517.                         while(k1==0);//等待松手
  518.                         changeflag=1;//表示模式有变化,即K1键按下
  519.                          modeflag=~modeflag;//0表示录入指纹  1表示识别指纹
  520.                          changeState();//看一下是不是要显示状态转换
  521.                          if(modeflag==0)//根据模式改变当前模式指示灯的颜色
  522.                          {
  523.                                 green=0;                red=1;         //录入指纹绿灯亮
  524.                          }
  525.                          else
  526.                          {
  527.                                 red=0;                 green=1;  //指纹识别红灯灯亮
  528.                          }
  529.                 }        
  530.         }        
  531. }
复制代码

所有资料51hei提供下载:
指纹识别.zip (2.27 MB, 下载次数: 72)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:8222 发表于 2020-2-21 10:13 | 显示全部楼层
谢谢分享,下载学习。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表