基于51单片机的指纹锁系统设计
在现代社会,随着科技的不断进步,家庭安全变得越来越重要。传统的机械锁由于安全性低,已经不能满足人们对家庭安全的需求。因此,我们设计了一款基于51单片机的指纹锁系统,该系统结合了指纹识别技术和密码锁的工作原理,提供了一种安全可靠、操作便捷的解决方案。
实物图:
系统概述
本指纹锁系统以STC89C52单片机为核心,辅以AS608指纹模块、L298N电机驱动芯片、LCD1602显示屏等模块。系统通过指纹验证或密码输入实现开锁功能,具有操作简便、安全性高的特点。LCD显示屏用于显示系统状态和用户操作指引,而L298N芯片则用于驱动锁具的机械部分。
硬件设计
51单片机
51单片机是整个系统的核心,负责处理所有的逻辑控制和数据处理。STC89C52单片机具有足够的I/O端口,可以连接多个外部设备,同时具备内部Flash存储器,便于程序的存储和运行。
AS608指纹模块
AS608指纹模块负责指纹的采集和识别。该模块通过光学传感器捕捉用户的指纹图像,并通过内置算法进行特征提取和比对。模块通过串口与单片机通信,发送和接收控制指令。
L298N电机驱动芯片
L298N芯片用于驱动锁具的电机,实现锁舌的开启和关闭。该芯片可以接收单片机的控制信号,驱动电机正转或反转,从而控制锁具的开闭状态。
LCD1602显示屏
LCD1602显示屏用于显示系统状态和用户操作指引。它能够显示多行文本信息,帮助用户了解当前的操作状态,如指纹验证成功、密码输入错误等提示信息。
软件设计
软件部分主要包括指纹模块的驱动程序、用户界面的控制程序、密码管理程序和主控制程序。
指纹模块驱动程序
//AS608???????é
volatile unsigned char AS608_RECEICE_BUFFER[32]; //volatile:????×??????????ü?ù???????????????????????ü?°????????????????????????????
//FINGERPRINT?¨?????é?¨??
code unsigned char AS608_Get_Device[10] ={0x01,0x00,0x07,0x13,0x00,0x00,0x00,0x00,0x00,0x1b};//?????é?¤
code unsigned char AS608_Pack_Head[6] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF}; //???é°ü?·
code unsigned char AS608_Get_Img[6] = {0x01,0x00,0x03,0x01,0x00,0x05}; //????????????
code unsigned char AS608_Get_Templete_Count[6] ={0x01,0x00,0x03,0x1D,0x00,0x21 }; //??????°?×???
code unsigned char AS608_Search[11]={0x01,0x00,0x08,0x04,0x01,0x00,0x00,0x03,0xE7,0x00,0xF8}; //???÷???????÷·??§0 - 999,????BUFFER1???????÷?????÷
code unsigned char AS608_Search_0_9[11]={0x01,0x00,0x08,0x04,0x01,0x00,0x00,0x00,0x13,0x00,0x21}; //???÷0-9??????
code unsigned char AS608_Img_To_Buffer1[7]={0x01,0x00,0x04,0x02,0x01,0x00,0x08}; //??????·?????BUFFER1
code unsigned char AS608_Img_To_Buffer2[7]={0x01,0x00,0x04,0x02,0x02,0x00,0x09}; //??????·?????BUFFER2
code unsigned char AS608_Reg_Model[6]={0x01,0x00,0x03,0x05,0x00,0x09}; //??BUFFER1?úBUFFER2???????÷??°?
code unsigned char AS608_Delete_All_Model[6]={0x01,0x00,0x03,0x0d,0x00,0x11};//???????????é???ù??????°?
volatile unsigned char AS608_Save_Finger[9]={0x01,0x00,0x06,0x06,0x01,0x00,0x0B,0x00,0x19};//??BUFFER1???????÷????·??????¨??????
//code unsigned char AS608_num_of_finger_in_lib1[7]={0x01,0x00,0x04,0x1F,0x00,0x00,0x24};//?é???????????ü??
//code unsigned char AS608_num_of_finger_in_lib2[7]={0x01,0x00,0x04,0x1F,0x01,0x00,0x25};
//code unsigned char AS608_num_of_finger_in_lib3[7]={0x01,0x00,0x04,0x1F,0x02,0x00,0x26};
//code unsigned char AS608_num_of_finger_in_lib4[7]={0x01,0x00,0x04,0x1F,0x03,0x00,0x27};
//·???°ü?·
void AS608_Cmd_Send_Pack_Head(void)
{
int i;
for(i=0;i<6;i++) //°ü?·
Uart_Send_Byte(AS608_Pack_Head[i]);
}
//·???????
void AS608_Cmd_Check(void)
{
int i=0;
AS608_Cmd_Send_Pack_Head(); //·????¨?????é°ü?·
for(i=0;i<10;i++)
Uart_Send_Byte(AS608_Get_Device[i]);
}
//????·???????????
void AS608_Receive_Data(unsigned char ucLength)
{
unsigned char i;
for (i=0;i<ucLength;i++)
AS608_RECEICE_BUFFER[i] = Uart_Receive_Byte();
}
//FINGERPRINT_?????????????ü??
void AS608_Cmd_Get_Img(void)
{
unsigned char i;
AS608_Cmd_Send_Pack_Head(); //·????¨?????é°ü?·
for(i=0;i<6;i++) //·????ü?? 0x1d
Uart_Send_Byte(AS608_Get_Img[i]);
}
//??????×????????÷????·???Buffer1??
void FINGERPRINT_Cmd_Img_To_Buffer1(void)
{
unsigned char i;
AS608_Cmd_Send_Pack_Head(); //·????¨?????é°ü?·
for(i=0;i<7;i++) //·????ü?? ??????×????? ???÷?? ??·??? CHAR_buffer1
Uart_Send_Byte(AS608_Img_To_Buffer1[i]);
}
//??????×????????÷????·???Buffer2??
void FINGERPRINT_Cmd_Img_To_Buffer2(void)
{
unsigned char i;
AS608_Cmd_Send_Pack_Head(); //·????¨?????é°ü?·
for(i=0;i<7;i++) //·????ü?? ??????×????? ???÷?? ??·??? CHAR_buffer1
Uart_Send_Byte(AS608_Img_To_Buffer2[i]);
}
//???÷???????§999??
void AS608_Cmd_Search_Finger(void)
{
unsigned char i;
AS608_Cmd_Send_Pack_Head(); //·????¨?????é°ü?·
for(i=0;i<11;i++)
Uart_Send_Byte(AS608_Search[i]);
}
//×????????÷??
void AS608_Cmd_Reg_Model(void)
{
unsigned char i;
AS608_Cmd_Send_Pack_Head(); //·????¨?????é°ü?·
for(i=0;i<6;i++)
Uart_Send_Byte(AS608_Reg_Model[i]);
}
//???????????é?????ù????????°?
void FINGERPRINT_Cmd_Delete_All_Model(void)
{
unsigned char i;
AS608_Cmd_Send_Pack_Head(); //·????¨?????é°ü?·
for(i=0;i<6;i++) //?ü????????????°?
Uart_Send_Byte(AS608_Delete_All_Model[i]);
}
//±???????
void AS608_Cmd_Save_Finger( unsigned int storeID )
{
unsigned long temp = 0;
unsigned char i;
AS608_Save_Finger[5] =(storeID&0xFF00)>>8;
AS608_Save_Finger[6] = (storeID&0x00FF);
for(i=0;i<7;i++) //???????é??
temp = temp + AS608_Save_Finger[i];
AS608_Save_Finger[7]=(temp & 0x00FF00) >> 8; //??·????é????
AS608_Save_Finger[8]= temp & 0x0000FF;
AS608_Cmd_Send_Pack_Head(); //·????¨?????é°ü?·
for(i=0;i<9;i++)
Uart_Send_Byte(AS608_Save_Finger[i]); //·????ü?? ??????×????? ???÷?? ??·??? CHAR_buffer1
}
//?é???±?°??????????????°???
int AS608_number_of_fingers()
{
int num=1;//??????°?????????????°?
uchar i=0;
AS608_Cmd_Send_Pack_Head(); //·????¨?????é°ü?·
for(i=0;i<6;i++)
Uart_Send_Byte(AS608_Get_Templete_Count[i]);
AS608_RECEICE_BUFFER[9]=1;//·?±??ó????????·?????????
AS608_Receive_Data(14);//????????
if(AS608_RECEICE_BUFFER[9]==0) //????????
num=AS608_RECEICE_BUFFER[10]*256+AS608_RECEICE_BUFFER[11];//??????°?×?????
return num;
}
//?í????·?·¨?é????????????·?????°? //±????????é???ù??1000????°???????·???????°???????°??????????°256?????????ò
/*
bit AS608_notEmpty()
{
bit exist=0;
char i=0;
AS608_Cmd_Send_Pack_Head(); //·????¨?????é°ü?·
for(i=0;i<7;i++)
{
Uart_Send_Byte(AS608_num_of_finger_in_lib1[i]);
}
AS608_Receive_Data(10);//?????°10byte????,????10×??????·???????????à???????ú
if(AS608_RECEICE_BUFFER[9]==0) //????????
{
AS608_Receive_Data(32);//?????ó??32byte??????????0~255????°?????·???????????°???????
for(i=0;i<32;i++)//?é????32byte????????????????????????°??ò·???????????·??ò????
{
if(AS608_RECEICE_BUFFER[i])
exist=1;
}
return exist;
}
}
*/
//?í??????
void AS608_Add_Fingerprint()
{
unsigned char id_show[]={0,0,0};
LCD1602_WriteCMD(0x01); //????
while(1)
{
LCD1602_Display(0x80," Add finger ",0,16);
LCD1602_Display(0xc0," ID is ",0,16);
//°?·????ü?±???????÷????
if(KEY_CANCEL == 0)
{
Delay_ms(5);
if(KEY_CANCEL == 0)
{
while(KEY_CANCEL==0);
break;
}
}
//°??????ü????iD????1
if(KEY_DOWN == 0)
{
Delay_ms(5);
if(KEY_DOWN == 0)
{
while(KEY_DOWN==0);
if(finger_id == 1000)
finger_id = 1;//±???0????±?????
else
finger_id = finger_id + 1;
}
}
//????iD?????????í
LCD1602_WriteCMD(0xc0+10);
LCD1602_Display_Number(finger_id);
//°??·???ü????????????????
if(KEY_OK == 0)
{
Delay_ms(5);
if(KEY_OK == 0)
{
while(KEY_OK==0);
LCD1602_Display(0x80," Please finger ",0,16);
LCD1602_Display(0xc0," ",0,16);
while(KEY_CANCEL == 1)
{
//°???·????ü????????·???fingerID?÷??×???
if(KEY_CANCEL == 0)
{
Delay_ms(5);
if(KEY_CANCEL == 0)
{
while(KEY_CANCEL==0);
break;
}
}
AS608_Cmd_Get_Img(); //????????????
AS608_Receive_Data(12);
//?????????????·????,????0????????????
if(AS608_RECEICE_BUFFER[9]==0)
{
Delay_ms(100);
FINGERPRINT_Cmd_Img_To_Buffer1();
AS608_Receive_Data(12);
LCD1602_Display(0x80,"Successful entry",0,16);
Beep_Times(1);
Delay_ms(1000);
LCD1602_Display(0x80," Please finger ",0,16);
LCD1602_Display(0xc0," ",0,16);
while(1)
{
if(KEY_CANCEL == 0)
{
Delay_ms(5);
if(KEY_CANCEL == 0)
{
while(KEY_CANCEL==0);
break;
}
}
AS608_Cmd_Get_Img(); //????????????
AS608_Receive_Data(12);
//?????????????·????,????0????????????
if(AS608_RECEICE_BUFFER[9]==0)
{
Delay_ms(200);
LCD1602_Display(0x80,"Successful entry",0,16);
LCD1602_Display(0xc0," ID is ",0,16);
//????iD?????????í
LCD1602_WriteCMD(0xc0+10);
LCD1602_Display_Number(finger_id);
FINGERPRINT_Cmd_Img_To_Buffer2();
AS608_Receive_Data(12);
AS608_Cmd_Reg_Model();//×????????÷??
AS608_Receive_Data(12);
AS608_Cmd_Save_Finger(finger_id);
AS608_Receive_Data(12);
Beep_Times(1);
Delay_ms(1000);
finger_id=finger_id+1;
break;
}
}
break;
}
}
}
}
}
}
//???÷????
void AS608_Find_Fingerprint()
{
unsigned int find_fingerid = 0;
unsigned char id_show[]={0,0,0};
do
{
LCD1602_Display(0x80," Please finger ",0,16);
LCD1602_Display(0xc0," ",0,16);
AS608_Cmd_Get_Img(); //????????????
AS608_Receive_Data(12);
//?????????????·????,????0????????????
if(AS608_RECEICE_BUFFER[9]==0)
{
Delay_ms(100);
FINGERPRINT_Cmd_Img_To_Buffer1();
AS608_Receive_Data(12);
AS608_Cmd_Search_Finger();
AS608_Receive_Data(16);
if(AS608_RECEICE_BUFFER[9] == 0) //???÷??
{
//????????//
LCD1602_Display(0x80," Search success ",0,16);
LCD1602_Display(0xc0," ID is ",0,16);
Beep_Times(1);
//????????ID??
find_fingerid = AS608_RECEICE_BUFFER[10]*256 + AS608_RECEICE_BUFFER[11];
//????iD?????????í
LCD1602_WriteCMD(0xc0+10);
LCD1602_Display_Number(find_fingerid);
//????IO??????????????×÷
if(flag)
{
P1=0xfe;
Delay_ms(OpenTime*100);
P1=0xff; //?????ú????×???
Delay_ms(1000);
P1=0xfd; //?????ú·?×?????
Delay_ms(CloseTime*100);//???ú??×?×è?????ó??·?×?????×??à???????±????×??è???ü?à?±??
P1=0xff; //?????ú????×???
}
flag=1; //???í?ó???à????×÷???í???ò??????????°?
break;
}
else //????????
{
LCD1602_Display(0x80," Search failed ",0,16);
LCD1602_Display(0xc0," ",0,16);
Beep_Times(3);
}
}
}while(KEY_CANCEL == 1);
}
//?????ù?????ü????????
void AS608_Delete_All_Fingerprint()
{
unsigned char i=0;
LCD1602_Display(0x80," empty all ",0,16);
LCD1602_Display(0xc0," Yes or no ? ",0,16);
do
{
if(KEY_OK==0)
{
Delay_ms(5);
if(KEY_OK==0)
{
while(KEY_OK==0);
LCD1602_Display(0x80," emptying ",0,16);
LCD1602_Display(0xc0," ",0,16);
Delay_ms(300);
LCD1602_WriteCMD(0xc0);
for(i=0;i<16;i++)
{
LCD1602_WriteDAT(42);// ??'*'
Delay_ms(100);
}
FINGERPRINT_Cmd_Delete_All_Model();
AS608_Receive_Data(12);
LCD1602_Display(0x80," All empty ",0,16);
LCD1602_Display(0xc0," ",0,16);
Beep_Times(3);
break;
}
}
}while(KEY_CANCEL==1);
}
该程序负责与AS608指纹模块进行通信,实现指纹的采集、特征提取和比对。程序通过串口发送指令,控制指纹模块的工作状态,并接收模块返回的比对结果。
用户界面控制程序
//???§·±???ì??
void LCD1602_CheckBusy(void)
{
uchar busy;
DataPort=0xff;
RS=0;
RW=1;
do
{
EN=1;
busy=DataPort;
EN=0;
}while(busy&0x80);
}
//???§??????????
void LCD1602_Init(void)
{
Delay_ms(15); //???????±15ms
LCD1602_WriteCMD(0x38); //??????????(???ì????????)
Delay_ms(5);
LCD1602_CheckBusy();
LCD1602_WriteCMD(0x38); //??????????
LCD1602_CheckBusy();
LCD1602_WriteCMD(0x01); //????
LCD1602_CheckBusy();
LCD1602_WriteCMD(0x06); //??????±ê?????è??
LCD1602_CheckBusy();
LCD1602_WriteCMD(0x0c); //???????°??±ê?è??
}
//???§???????? ??????????addr???????·??pointer???????·??index??±ê??num????
void LCD1602_Display(unsigned char addr,unsigned char* pointer,unsigned char index,unsigned char num)
{
unsigned char i;
LCD1602_CheckBusy(); //??????????
LCD1602_WriteCMD(addr); //???????·
for(i=0;i<num;i++) //????????
{
LCD1602_CheckBusy(); //??????????
LCD1602_WriteDAT(pointer[index+i]);//????????
}
}
//???§??????????
void LCD1602_Display_Number(unsigned int num)
{
if(num/1000)
LCD1602_WriteDAT(num/1000+48);
LCD1602_WriteDAT(num%1000/100+48);
LCD1602_WriteDAT(num%100/10+48);
LCD1602_WriteDAT(num%10+48);
}
该程序负责控制LCD1602显示屏,显示系统状态和用户操作指引。程序根据系统的工作状态,动态更新显示内容,提供清晰的用户交互界面。
主控制程序
//?÷????
void main()
{
finger_id=0;
I2C_init();//I2C??????
LCD1602_Init(); //?????????§
LCD1602_Display(0x80," Designer : lsy ",0,16); //???§???ú????????
Delay_ms(500);
LCD1602_Display(0x80,"Fingerprint Test",0,16); //???§???ú????????
Uart_Init(); //??????????
Key_Init(); //??????°??ü
Delay_ms(200); //???±200MS?????????????é????
Device_Check(); //???????????é??·????????·?????§×????à?????á??
Delay_ms(1000); //???????????????????¨?±??
OpenTime=I2C_ReadData(254);//??AT24C02??254????????????????
CloseTime=I2C_ReadData(250);//??AT24C02??255????????????????
while(1)
{
/**************?????÷????????****************/
LCD1602_Display(0x80," search finger ",0,16); //?????????????÷????
LCD1602_Display(0xc0," Add delete",0,16); //?í????????????
switch(local_date)
{
case 0:
LCD1602_Display(0x80, " *",0,2);
LCD1602_Display(0xc0, " ",0,2);
LCD1602_Display(0xc0+8," ",0,2);
break;
case 1:
LCD1602_Display(0x80, " ",0,2);
LCD1602_Display(0xc0, " *",0,2);
LCD1602_Display(0xc0+8," ",0,2);
break;
case 2:
LCD1602_Display(0x80, " ",0,2);
LCD1602_Display(0xc0, " ",0,2);
LCD1602_Display(0xc0+8," *",0,2);
break;
}
//?·???ü
if(KEY_OK == 0)
{
Delay_ms(5);
if(KEY_OK == 0)
{
while(KEY_OK == 0);//????????°??ü
switch(local_date)
{
case 0: //???÷????
flag=1;
AS608_Find_Fingerprint();
break;
case 1: //?í??????
flag=1; //flag=1?????????????????ò?????±???í??????
if(AS608_number_of_fingers())
{
flag=0;//flag??0??????×÷????
//1?????????????????????ò?è?????÷????????????AS608_Find_Fingerprint()??flag??1???????í??????
//2??flag=0???ò?????÷?????????ó????????????×÷
AS608_Find_Fingerprint();
}
if(flag)
AS608_Add_Fingerprint();
break;
case 2: //????????
flag=0; //1???????÷?????????ó????????????×÷??2???????÷????????????????????×÷
AS608_Find_Fingerprint();//???÷?????????ó????????????flag??1????????????????
if(flag)
AS608_Delete_All_Fingerprint();
break;
}
}
}
//?????ü
if(KEY_DOWN == 0)
{
Delay_ms(5);
if(KEY_DOWN == 0)
{
while(KEY_DOWN == 0); //????????°??ü
local_date++;
if(local_date==3)
local_date=0;
}
}
//°?Key_Mode?????±???÷??????
if (KEY_Mode == 0)
{
Delay_ms(5);
if(KEY_Mode == 0)
{
while(KEY_Mode == 0);
flag=0;
AS608_Find_Fingerprint();
if(flag)
Refresh_time();
}
}
Delay_ms(100); //???±????100MS?ì??????
}
}
主控制程序负责协调各个模块的工作,实现系统的开锁逻辑。当用户进行指纹验证或密码输入时,主程序会调用相应的驱动程序,根据验证结果控制L298N芯片,实现锁具的开闭。
系统功能
本指纹锁系统具备以下功能:
- 指纹开锁:用户可以通过验证指纹来开锁。
- 状态显示:LCD显示屏会实时显示系统状态,如开锁成功、密码错误等。
- 安全报警:如果连续多次输入错误的指纹,系统会触发报警。
结论
基于51单片机的指纹锁系统设计,不仅提高了家庭安全的水平,也为用户提供了便捷的开锁方式。通过结合现代电子技术和生物识别技术,该系统在保证安全性的同时,也提供了良好的用户体验。随着技术的不断进步,未来指纹锁系统将更加智能化、多样化,为家庭安全提供更加可靠的保障。
原理图
PCB设计
希望你喜欢这个项目,并在构建过程中找到乐趣!如果你有任何问题或需要帮助,欢迎在评论区交流。
作者:Svan.
注意:本博文为不得在未经本人同意进行转载或者二次创作,违者必究!!!
博客主页:https://blog.csdn.net/weixin_51141489,需要源码或相关资料实物的友友请关注、点赞,私信吧!