基于AS608与STC89C52的指纹密码锁

原理图与PCB图

首先先附上原理图,如下图所示。为了方便制版,于是画了原理图进行PCB打板。
在这里插入图片描述
PCB的三维图如下图所示。看起来还是很不错的。由于指纹模块AS608的供电电压是3.3v,大家可以买AMS1117模块进行降压。我没有试过AS608接5V。大家可以试一下,如果可以用那还省事一点。
在这里插入图片描述


AS608模块的介绍

录入图像

首先肯定是要录入指纹的,录入指纹的指令与详解如下所示,我就不一 一赘述了。我直接讲解我写这个代码的思路叭。首先可以肯定的是串口初始化,串口初始化完成之后,我们可以将包头、芯片地址之类的生成一个不可改变的数组,通过调用数组去发送,会让代码看起来更容易理解一点。
在这里插入图片描述

生成特征

在这里插入图片描述

对比两个指纹

我的程序里并没有用到,所以导致录入指纹的时候会出现同一个手指录了两个不同指纹。我想应该是没有比对的原因。
在这里插入图片描述

搜索指纹

搜索指纹,由于AS608有内部flash,所以可以存好多枚指纹,于是大家在扫描指纹开锁的时候,可以采用搜索指纹的方式,看看是否内部存有指纹进行开锁。
在这里插入图片描述

合成模板

将录入的指纹合成特征模板
在这里插入图片描述
大概关键的指令就这些。

24C02的代码

另外在附录一下24C02的代码,大家可以借鉴学习一下。

/*************************************************
D罗电子设计qq:1679960378 qq:672939453
***************************************************/
#include <reg52.h>
#include <intrins.h>
#include "24C02.h"
//#include"mytype.h"

#include <24c02.h>

void nop()
{
   
   
	_nop_();
	_nop_();
}

/24C02读写驱动程序
void delay1(unsigned int m)
{
   
   	unsigned int n;
  	for(n=0;n<m;n++);
}

void x24c02_init()     //24C02初始化
{
   
   
	wp=0;
	scl=1;
	nop();
	sda=1;
	nop();
}

void start()        //启动I2C总线
{
   
   
	sda=1;
	nop();
	scl=1;
	nop();
	sda=0;
	nop();
	scl=0;
	nop();
}

void stop()         //停止I2C总线
{
   
   
	sda=0;
	nop();
	scl=1;
	nop();
	sda=1;
	nop();
}

void writebyte(unsigned char j)  //写一个字节
{
   
   
	unsigned char i,temp;
   	temp=j;
   	for (i=0;i<8;i++)
   {
   
   
	   temp=temp<<1;
	   scl=0;
	   nop();
	   sda=CY;		//temp左移时,移出的值放入了CY中
	   nop();
	   scl=1;		//待sda线上的数据稳定后,将scl拉高
	   nop();
   }
   scl=0;
   nop();
   sda=1;
   nop();
}

unsigned char readbyte()   //读一个字节
{
   
   
   unsigned char i,j,k=0;
   scl=0; nop(); sda=1;
   for (i=0;i<8;i++)
   {
   
     
		nop(); scl=1; nop();
      	if(sda==1) 
		j=1;
      	else
		j=0;
      	k=(k<<1)|j;
	  	scl=0;
	}
   	nop();
	return(k);
}

void clock()         //I2C总线时钟
{
   
   
   unsigned char i=0;
   scl=1;
   nop();
   while((sda==1)&&(i<255))
   	  i++;
   scl=0;
   nop();
}

从24c02的地址address中读取一个字节数据/
unsigned char read24c02(unsigned char address)
{
   
   
   unsigned char i;
   start();
   writebyte(0xa0);
   clock();
   writebyte(address);
   clock();
   start();
   writebyte(0xa1);
   clock();
   i=readbyte();
   stop();
   delay1(100);
   return(i);
}

//向24c02的address地址中写入一字节数据info/
void write24c02(unsigned char address,unsigned char info)
{
   
   
   start();
   writebyte(0xa0);
   clock();
   writebyte(address);
   clock();
   writebyte(info);
   clock();
   stop();
   delay1(5000); //这个延时一定要足够长,否则会出错。因为24c02在从sda上取得数据后,还需要一定时间的烧录过程。
}

12864的代码

/*************************************************
D罗电子设计
***************************************************/
#include <reg52.h>
#include <intrins.h>
#include"12864.h"
/**************************************************************
这里采用串行方式控制,因为不要接数据传输的脚,为了省实物焊接过程。
**************************************************************/	    
unsigned char code AC_TABLE[]={
   
   				           //座标编码
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
};
/****************************************************************	  
              发送一个字节
*****************************************************************/
void SendByte(unsigned char Dbyte)
{
   
   
	unsigned char i;
	for(i=0;i<8;i++)
	{
   
   
		SCK = 0;
		Dbyte=Dbyte<<1;
		SID = CY;
		SCK = 1;
		SCK = 0;
	}
}
/**********************************************************
              接收一个字节
***********************************************************/

unsigned char ReceiveByte(void)
{
   
   
	unsigned char i,temp1,temp2;
	temp1=temp2=0;
	for(i=0;i<8;i++)
	{
   
   
		temp1=temp1<<1;
		SCK = 0;
		SCK = 1;                
		SCK = 0;
		if(SID) temp1++;
	}
	for(i=0;i<8;i++)
	{
   
   
		temp2=temp2<<1;
		SCK = 0;
		SCK = 1;
		SCK = 0;
		if(SID) temp2++;
	}
	return ((0xf0&temp1)+(0x0f&temp2));
}
/****************************************************************
                      检查忙状态
******************************************************************/
void CheckBusy( void )
{
   
   
	do SendByte(0xfc);     //11111,RW(1),RS(0),0
	while(0x80&ReceiveByte());
}

/******************************************************************
           写一个字节的指令
*******************************************************************/
void WriteCommand( unsigned char Cbyte )
{
   
   
	CS = 1;
	CheckBusy();
	SendByte(0xf8);          
	SendByte(0xf0&Cbyte);
	SendByte(0xf0&Cbyte<<4);
	CS = 0;
}
/*************************************************************
                 写一个字节的数据
**************************************************************/
void WriteData( unsigned char Dbyte )
{
   
   
	CS = 1;
	CheckBusy();
	SendByte(0xfa);          //11111,RW(0),RS(1),0
	SendByte(0xf0&Dbyte);
	SendByte(0xf0&Dbyte<<4);
	CS = 0;
}

/******************************************************************
                         lcd初始化函数
*******************************************************************/
void LcmInit( void )
{
   
   
     WriteCommand(0x30);
     WriteCommand(0x03);
     WriteCommand(0x0c);
     WriteCommand(0x01);
     WriteCommand(0x06);
}

/*******************************************************************************************************
                                 设定光标函数
********************************************************************************************************/
void Location_xy_12864(unsigned char x,unsigned char y)
{
   
   
	switch(x)
	{
   
   
		case 0:
			x=0x80;break;
		case 1:
			x=0x90;break;
		case 2:
			x=0x88;break;
		case 3:
			x=0x98;break;
		default:
			x=0x80;
	}
	y=y&0x07;
	WriteCommand(0x30);
	WriteCommand(y+x);
	WriteCommand(y+x);

}
/***********************************************************************************
                  清除文本
************************************************************************************/
void LcmClearTXT( void )
{
   
   
	unsigned char i;
	WriteCommand(0x30);
	WriteCommand(0x80);
	for(i=0;i<64;i++)
	WriteData(0x20);
	Location_xy_12864(0,0);	    
}


/***********************************************************************
                      显示字符串
***********************************************************************/
void PutStr(unsigned char row,unsigned char col,unsigned char *puts)
{
   
       
	WriteCommand(0x30);
	WriteCommand(AC_TABLE[8*row+col]);
	while(*puts != '\0')
	{
   
   
		if(col==8)
		{
   
   
			col=0;
			row++;
		}
		if(row==4) row=0;
		WriteCommand(AC_TABLE[8*row+col]);
		WriteData(*puts);
		puts++;
		if(*puts != '\0')
		{
   
   
			WriteData(*puts);
			puts++;
			col++;
		}  
	}
}

按键扫描

unsigned char Keycan(void)
{
   
   
 	unsigned char row,col,i;
 	P1=0xf0;
 	if((P1&0xf0)!=0xf0)
 	{
   
   
	   	delay(50);
        delay(50);
   		if((P1&0xf0)!=0xf0)
		{
   
   
    		row=P1^0xf0;          //确定行线
			i=0;
			P1=a[i];	          //精确定位
			while(i<4)
			{
   
   
	 			if((P1&0xf0)!=0xf0)
	  			{
   
   
	   				col=~(P1&0xff);	  //确定列线
	   				break;            //已定位后提前退出   
	  			}
				else 
	  			{
   
   
	   				i++;
	   				P1=a[i];
	  			}
			}
		}
		else 
		{
   
   
			return 0;
		}
		while((P1&0xf0)!=0xf0);
		return (row|col);	 		//行线与列线组合后返回
 	}
 	else 
    return 0;	         		//无键按下时返回0
}

void KeyDeal(unsigned char Key)
{
   
     //unsigned char n;
   if(Key!=0)
 {
   
   
		   switch(Key)
		   {
   
   
		   case 0x11: K=1; break;	 
		   case 0x21: K=2; break;  
		   case 0x41: K=3; break;  
		   case 0x81: break;       
		   case 0x12: K=4; break;
		   case 0x22: K=5; break;
		   case 0x42: K=6; break;
		   case 0x82: break;		
		   case 0x14: K=7; break;
		   case 0x24: K=8; break;
		   case 0x44: K=9; break;
		   case 0x84: break;		
		   case 0x18: break;		
		   case 0x28: K=0; break;
		   case 0x48: K=11; break;
		   case 0x88: K=34;break;		
		   default: break;
		   }
  }
}

仔细讲解一下录指纹

附上代码。

//不可改变与可以改变的数组如下所示
unsigned char code a[]={
   
   0xFE,0xFD,0xFB,0xF7};   //按键扫描数组
unsigned char code FPM10A_Pack_Head[6] = {
   
   0xEF,0x01,0xFF,0xFF,0xFF,0xFF};  //协议包头
unsigned char code FPM10A_Get_Img[6] = {
   
   0x01,0x00,0x03,0x01,0x00,0x05};    //获得指纹图像
unsigned char code FPM10A_Img_To_Buffer1[7]={
   
   0x01,0x00,0x04,0x02,0x01,0x00,0x08}; //将图像放入到BUFFER1  PageId+0x07
unsigned char code FPM10A_Img_To_Buffer2[7]={
   
   0x01,0x00,0x04,0x02,0x02,0x00,0x09}; //将图像放入到BUFFER2  PageId+0x07
unsigned char code FPM10A_Reg_Model[6]={
   
   0x01,0x00,0x03,0x05,0x00,0x09}; //将BUFFER1跟BUFFER2合成特征模版
unsigned char code FPM10A_Search[11]={
   
   0x01,0x00,0x08,0x04,0x01,0x00,0x00,0x03,0xE7,0x00,0xF8}; //搜索指纹搜索范围0 - 999,使用BUFFER1中的特征码搜索    //起始页+页数+校验和
unsigned char code FPM10A_Delete_All_Model[6]={
   
   0x01,0x00,0x03,0x0d,0x00,0x11};//删除指纹模块里所有的模版
volatile unsigned char FPM10A_Delete_Finger[10]={
   
   0x01,0x00,0x07,0x0c,0x00,0x00,0x00,0x01,0x00,0x15};//删除指纹模块里的模版
volatile unsigned char FPM10A_Save_Finger[9]={
   
   0x01,0x00,0x06,0x06,0x02,0x00,0x0B,0x00,0x19};//将BUFFER1中的特征码存放到指定的位置

串口初始化代码如下:

void UART_Init()
{
   
   
	SCON= 0x50;               //串口方式1	//REN=1; 允许接收
	PCON=0x00;                //SMOD=0
	TMOD= 0x20;               //定时器1定时方式2
	TH1= 0xFD;                //11.0592MHz  模块默认波特率为9600bps
	TL1= 0xFD;										 
	TR1= 1;                   //启动定时器 
	EA=1;	
}

/***********************************************************************************************
串口发送函数
D罗电子设计qq:1679960378 qq:672939453
***********************************************************************************************/
void Uart_Send_Byte(unsigned char c)//UART Send a byte
{
   
   
	SBUF = c;
	while(!TI);		
	TI = 0;
}

unsigned char Uart_Receive_Byte()//UART Receive a byteg
{
   
   	
	unsigned char dat;
	while(!RI);	  
	RI = 0;
	dat = SBUF;
	return (dat);
}

大家还是不要看后面的注释哈,有的是最开始就注释了的,但是后面改了忘了修改注释。
在添加指纹代码之前,现将各种包头、与接收的数据写成函数

void FPM10A_Cmd_Send_Pack_Head(void)
{
   
   
	int i;	
	for(i=0;i<6;i++) //包头
    {
   
   
     Uart_Send_Byte(FPM10A_Pack_Head[i]);   
    }		
}

//接收反馈数据缓冲
void FPM10A_Receive_Data(unsigned char ucLength)
{
   
   
  unsigned char i;

  for (i=0;i<ucLength;i++)
     FPM10A_RECEICE_BUFFER[i] = Uart_Receive_Byte();

}

//FINGERPRINT_获得指纹图像命令
void FPM10A_Cmd_Get_Img(void)
{
   
   
    unsigned char i;
    FPM10A_Cmd_Send_Pack_Head(); //发送通信协议包头
    for(i=0;i<6;i++) //发送命令
	{
   
   
       Uart_Send_Byte(FPM10A_Get_Img[i]);
	}
}

//将图像转换成特征码存放在Buffer1中
void FINGERPRINT_Cmd_Img_To_Buffer1(void)
{
   
   
 	unsigned char i;
	FPM10A_Cmd_Send_Pack_Head(); //发送通信协议包头      
   	for(i=0;i<7;i++)             //发送命令 将图像转换成 特征码 存放在 CHAR_buffer1
     {
   
   
      Uart_Send_Byte(FPM10A_Img_To_Buffer1[i]);
   	 }
}

//将图像转换成特征码存放在Buffer2中
void FINGERPRINT_Cmd_Img_To_Buffer2(void)
{
   
   
     unsigned char i;
     for(i=0;i<6;i++)    //发送包头
	 {
   
   
    	Uart_Send_Byte(FPM10A_Pack_Head[i]);   
   	 }
     for(i=0;i<7;i++)   //发送命令 将图像转换成 特征码 存放在 CHAR_buffer2
      {
   
   
      	Uart_Send_Byte(FPM10A_Img_To_Buffer2[i]);
   	  }
}


//合成特征模板
void FPM10A_Cmd_Reg_Model(void)
{
   
   
	unsigned char i;	   
	FPM10A_Cmd_Send_Pack_Head(); //发送通信协议包头
	for(i=0;i<6;i++)
    {
   
   
		Uart_Send_Byte(FPM10A_Reg_Model[i]);   
   	}
}

再就是添加指纹函数了,添加指纹函数有如下几步
发送包头,发送添加指纹的指令这个函数 FPM10A_Cmd_Get_Img(void);在前文添加指纹的指令中我们发现如果返回来接收到的数据是0则接收到了指纹,如果没有则一直扫描指纹,直到接收到。在录入了指纹之后应该先与指纹库比对一下,如果指纹库中有这个指纹则不再存入。如果指纹库中没有这个指纹则再次按下指纹,于是将指纹存下来,此时指纹ID加1,24C02中的区域中也要存下ID值,以便掉电存储。

/***********************************************************************************************
添加指纹函数合集
D罗电子设计qq:1679960378 qq:672939453
***********************************************************************************************/

//保存指纹
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++)  
	Uart_Send_Byte(FPM10A_Save_Finger[i]);      //发送命令 将图像转换成 特征码 存放在 CHAR_buffer2
    		
}

//添加指纹
void FPM10A_Add_Fingerprint()
{
   
   
	uchar IDa1,IDa2,IDa3;
	LcmClearTXT();
	PutStr(1,2,"请按手指");
    delayms(2000);
    FPM10A_Cmd_Get_Img(); //获得指纹图像
    FPM10A_Receive_Data(12);
	while(FPM10A_RECEICE_BUFFER[9]!=0)
	{
   
   
		FPM10A_Cmd_Get_Img(); //获得指纹图像
		FPM10A_Receive_Data(12);
	}
    if(FPM10A_RECEICE_BUFFER[9]==0)
	{
   
   
		FINGERPRINT_Cmd_Img_To_Buffer1();
		FPM10A_Receive_Data(12);
		FPM10A_Cmd_Search_Finger();
		FPM10A_Receive_Data(16);
		if(FPM10A_RECEICE_BUFFER[9] == 0)    //搜索是否已经存储
		{
   
   

			PageID = FPM10A_RECEICE_BUFFER[10]*256 + FPM10A_RECEICE_BUFFER[11];
			IDa1=PageID/100;
			IDa2=PageID/10%10;
			IDa3=PageID%10;
			LcmClearTXT();
			PutStr(0,1,"该指纹已存储");
			PutStr(1,1,"编号为:");
			WriteCommand(0x8D); 
			WriteData(0x30+IDa1);
			WriteData(0x30+IDa2);
			WriteData(0x30+IDa3);
			PutStr(3,0,"  按任意键继续"); 
            while(Keycan()==0);
		}
		if(FPM10A_RECEICE_BUFFER[9] == 9)
		{
   
   	
			LcmClearTXT();		
			PutStr(1,1,"请再次按指纹");
			FPM10A_Cmd_Get_Img(); //获得指纹图像
		    FPM10A_Receive_Data(12);
			if(FPM10A_RECEICE_BUFFER[9] == 0)
			{
   
   
				FINGERPRINT_Cmd_Img_To_Buffer2();
				FPM10A_Receive_Data(12);
				FPM10A_Cmd_Reg_Model();
			    FPM10A_Receive_Data(12);
			    IDa1=PageID/100;
			    IDa2=PageID/10%10;
			    IDa3=PageID%10;
			    LcmClearTXT();
			    PutStr(1,1,"指纹采集成功");
			    PutStr(2,1,"编号为:");
			    WriteCommand(0x8D); 
			    WriteData(0x30+IDa1);
			    WriteData(0x30+IDa2);
			    WriteData(0x30+IDa3);
			    delay(1000);
				write24c02(116,PageID+1);
			    FPM10A_Cmd_Save_Finger(PageID++);
				FPM10A_Receive_Data(12);				
			}
		}
	    PutStr(3,0,"  按任意键继续"); 
	    while(Keycan()==0);
	}
	LcmClearTXT();
}

由于篇幅关系,只介绍录入指纹的代码,但是其余代码都大同小异,只要弄清楚指令就可以了。
另外将剩下的的代码都附录如下,以便大家学习借鉴。

/***********************************************************************************************
管理员与开锁合集
D罗电子设计——邓工
***********************************************************************************************/

void shuazhiwen()
{
   
    
	LcmClearTXT();
	PutStr(1,1,"请按手指开锁");      
	FPM10A_Find_Fingerprint();
}

void gaimima()      //修改用户密码
{
   
   
	uchar i,j=0,mima1[6],mima2[6];
	uchar k,temp;
	LcmClearTXT();
	PutStr(1,1,"请输入新密码");
	for(i=0;i<6;i++)
	{
   
   
		mima1[i]=0;
	}									
	Key=Keycan();
    while(Key!=queren)
	{
   
   
	    Key=Keycan();
	    KeyDeal(Key);
	    delay(30);				                              
	    if(Key==0)
		{
   
   
			K=10;		
		}
	    if((K>=0)&&(K<=9))
	    {
   
   
			mima1[j]=K;
			if(j<6)
			{
   
   	
				WriteCommand(0x89+j);		//指定第三行显示位置
				//WriteData(0x0f);	
				WriteData(K+0x30);
			}
			++j;
			if(j==7)
			j=6;												   
	    }   //显示LCD12864并行显示 
		if(K==34)		//按了删除键
		{
   
   
		    if(j==0)
			{
   
   
				WriteCommand(0x89);		//指定第三行显示位置
				WriteData(0x20);
			}
			else
			{
   
   
				--j;
				WriteCommand(0x89+j);	    //指定第三行显示位置
				WriteData(0x20);
			}
		}
	}
	LcmClearTXT();
	j=0;
	PutStr(1,0,"请再次输入新密码");
	for(i=0;i<6;i++)
	{
   
   
		mima2[i]=0;
	}									
	Key=Keycan();
    while(Key!=queren)
	{
   
   
		Key=Keycan();
	    KeyDeal(Key);
	    delay(30);				                              
	    if(Key==0)
		{
   
   
			K=10;
		}
	    if((K>=0)&&(K<=9))
	    {
   
   
			mima2[j]=K;
			if(j<6)
			{
   
   		
				WriteCommand(0x89+j);		//指定第三行显示位置
				//WriteData(0x0f);	
				WriteData(K+0x30);	
			}
	        ++j;
		    if(j==7)
	        j=6;												   
	    }   //显示LCD12864并行显示 
		if(K==34)		//按了删除键
		{
   
   
		    if(j==0)
			{
   
   
				WriteCommand(0x89);		//指定第三行显示位置
				WriteData(0x20);
			}
			else
			{
   
   
				--j;
				WriteCommand(0x89+j);	    //指定第三行显示位置
				WriteData(0x20);
			}
		}
	}
	LcmClearTXT();
	if((mima1[0]==mima2[0])&&(mima1[1]==mima2[1])&&(mima1[2]==mima2[2])&&(mima1[3]==mima2[3])&&(mima1[4]==mima2[4])&&(mima1[5]==mima2[5]))
	{
   
   
		for(i=0;i<6;i++)
		mimaID[i]=mima1[i];
		for(i=0;i<6;i++)           //密码限制在6位以内
		{
   
   
			UserPassword[i]=mima1[i]+0x30;                          	
		}
		temp=(Member-1)*100+10;	
		delayms(5);
		for(k=0;k<6;k++)
		{
   
   
			write24c02(temp,UserPassword[k]);
			delayms(10);
			temp++;
		}  
		//
		PutStr(0,1,"密码修改成功"); 
		PutStr(3,0,"  按任意键继续");
		Member=0;                              //方便下次修改密码
		while(Keycan()==0);
	}
	else
	{
   
   
		PutStr(0,0,"  密码修改失败  ");
		PutStr(1,0,"两次输入的密码不"); 
		PutStr(2,0,"一致,请重新操作");       
		PutStr(3,0,"  按任意键继续"); 
		while(Keycan()==0);
	}
	LcmClearTXT();
}

void zhu()
{
   
     	 
    LcmClearTXT();
	PutStr(1,2,"门已打开");
   	jidianqi=0;
	delay(2500); 
	jidianqi=1;
	PutStr(3,0,"  按任意键继续");
	while(Keycan()==0);
}

void guanliyuan()       //管理员
{
   
    
	uchar i,j=0,x=1;uchar Right_flag;
    LcmClearTXT();
	PutStr(1,1,"请输入密码:");	
	for(i=0;i<6;i++)
	{
   
   
		mima[i]=0;	
	}
	Key=Keycan();
    while(Key!=queren)
	{
   
   
		Key=Keycan();
	    KeyDeal(Key);
	    delay(30);				                              
	    if(Key==0)
		{
   
   
			K=10;		
		}
	    if((K>=0)&&(K<=9))
	    {
   
   
			mima[j]=K;
			if(j<6)
		    {
   
   	
				WriteCommand(0x89+j);		//指定第三行显示位置
				WriteData(0x0f);	
		    }
	        ++j;
		    if(j==7)
			{
   
   
	            j=6;			
			}
												  
	    }   //显示LCD12864并行显示 
		if(K==34)		//按了删除键
		{
   
   
			if(j==0)
			{
   
   
		        WriteCommand(0x89);		//指定第三行显示位置
	            WriteData(0x20);
			}
			else
			{
   
   
			    --j;
		        WriteCommand(0x89+j);	    //指定第三行显示位置
	            WriteData(0x20);
			}
		}
	}
    LcmClearTXT();
    for(i=0;i<6;i++)
    {
   
   
		UserPassword[i]=mima[i]+0x30;
	
    } 
	if(j==6)
    {
   
   
	    Right_flag=PassWord_Chack(); 
	}
	if (Right_flag==1)
	{
   
   
	  	Right_flag=0;
		Key=Keycan();
		while(Key!=tuichu)
		{
   
   	 
			PutStr(0,0,"按键1 : 增加指纹"); 
			PutStr(1,0,"按键2 : 删去指纹");
			PutStr(2,0,"按键3 : 清空所有");
			PutStr(3,0,"按键4 : 修改密码");
			Key=Keycan();
			KeyDeal(Key);  
			switch(K)
			{
   
   
			case 1:
				FPM10A_Add_Fingerprint(); K=8;      //仅录一次,如果不设置K=8(可以比4大就行),会一直录指纹
				break;
			case 2: 
				FPM10A_Delete_Fingerprint();				
				break;
			case 3:	   
				FPM10A_Delete_All_Fingerprint();  
				break;
			case 4:    
				gaimima();     
				break;
			default:   
				break;
			}
		}
    }
    else
    {
   
   

		alarm=0;
		PutStr(1,2,"密码错误");
		PutStr(2,0,"  请重新操作!"); 
		PutStr(3,0,"  按任意键继续");
        delay(2500);
        alarm=1;		
		while(Keycan()==0);
    }
	Key=0;
	LcmClearTXT();
}


//功能介绍
void MEMU()
{
   
   
	PutStr(0,2,"欢迎使用");
	PutStr(1,1,"D罗电子设计");
	PutStr(2,1,"qq1679960378");
	PutStr(3,1,"qq:672939453");
    Key=Keycan();
    if(k2==1)		//指纹刷机
    {
   
   
		LcmClearTXT();
		shuazhiwen();
		LcmClearTXT();
    }
	if(Key==0x81)			//管理员操作
    {
   
   
		LcmClearTXT();
		guanliyuan();
		LcmClearTXT();
    }
}	
     
void main()
{
   
    	
	UART_Init();	   //串口初始化	
	x24c02_init();     //24C02初始化
	LcmInit();	       //LCD12864初始化
	LcmClearTXT();	   //LCD12864清屏
//	write24c02(110,0x30);
//  write24c02(111,0x30);//24c02的第110到115地址单元作为密码存储区
//  write24c02(112,0x30);
//	write24c02(113,0x30);
//	write24c02(114,0x30);
//	write24c02(115,0x30);
//	write24c02(116,0);
	PageID=read24c02(116);
	while(1) 
	{
   
   
		
		MEMU();
		delay(100);	  
	}	
}

附上实物图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
图中所示的3.2是5v降压到3.3的显示屏,大家降压可以前文提到的AMS1117模块。


串口通讯失败的原因

1、串口初始化有问题,如果想知道初始化是否正确,用USB TO TTL串口下载器进行调试一下,如果不对,大家再多查一下串口的资料。
2、另外,最后最重要的是,AS608模块是有波特率的,一开始你不可能一下就能把波特率设置对。你可以自己用单片机串口初始化设置波特率。运用指纹上位机调试指纹模块波特率,与单片机一致就可以了。

指纹上位机去我的资源里下载,免费哈。
指纹模块波特率设置就是与下载器普通的连接就行了。RXD----TXD,TXD-----RXD。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章