基于STM32的智能门锁安防系统(开源)

目录

项目演示

项目概述

硬件组成:

功能实现

[1. 开锁模式](#1. 开锁模式)

[1.1 按键密码开锁](#1.1 按键密码开锁)

[1.2 门禁卡开锁](#1.2 门禁卡开锁)

[1.3 指纹开锁](#1.3 指纹开锁)

[2. 功能备注](#2. 功能备注)

[3. 硬件模块工作流程](#3. 硬件模块工作流程)

[3.1 步进电机控制](#3.1 步进电机控制)

[3.2 蜂鸣器提示](#3.2 蜂鸣器提示)

[3.3 OLED显示](#3.3 OLED显示)

[3.4 指纹与卡片管理](#3.4 指纹与卡片管理)

项目源代码分析

[1. 主程序流程 (main.c)](#1. 主程序流程 (main.c))

[1.1 开机界面](#1.1 开机界面)

[1.2 主界面](#1.2 主界面)

[1.3 开锁功能](#1.3 开锁功能)

[2. 指纹录入与删除](#2. 指纹录入与删除)

3.门禁卡的录入

[4. 数据存储与恢复](#4. 数据存储与恢复)

完整的main.c文件

总结


项目演示

基于STM32的智能门锁安防系统-CSDN直播

项目概述

智能门锁安防系统是一种集成了多种开锁方式的安全系统,采用STM32单片机作为核心控制器,配备多种硬件设备,如OLED显示器、RC522门禁卡模块、AS608指纹模块、4x4矩阵按键、步进电机、蜂鸣器等,旨在为家庭或企业提供更加安全和便利的门禁系统。该系统支持三种开锁方式:密码锁、门禁卡、指纹识别。

硬件组成:

  • STM32F103C8T6:主控芯片,处理所有的控制任务。
  • OLED显示器:用于显示系统状态、信息、时间等。
  • RC522门禁卡模块:实现RFID卡的读写,支持门禁卡开锁。
  • AS608指纹模块:用于指纹识别,实现指纹开锁。
  • 4x4矩阵按键模块:用于输入密码,实现密码开锁。
  • 步进电机模块:驱动门锁的开关。
  • 蜂鸣器模块:用于提醒用户操作结果,如密码错误、开锁成功等。

功能实现

1. 开锁模式

本系统支持三种开锁方式,每种方式都具有一定的安全性,用户可以根据实际需求选择合适的方式进行解锁:

1.1 按键密码开锁

用户通过按键输入密码进行开锁,密码是可以修改的,用户可以根据需要设置和修改密码。每次输入密码后,系统会对比预设的密码,并决定是否开锁。

1.2 门禁卡开锁

使用RC522门禁卡模块,通过读取门禁卡的信息进行开锁。用户可以录入新的门禁卡,系统会根据用户输入的卡号进行验证,如果匹配成功,则开锁。

1.3 指纹开锁

使用AS608指纹模块,通过指纹识别实现开锁。用户可以录入多个指纹,并通过指纹验证进行开锁。如果验证通过,系统自动解锁。

2. 功能备注

  • 修改密码:用户可以随时修改开锁密码,提供更好的安全性。
  • 添加/删除功能:可以添加新的指纹、门禁卡、密码,支持删除已录入的指纹、门禁卡、密码。
  • 内部Flash存储:系统支持通过内部Flash存储数据,保证即使在掉电情况下,密码、指纹和门禁卡信息仍然能够保留,下次上电时可以继续使用。

3. 硬件模块工作流程

3.1 步进电机控制

步进电机负责锁的物理开关,通过与STM32的GPIO端口连接,可以在接收到开锁命令时,驱动电机打开或关闭锁。

3.2 蜂鸣器提示

蜂鸣器用于提供音响提示,比如开锁成功、密码错误等操作结果。蜂鸣器会根据不同的状态发出不同的声音。

3.3 OLED显示

OLED显示器显示系统的当前状态,包括时间、密码输入界面、开锁提示等信息,增强了用户的交互体验。

3.4 指纹与卡片管理

指纹模块(AS608)与RFID卡模块(RC522)是门锁系统的两大身份验证方式。系统通过这些模块读取指纹和门禁卡信息,并将其与预存的数据库进行比对,判断是否开锁。

项目源代码分析

1. 主程序流程 (main.c)

系统启动后,主程序执行硬件初始化,包括初始化OLED显示器、步进电机、蜂鸣器、按键、指纹模块、门禁卡模块等。然后系统进入主循环,根据用户输入的操作,进行密码验证、指纹识别、门禁卡识别等。

1.1 开机界面
cpp 复制代码
void starting(void)
{
    OLED_Clear();
    Show_Str(16,12,128,16,"智能门锁系统",16,0);
    OLED_Refresh_Gram();
    delay_ms(2000);
}

在开机时,OLED显示器显示"智能门锁系统",并延时2秒。

1.2 主界面
cpp 复制代码
			/********************主界面**************************/

MENU:
			OLED_Clear();
MENUNOCLR:
			OLED_Fill(0,0,20,48,0);
			//主页菜单显示
			if(arrow<3){
				Show_Str(5,arrow*16,128,16,"->",16,0);//显示箭头
				set=0;}
			else {
				Show_Str(5,(arrow-3)*16,128,16,"->",16,0);
				set=3;}
			Show_Str(25,0,128,16,setup[set],16,0);
			Show_Str(25,16,128,16,setup[set+1],16,0);
			Show_Str(25,32,128,16,setup[set+2],16,0);
			Show_Str(0,52,128,12,"上    下     确定",12,0);
			OLED_Refresh_Gram();//更新显示
			time2=0;
			while(1)
			{
						//超时锁屏
						time2++;
						if(time2>10000 | key_num==4){  
							
							OLED_Clear();
								DisLock();
								if(time2>10000)beep_on_mode2();
								time2 =0;
//								delay_ms(1000);
								OLED_Clear();
								goto MAIN;
						}
						//手机蓝牙锁定
						if(memcmp(USART_RX_BUF,"LOCK",4)==0)	{
//							USART_RX_STA=0;
//							memset(USART_RX_BUF,0,USART_REC_LEN);
							DisLock();
							goto MAIN;
						}
						
						//功能选项选择
						key_num=Button4_4_Scan();	
						if(key_num)
						{
							if(key_num==13){
								if(arrow>0)arrow--;
								goto MENUNOCLR;
							}
							if(key_num==15){
								if(arrow<MaxParaNum-1)arrow++;
								goto MENUNOCLR;
							}
							if(key_num==16){
								switch(arrow)
								{
#if USE_FINGERPRINT
									case 0:Add_FR();		break;//录指
									case 1:Del_FR();		break;//删指纹
									case 2:SetPassworld();break;//修改密码
									case 3:Set_Time(); break;  //设置时间
									case 4:Add_Rfid(); break;  //录入卡片
									case 5:Massige(); break;  //显示信息
#else
									case 0:SetPassworld();break;//修改密码
									case 1:Set_Time(); break;  //设置时间
									case 2:Add_Rfid(); break;  //录入卡片
									case 3:Massige(); break;  //显示信息
#endif

									
//									
								}
								goto MENU;
							}		
						}delay_ms(1);
			}	
	}

在主界面,用户可以选择不同的功能选项。界面通过按键的输入切换,显示相应的功能选项,如修改密码、录入指纹、查看信息等。

1.3 开锁功能

系统实现了三种开锁模式,分别是密码开锁、指纹开锁和门禁卡开锁。根据用户输入的方式,系统会调用相应的函数来完成开锁操作。

  • 密码开锁:用户输入密码后,系统会与预设密码进行对比,如果匹配成功,则开锁。
  • 指纹开锁:用户将手指放在指纹模块上,系统通过指纹识别来判断是否开锁。
  • 门禁卡开锁:通过刷卡的方式,系统会验证门禁卡是否匹配,如果匹配成功,则开锁。

蓝牙密码开锁:

cpp 复制代码
						//手机蓝牙解锁密码1
						Error=usart1_cherk((char*)sys.passwd1);         
						if(Error==0){ 
							OLED_Clear_NOupdate();
							Show_Str(12,13,128,20,"蓝牙密码1:正确",12,0); 
							OLED_Refresh_Gram();//更新显示
							delay_ms(800);
							DisUnLock();
							goto MENU;	
						}
						else 
						{
//							OLED_Clear_NOupdate();
//							Show_Str(12,13,128,12,"蓝牙密码:错误!",12,0); 
//							OLED_Refresh_Gram();//更新显示
//							delay_ms(800);
//							OLED_Show_Font(56,48,0);//锁
						}
						
						//手机蓝牙解锁密码2
						Error=usart1_cherk((char*)sys.passwd2);         
						if(Error==0){
							sys.errCnt = 0;
							OLED_Clear_NOupdate();
							Show_Str(12,13,128,12,"蓝牙密码2:正确",12,0); 
							OLED_Refresh_Gram();//更新显示
							delay_ms(800);
							DisUnLock();
							goto MENU;	
						}
						else 
						{
							//OLED_Show_Font(56,48,0);//锁
						}
						

按键密码开锁:

cpp 复制代码
//密码锁
int password(void)
{
	int  key_num=0,i=0,satus=0;
	u16 num=0,num2=0,time3=0,time;
	u8 pwd[11]="          ";
	u8 hidepwd[11]="          ";
	u8 buf[64];
	OLED_Clear();//清屏

	if(DisErrCnt())return -1;//错误次数超限
	
	OLED_Clear();//清屏
	Show_Str(5,0,128,16,"密码:",16,0);
	Show_Str(10,16,128,12," 1   2   3  Bck",12,0);
	Show_Str(10,28,128,12," 4   5   6  Del",12,0);
	Show_Str(10,40,128,12," 7   8   9  Dis",12,0);
	Show_Str(10,52,128,12,"Clr  0  Clr  OK",12,0);
	OLED_Refresh_Gram();//更新显示
//	Show_Str(102,36,128,12,"显示",12,0);
//	Show_Str(0,52,128,12,"删除 清空   返回 确认",12,0);
	while(1)
	{
		key_num=Button4_4_Scan();	
		if(key_num != -1)
		{	
			printf("key=[%d]\r\n",key_num);
			DisFlag = 1;
			time3=0;
			if(key_num != -1)
			{	
				DisFlag = 1;
				time3=0;
				switch(key_num)
				{
					case 1:
					case 2:
					case 3:
						pwd[i]=key_num+0x30; //1-3
						hidepwd[i]='*';
						i++;
					break;
					case 4://返回
						OLED_Clear();
						delay_ms(500);
					return -1;
						
					break;
					case 5:
					case 6:
					case 7:
						pwd[i]=key_num+0x30-1; //4-6
						hidepwd[i]='*';
						i++;
					break;
					case 8:
						if( i > 0){
							pwd[--i]=' ';  //'del'键
							hidepwd[i]=' '; 
						}
					break;
					case 9:
					case 10:
					case 11:
						pwd[i]=key_num+0x30-2; //4-6
						hidepwd[i]='*';
						i++;
					break;
					case 12:satus=!satus; break;//DIS
					case 13:
					case 15:
						while(i--){
						pwd[i]=' ';  //'清空'键
						hidepwd[i]=' '; 
						}
						i=0;
					break;
					case 14:
						pwd[i]=0x30; //4-6
						hidepwd[i]='*';
						i++;
					break;
					case 16:
						goto UNLOCK;
					break;
				}
		}
		if(DisFlag == 1)
		{
			if(satus==0)OLED_ShowString(53,0,hidepwd,12);
			else OLED_ShowString(53,0,pwd,12);
		OLED_Refresh_Gram();//更新显示
		}
		
		time3++;
		if(time3%1000==0){
			OLED_Clear();//清屏
			return -1;
		}
		}
	}

UNLOCK:	
		for(i=0; i<10; i++){   //验证虚伪密码
			if(pwd[i]==sys.passwd1[num])num++;
				else num=0;
			if(num==6)
				break;
		}
		for(i=0; i<10; i++){   //验证密码
			if(pwd[i]==sys.passwd2[num2])num2++;
				else num2=0;
			if(num2==6)
				break;
		}
		if(num==6 | num2==6){
			DisUnLock();
			OLED_Clear();//清屏
			sys.errCnt = 0;
			return 0;
		}
		else {
			sys.errCnt++;//错误次数计数
			if(sys.errCnt>MAXERRTIMES)
				sys.errTime = 30; //30秒不能再解锁
			OLED_Clear();//清屏
			Show_Str(45,48,128,16,"密码错误!",16,0);
			OLED_Refresh_Gram();//更新显示
			beep_on_mode1();
			delay_ms(1500);
			OLED_Clear();//清屏
			return -1;
		}
	
}

指纹开锁:

cpp 复制代码
//刷指纹
int press_FR(void)
{
	SearchResult seach;
	u8 ensure;
	char str[256];
	
	
	if(DisErrCnt())return -1;//错误次数超限
	ensure=PS_GetImage();
	
	OLED_Clear_NOupdate();
	Show_Str(0,0,128,16,"正在检测指纹",16,0);
	OLED_Refresh_Gram();//更新显示
	if(ensure==0x00)//获取图像成功 
	{	
		ensure=PS_GenChar(CharBuffer1);
		if(ensure==0x00) //生成特征成功
		{		
			
			ensure=PS_HighSpeedSearch(CharBuffer1,0,AS608Para.PS_max,&seach);
			if(ensure==0x00)//搜索成功
			{				
				OLED_Clear_NOupdate();
				Show_Str(20,10,128,24,"解锁中...",24,0);	
				OLED_Refresh_Gram();//更新显示
				Walkmotor_ON();
				Show_Str(20,10,128,24,"已解锁!",24,0);
				OLED_Refresh_Gram();//更新显示
				OLED_Show_Font(112,18,1);//开锁				
				//str=mymalloc(SRAMIN,2000);
				sprintf(str,"ID:%d     匹配分",seach.pageID);
				Show_Str(0,52,128,12,(u8*)str,12,0);	
				sprintf(str,":%d",seach.mathscore);
				Show_Str(96,52,128,12,(u8*)str,12,0);	
				//myfree(SRAMIN,str);
				OLED_Refresh_Gram();//更新显示
				delay_ms(1800);
				OLED_Clear();
				return 0;
			}
			else {
				sys.errCnt++;//错误次数计数
				if(sys.errCnt>MAXERRTIMES)
					sys.errTime = 30; //30秒不能再解锁
				ShowErrMessage(ensure);	
				OLED_Refresh_Gram();//更新显示
				beep_on_mode1();
				OLED_Clear();
				return -1;
			}				
	  }
		else
			ShowErrMessage(ensure);
		
	OLED_Refresh_Gram();//更新显示
	delay_ms(2000);
	OLED_Clear();
		
	}
	return -1;	
}

门禁卡开锁:

cpp 复制代码
MFRC522_Initializtion();			
Error=MFRC522_lock();
if(Error==0)
{
    goto MENU;	
}
else 
{
	OLED_Show_Font(56,48,0);//锁
}

2. 指纹录入与删除

指纹的录入与删除功能也在系统中得到了实现,用户可以通过界面选择录入或删除指纹,并且在录入时会进行指纹的匹配与验证,确保指纹信息的正确性。

cpp 复制代码
void Add_FR(void)
{
    // 录入指纹逻辑
    ...
}
cpp 复制代码
//删除指纹
void Del_FR(void)
{
    //删除指纹逻辑
    ......
	
MENU:	
	OLED_Clear();
}

3.门禁卡的录入

cpp 复制代码
//录入新卡
u8 Add_Rfid(void)
{
    //录入卡片逻辑
    ......
}

4. 数据存储与恢复

系统使用STM32的Flash存储用户信息(如指纹、密码和门禁卡信息),确保即使系统掉电,数据不会丢失。系统会在每次开机时检查Flash中的数据,恢复上次的配置。

cpp 复制代码
void SysPartInit(void )
{
    STMFLASH_Read(SYS_SAVEADDR, (u16*)&sys, sizeof(sys));
    if(sys.HZCFlag != 980706)
    {
        // 初始化系统配置
    }
}

完整的main.c文件

cpp 复制代码
#include "main.h"
#include <string.h>

SysTemPat sys;


#define USE_FINGERPRINT  1
#define MAXERRTIMES 5
#define usart2_baund  57600//串口2波特率,根据指纹模块波特率更改

//要写入到STM32 FLASH的字符串数组
const u8 TEXT_Buffer[]={0x17,0x23,0x6f,0x60,0,0};
#define TEXT_LENTH sizeof(TEXT_Buffer)	 		  	//数组长度	
#define SIZE TEXT_LENTH/4+((TEXT_LENTH%4)?1:0)
#define FLASH_SAVE_ADDR  0X0802C124 	//设置FLASH 保存地址(必须为偶数,且所在扇区,要大于本代码所占用到的扇区.
										//否则,写操作的时候,可能会导致擦除整个扇区,从而引起部分程序丢失.引起死机.

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

void Display_Data(void);//显示时间
void Add_FR(void);	//录指纹
void Del_FR(void);	//删除指纹
int press_FR(void);//刷指纹
void ShowErrMessage(u8 ensure);//显示确认码错误信息
int password(void);//密码锁
void SetPassworld(void);//修改密码
void starting(void);//开机界面信息
u8 MFRC522_lock(void);//刷卡解锁
u8 Add_Rfid(void);		//录入
void Set_Time(void);
void Massige(void);
void SysPartInit(void );   //系统参数初始化 
//u8 Pwd[7]="      ";  //解锁密码1
//u8 Pwd2[7]="      ";  //解锁密码2
//u8 cardid[6]={0,0,0,0,0,0};  //卡号1
int Error;  //密码验证信息


u8 DisFlag = 1;



//数字的ASCII码
uc8 numberascii[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
//显示缓冲区
u8  dispnumber5buf[6];
u8  dispnumber3buf[4];
u8  dispnumber2buf[3];
//MFRC522数据区
u8  mfrc552pidbuf[18];
u8  card_pydebuf[2];
u8  card_numberbuf[5];
u8  card_key0Abuf[6]={0xff,0xff,0xff,0xff,0xff,0xff};
u8  card_writebuf[16]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
u8  card_readbuf[18];
//SM05-S数据区
u8  sm05cmdbuf[15]={14,128,0,22,5,0,0,0,4,1,157,16,0,0,21};
//extern声明变量已在外部的C文件里定义,可以在主文件中使用
extern u8  sm05receivebuf[16];	//在中断C文件里定义
extern u8  sm05_OK;							//在中断C文件里定义

//u8 * week[7]={"Mon","Tue","Wed","Thu","Fri","Sat","Sun"};
u8 * week[7]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};


#if USE_FINGERPRINT
#define MaxParaNum 6
u8 * setup[7]={"1、录入指纹","2、删除指纹","3、修改密码","4、修改时间","5、录入卡片","6、查看信息"};
#else
#define MaxParaNum 4
u8 * setup[7]={"1、修改密码","2、修改时间","3、录入卡片","4、查看信息","           ","           "};
#endif


void DisUnLock(void )
{
	OLED_Clear();
	Show_Str(20,10,128,24,"解锁中...",24,0);	
	OLED_Refresh_Gram();//更新显示
	Walkmotor_ON();
	Show_Str(20,10,128,24,"已解锁!",24,0);
	OLED_Refresh_Gram();//更新显示
	delay_ms(1500);
}

void DisLock(void )
{
	OLED_Clear();
	Show_Str(30,20,128,16,"锁定中!",16,0);
	OLED_Refresh_Gram();//更新显示
	Walkmotor_OFF();
	Show_Str(30,20,128,16,"已锁定!",16,0);
	OLED_Show_Font(56,48,0);//锁
	OLED_Refresh_Gram();//更新显示
	delay_ms(1000);
}



int main(void)
{			
	u16 set=0;
	u8 err=0;
	int key_num;
	int time1;
	int time2;		//锁屏时间
	char arrow=0;  //箭头位子
	//SysHSI_Init();
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(9600);	 //串口初始化为9600
	printf("串口功能正常\r\n");
	Button4_4_Init();          //初始化与按键连接的硬件接口
	OLED_Init();    			//显示初始化
	Walkmotor_Init();        //步进电机初始化
	BEEP_Init();			//蜂鸣器初始化
	usart2_init(usart2_baund);           //初始化指纹模块
	PS_StaGPIO_Init();
	OLED_Clear(); 
	 
	starting();//开机信息  logo
	err = RTC_Init();	  			//RTC初始化
	if(err)
	{
		OLED_Clear(); 
		Show_Str(12,13,128,20,"RTC CRY ERR!",12,0); 
		OLED_Refresh_Gram();//更新显示
		delay_ms(3000);
	}
	SysPartInit();   //系统参数初始化 
 	while(1)
	{
//锁屏界面
MAIN:
			OLED_Clear(); 
			OLED_Show_Font(56,48,0);//显示锁图标
			while(1)
			{
				time1++;Display_Data();//时间显示:每1000ms更新一次显示数据
				
				if(DisFlag == 1)
				{
					DisFlag = 0;
					OLED_Fill(0,24,16,63,0);
					OLED_Refresh_Gram();//更新显示
				}
				
				if((time1%100)==1)
		 		{
					//MFRC522解锁
						time1=0;
						MFRC522_Initializtion();			
						Error=MFRC522_lock();
						if(Error==0)
						{
							goto MENU;	
						}
						else 
						{
							OLED_Show_Font(56,48,0);//锁
						}
						
						//手机蓝牙解锁密码1
						Error=usart1_cherk((char*)sys.passwd1);         
						if(Error==0){ 
							OLED_Clear_NOupdate();
							Show_Str(12,13,128,20,"蓝牙密码1:正确",12,0); 
							OLED_Refresh_Gram();//更新显示
							delay_ms(800);
							DisUnLock();
							goto MENU;	
						}
						else 
						{
//							OLED_Clear_NOupdate();
//							Show_Str(12,13,128,12,"蓝牙密码:错误!",12,0); 
//							OLED_Refresh_Gram();//更新显示
//							delay_ms(800);
//							OLED_Show_Font(56,48,0);//锁
						}
						
						//手机蓝牙解锁密码2
						Error=usart1_cherk((char*)sys.passwd2);         
						if(Error==0){
							sys.errCnt = 0;
							OLED_Clear_NOupdate();
							Show_Str(12,13,128,12,"蓝牙密码2:正确",12,0); 
							OLED_Refresh_Gram();//更新显示
							delay_ms(800);
							DisUnLock();
							goto MENU;	
						}
						else 
						{
							//OLED_Show_Font(56,48,0);//锁
						}
						
				}
				//指纹解锁
				if(PS_Sta)	 //检测PS_Sta状态,如果有手指按下
				{
						while(PS_Sta){
						Error=press_FR();//刷指纹
						if(Error==0)
						{
							//DisUnLock();
							goto MENU;   //跳到解锁界面
						}								
						else 
						{
							OLED_Show_Font(56,48,0);//锁
						}
					}
				}
				//密码锁
				key_num=Button4_4_Scan();	//按键扫描
				if(key_num!=-1)
				{
					Error=password();//密码解锁函数
					if(Error==0)
					{
						goto MENU;	//跳到解锁界面
					}
					else 
					{
						OLED_Show_Font(56,48,0);//锁
					}
				}
				
				delay_ms(1);
				
				
				
			}
			/********************主界面**************************/

MENU:
			OLED_Clear();
MENUNOCLR:
			OLED_Fill(0,0,20,48,0);
			//主页菜单显示
			if(arrow<3){
				Show_Str(5,arrow*16,128,16,"->",16,0);//显示箭头
				set=0;}
			else {
				Show_Str(5,(arrow-3)*16,128,16,"->",16,0);
				set=3;}
			Show_Str(25,0,128,16,setup[set],16,0);
			Show_Str(25,16,128,16,setup[set+1],16,0);
			Show_Str(25,32,128,16,setup[set+2],16,0);
			Show_Str(0,52,128,12,"上    下     确定",12,0);
			OLED_Refresh_Gram();//更新显示
			time2=0;
			while(1)
			{
						//超时锁屏
						time2++;
						if(time2>10000 | key_num==4){  
							
							OLED_Clear();
								DisLock();
								if(time2>10000)beep_on_mode2();
								time2 =0;
//								delay_ms(1000);
								OLED_Clear();
								goto MAIN;
						}
						//手机蓝牙锁定
						if(memcmp(USART_RX_BUF,"LOCK",4)==0)	{
//							USART_RX_STA=0;
//							memset(USART_RX_BUF,0,USART_REC_LEN);
							DisLock();
							goto MAIN;
						}
						
						//功能选项选择
						key_num=Button4_4_Scan();	
						if(key_num)
						{
							if(key_num==13){
								if(arrow>0)arrow--;
								goto MENUNOCLR;
							}
							if(key_num==15){
								if(arrow<MaxParaNum-1)arrow++;
								goto MENUNOCLR;
							}
							if(key_num==16){
								switch(arrow)
								{
#if USE_FINGERPRINT
									case 0:Add_FR();		break;//录指
									case 1:Del_FR();		break;//删指纹
									case 2:SetPassworld();break;//修改密码
									case 3:Set_Time(); break;  //设置时间
									case 4:Add_Rfid(); break;  //录入卡片
									case 5:Massige(); break;  //显示信息
#else
									case 0:SetPassworld();break;//修改密码
									case 1:Set_Time(); break;  //设置时间
									case 2:Add_Rfid(); break;  //录入卡片
									case 3:Massige(); break;  //显示信息
#endif

									
//									
								}
								goto MENU;
							}		
						}delay_ms(1);
			}	
	}//while
			
			
			
			
		
		 
 }
 
 u8 DisErrCnt(void)
 {
	 int time=0;
	 u8 buf[64];
	 if(sys.errTime>0)//错误次数计数
	{
		
		OLED_Clear();
		while(1)
		{
			if(time++ == 1000)
			{
				time = 0;
				if(sys.errTime==0)
				{
					OLED_Clear();
					break;
				}
				Show_Str(0,16,128,16,"密码错误次数过多",16,0);
				sprintf(buf,"请%02d秒后重试", sys.errTime);
				Show_Str(20,32,128,16,buf,16,0);
				OLED_Refresh_Gram();//更新显示
			}
			delay_ms(1);
			if(4 == Button4_4_Scan())//返回
			{
				OLED_Clear();
				return 1;
			}
		}
	}
 }
 

//获取键盘数值
u16 GET_NUM(void)
{
	u8  key_num=0;
	u16 num=0;
		OLED_ShowNum(78,32,num,3,12);
	OLED_Refresh_Gram();//更新显示
	while(1)
	{
		key_num=Button4_4_Scan();	
		if(key_num != -1)
		{
//			if(key_num==13)return 0xFFFF;//'返回'键
//			if(key_num==14)return 0xFF00;//		
//			if(key_num>0&&key_num<10&&num<99)//'1-9'键(限制输入3位数)
//				num =num*10+key_num;		
//			if(key_num==15)num =num/10;//'Del'键			
//			if(key_num==10&&num<99)num =num*10;//'0'键
//			if(key_num==16)return num;  //'Enter'键
			
			switch(key_num)
				{
					case 1:
					case 2:
					case 3:
						if(key_num>0&&key_num<10&&num<99)//'1-9'键(限制输入3位数)
						num =num*10+key_num;		
					break;
					case 4://返回
						return 0xFFFF;
					return -1;
						
					break;
					case 5:
					case 6:
					case 7:
						if(key_num>0&&key_num<10&&num<99)//'1-9'键(限制输入3位数)
						num =num*10+key_num-1;
					break;
					case 8:num =num/10;//'del'键
					break;
					case 9:
					case 10:
					case 11:
						if(key_num>0&&key_num<10&&num<99)//'1-9'键(限制输入3位数)
						num =num*10+key_num-2;
					break;
					case 12: break;//DIS
					case 13:
					case 15:
						return 0xFF00;
					break;
					case 14:num =num*10;
					break;
					case 16:return num;
					break;
				}
		OLED_ShowNum(78,32,num,3,12);
	OLED_Refresh_Gram();//更新显示
		}
	}	
}
//密码锁
int password(void)
{
	int  key_num=0,i=0,satus=0;
	u16 num=0,num2=0,time3=0,time;
	u8 pwd[11]="          ";
	u8 hidepwd[11]="          ";
	u8 buf[64];
	OLED_Clear();//清屏

	if(DisErrCnt())return -1;//错误次数超限
	
	OLED_Clear();//清屏
	Show_Str(5,0,128,16,"密码:",16,0);
	Show_Str(10,16,128,12," 1   2   3  Bck",12,0);
	Show_Str(10,28,128,12," 4   5   6  Del",12,0);
	Show_Str(10,40,128,12," 7   8   9  Dis",12,0);
	Show_Str(10,52,128,12,"Clr  0  Clr  OK",12,0);
	OLED_Refresh_Gram();//更新显示
//	Show_Str(102,36,128,12,"显示",12,0);
//	Show_Str(0,52,128,12,"删除 清空   返回 确认",12,0);
	while(1)
	{
		key_num=Button4_4_Scan();	
		if(key_num != -1)
		{	
			printf("key=[%d]\r\n",key_num);
			DisFlag = 1;
			time3=0;
			if(key_num != -1)
			{	
				DisFlag = 1;
				time3=0;
				switch(key_num)
				{
					case 1:
					case 2:
					case 3:
						pwd[i]=key_num+0x30; //1-3
						hidepwd[i]='*';
						i++;
					break;
					case 4://返回
						OLED_Clear();
						delay_ms(500);
					return -1;
						
					break;
					case 5:
					case 6:
					case 7:
						pwd[i]=key_num+0x30-1; //4-6
						hidepwd[i]='*';
						i++;
					break;
					case 8:
						if( i > 0){
							pwd[--i]=' ';  //'del'键
							hidepwd[i]=' '; 
						}
					break;
					case 9:
					case 10:
					case 11:
						pwd[i]=key_num+0x30-2; //4-6
						hidepwd[i]='*';
						i++;
					break;
					case 12:satus=!satus; break;//DIS
					case 13:
					case 15:
						while(i--){
						pwd[i]=' ';  //'清空'键
						hidepwd[i]=' '; 
						}
						i=0;
					break;
					case 14:
						pwd[i]=0x30; //4-6
						hidepwd[i]='*';
						i++;
					break;
					case 16:
						goto UNLOCK;
					break;
				}
		}
		if(DisFlag == 1)
		{
			if(satus==0)OLED_ShowString(53,0,hidepwd,12);
			else OLED_ShowString(53,0,pwd,12);
		OLED_Refresh_Gram();//更新显示
		}
		
		time3++;
		if(time3%1000==0){
			OLED_Clear();//清屏
			return -1;
		}
		}
	}

UNLOCK:	
		for(i=0; i<10; i++){   //验证虚伪密码
			if(pwd[i]==sys.passwd1[num])num++;
				else num=0;
			if(num==6)
				break;
		}
		for(i=0; i<10; i++){   //验证密码
			if(pwd[i]==sys.passwd2[num2])num2++;
				else num2=0;
			if(num2==6)
				break;
		}
		if(num==6 | num2==6){
			DisUnLock();
			OLED_Clear();//清屏
			sys.errCnt = 0;
			return 0;
		}
		else {
			sys.errCnt++;//错误次数计数
			if(sys.errCnt>MAXERRTIMES)
				sys.errTime = 30; //30秒不能再解锁
			OLED_Clear();//清屏
			Show_Str(45,48,128,16,"密码错误!",16,0);
			OLED_Refresh_Gram();//更新显示
			beep_on_mode1();
			delay_ms(1500);
			OLED_Clear();//清屏
			return -1;
		}
	
}


//显示确认码错误信息
void ShowErrMessage(u8 ensure)
{
	Show_Str(0,48,128,12,(u8*)EnsureMessage(ensure),12,0);	
	OLED_Refresh_Gram();//更新显示
	delay_ms(1000);
	OLED_ShowString(0,48,"                   ",12);	
	
	OLED_Refresh_Gram();//更新显示
}
//录指纹
void Add_FR(void)
{
	u8 i,ensure ,processnum=0;
	int key_num;
	u16 ID;
	OLED_Clear();//清屏
	while(1)
	{
		key_num=Button4_4_Scan();	
		if(key_num==16){
			OLED_Clear();//清屏
			return ;
		}
		switch (processnum)
		{
			case 0:
				//OLED_Clear();//清屏
				i++;
				Show_Str(0,0,128,16,"=== 录入指纹 ===",16,0);
				Show_Str(0,24,128,12,"请按指纹!  ",12,0);	
				Show_Str(104,52,128,12,"返回",12,0);		
				OLED_Refresh_Gram();//更新显示	
				ensure=PS_GetImage();
				if(ensure==0x00) 
				{
					BEEP=0;
					ensure=PS_GenChar(CharBuffer1);//生成特征
					BEEP=1;
					if(ensure==0x00)
					{
						Show_Str(0,24,128,12,"指纹正常!    ",12,0);
						OLED_Refresh_Gram();//更新显示	
						i=0;
						processnum=1;//跳到第二步						
					}else ShowErrMessage(ensure);				
				}else ShowErrMessage(ensure);
				//OLED_Clear();//清屏
				break;
			
			case 1:
				i++;
				Show_Str(0,24,128,12,"请再按一次指纹",12,0);
				OLED_Refresh_Gram();//更新显示		
				ensure=PS_GetImage();
				if(ensure==0x00) 
				{
					BEEP=0;
					ensure=PS_GenChar(CharBuffer2);//生成特征
					BEEP=1;
					if(ensure==0x00)
					{
						Show_Str(0,24,128,12,"指纹正常!",12,0);	
						OLED_Refresh_Gram();//更新显示
						i=0;
						processnum=2;//跳到第三步
					}else ShowErrMessage(ensure);	
				}else ShowErrMessage(ensure);		
				//OLED_Clear();//清屏
				break;

			case 2:		
				Show_Str(0,24,128,12,"对比两次指纹        ",12,0);
				OLED_Refresh_Gram();//更新显示
				ensure=PS_Match();
				if(ensure==0x00) 
				{
					Show_Str(0,24,128,12,"两次指纹一样       ",12,0);
					OLED_Refresh_Gram();//更新显示
					processnum=3;//跳到第四步
				}
				else 
				{
					Show_Str(0,24,128,12,"对比失败 请重录    ",12,0);	
					OLED_Refresh_Gram();//更新显示
					ShowErrMessage(ensure);
					i=0;
					OLED_Clear();//清屏
					processnum=0;//跳回第一步		
				}
				delay_ms(1200);
				//OLED_Clear();//清屏
				break;

			case 3:
			Show_Str(0,24,128,12,"生成指纹模板...    ",12,0);
			OLED_Refresh_Gram();//更新显示	
				ensure=PS_RegModel();
				if(ensure==0x00) 
				{
//					
					Show_Str(0,24,128,12,"生成指纹模板成功!",12,0);
					OLED_Refresh_Gram();//更新显示
					processnum=4;//跳到第五步
				}else {processnum=0;ShowErrMessage(ensure);}
				delay_ms(1200);
				break;
				
			case 4:	
				//OLED_Clear();//清屏
			Show_Str(0,24,128,12,"请输入储存ID:        ",12,0);
			Show_Str(122,52,128,12," ",12,0);
			Show_Str(0,52,128,12,"删除 清空      确认",12,0);
			OLED_Refresh_Gram();//更新显示
				do
					ID=GET_NUM();
				while(!(ID<AS608Para.PS_max));//输入ID必须小于模块容量最大的数值
				ensure=PS_StoreChar(CharBuffer2,ID);//储存模板
				if(ensure==0x00) 
				{			
          OLED_Clear_NOupdate();//清屏
					Show_Str(0,30,128,16,"录指纹成功!",16,0);	
					PS_ValidTempleteNum(&ValidN);//读库指纹个数
					Show_Str(66,52,128,12,"剩余",12,0);
					OLED_ShowNum(90,52,AS608Para.PS_max-ValidN,3,12);
					OLED_Refresh_Gram();//更新显示
					delay_ms(1500);
					OLED_Clear();	
					return ;
				}else {processnum=0;ShowErrMessage(ensure);}
				OLED_Clear();//清屏					
				break;				
		}
		delay_ms(400);
		if(i==10)//超过5次没有按手指则退出
		{
			OLED_Clear();
			break;
		}				
	}
}

//刷指纹
int press_FR(void)
{
	SearchResult seach;
	u8 ensure;
	char str[256];
	
	
	if(DisErrCnt())return -1;//错误次数超限
	ensure=PS_GetImage();
	
	OLED_Clear_NOupdate();
	Show_Str(0,0,128,16,"正在检测指纹",16,0);
	OLED_Refresh_Gram();//更新显示
	if(ensure==0x00)//获取图像成功 
	{	
		ensure=PS_GenChar(CharBuffer1);
		if(ensure==0x00) //生成特征成功
		{		
			
			ensure=PS_HighSpeedSearch(CharBuffer1,0,AS608Para.PS_max,&seach);
			if(ensure==0x00)//搜索成功
			{				
				OLED_Clear_NOupdate();
				Show_Str(20,10,128,24,"解锁中...",24,0);	
				OLED_Refresh_Gram();//更新显示
				Walkmotor_ON();
				Show_Str(20,10,128,24,"已解锁!",24,0);
				OLED_Refresh_Gram();//更新显示
				OLED_Show_Font(112,18,1);//开锁				
				//str=mymalloc(SRAMIN,2000);
				sprintf(str,"ID:%d     匹配分",seach.pageID);
				Show_Str(0,52,128,12,(u8*)str,12,0);	
				sprintf(str,":%d",seach.mathscore);
				Show_Str(96,52,128,12,(u8*)str,12,0);	
				//myfree(SRAMIN,str);
				OLED_Refresh_Gram();//更新显示
				delay_ms(1800);
				OLED_Clear();
				return 0;
			}
			else {
				sys.errCnt++;//错误次数计数
				if(sys.errCnt>MAXERRTIMES)
					sys.errTime = 30; //30秒不能再解锁
				ShowErrMessage(ensure);	
				OLED_Refresh_Gram();//更新显示
				beep_on_mode1();
				OLED_Clear();
				return -1;
			}				
	  }
		else
			ShowErrMessage(ensure);
		
	OLED_Refresh_Gram();//更新显示
	 delay_ms(2000);
		OLED_Clear();
		
	}
	return -1;	
}

//删除指纹
void Del_FR(void)
{
	u8  ensure;
	u16 num;
	OLED_Clear();
	Show_Str(0,0,128,16,"=== 删除指纹 ===",16,0);	
	Show_Str(0,16,128,12,"输入指纹ID:",12,0);
	Show_Str(0,52,128,12,"返回 清空    确认删除",12,0);
	OLED_Refresh_Gram();//更新显示
	delay_ms(50);
//	AS608_load_keyboard(0,170,(u8**)kbd_delFR);
	num=GET_NUM();//获取返回的数值
	if(num==0xFFFF)
		goto MENU ; //返回主页面
	else if(num==0xFF00)
		ensure=PS_Empty();//清空指纹库
	else 
		ensure=PS_DeletChar(num,1);//删除单个指纹
	if(ensure==0)
	{
		OLED_Clear();
		Show_Str(0,20,128,12,"删除指纹成功!",12,0);		
		Show_Str(80,48,128,12,"剩余",12,0);		
	OLED_Refresh_Gram();//更新显示
	}
  else
		ShowErrMessage(ensure);	
	
	OLED_Refresh_Gram();//更新显示
	PS_ValidTempleteNum(&ValidN);//读库指纹个数
	OLED_ShowNum(110,48,AS608Para.PS_max-ValidN,3,12);
	delay_ms(1200);
	
MENU:	
	OLED_Clear();
}
//修改密码
void SetPassworld(void)
{
	int pwd_ch=0;
	int  key_num=0,i=0,satus=0;
	u16 time4=0;
	u8 pwd[6]="      ";
	u8 hidepwd[6]="      ";
	u8 buf[10];
	OLED_Clear();//清屏
	Show_Str(10,16,128,12," 1   2   3  Bck",12,0);
	Show_Str(10,28,128,12," 4   5   6  Del",12,0);
	Show_Str(10,40,128,12," 7   8   9  Dis",12,0);
	Show_Str(10,52,128,12,"Clr  0  Chg  OK",12,0);
	
	
	Show_Str(5,0,128,16,"新密码",16,0);
	sprintf((char*)buf,"%d:",pwd_ch+1);
	Show_Str(5,48,128,16,buf,16,0);
	OLED_Refresh_Gram();//更新显示
	while(1)
	{
		key_num=Button4_4_Scan();	
		if(key_num != -1)
		{	
			DisFlag = 1;
			time4=0;
			switch(key_num)
			{
				case 1:
				case 2:
				case 3:
					pwd[i]=key_num+0x30; //1-3
					hidepwd[i]='*';
					i++;
				break;
				case 4://返回
					OLED_Clear();
					delay_ms(500);
				return ;
					
				break;
				case 5:
				case 6:
				case 7:
					pwd[i]=key_num+0x30-1; //4-6
					hidepwd[i]='*';
					i++;
				break;
				case 8:
					if( i > 0){
						pwd[--i]=' ';  //'del'键
						hidepwd[i]=' '; 
					}
				break;
				case 9:
				case 10:
				case 11:
					pwd[i]=key_num+0x30-2; //4-6
					hidepwd[i]='*';
					i++;
				break;
				case 12:satus=!satus; break;//DIS
				case 13:
					sprintf((char*)buf,"%d:",pwd_ch+1);
					Show_Str(5,48,128,16,buf,16,0);
					pwd_ch = !pwd_ch;
				case 15:
					while(i--){
					pwd[i]=' ';  //'清空'键
					hidepwd[i]=' '; 
					}
					i=0;
				break;
				case 14:
					pwd[i]=0x30; //4-6
					hidepwd[i]='*';
					i++;
				break;
				case 16:
					goto MODIF;
				break;
			}
		}
		if(DisFlag == 1)
		if(satus==0)
		{
			OLED_ShowString(70,0,hidepwd,12);
			OLED_Refresh_Gram();//更新显示
		}
		else 
		{
			OLED_ShowString(70,0,pwd,12);
			OLED_Refresh_Gram();//更新显示
		}
		
		time4++;
		if(time4%1000==0){
			OLED_Clear();//清屏
			DisFlag = 1;
			return ;
		}
	}	
	
	
MODIF:
	if(pwd_ch==0)
	{
		memcpy(sys.passwd1,pwd,7);
		STMFLASH_Write(SYS_SAVEADDR,(u16*)&sys,sizeof(sys));//保存到内部FLASH
		
		//STMFLASH_Read(SYS_SAVEADDR,(u16*)&sys,sizeof(sys)); //读取
		printf("pwd=%s",sys.passwd1);
	}
	else
	{		
		memcpy(sys.passwd2,pwd,7);
		STMFLASH_Write(SYS_SAVEADDR,(u16*)&sys,sizeof(sys));//保存密码到内部FLASH
//		STMFLASH_Write(0X08090004,(u32*)pwd,2);//保存密码到内部eeprom
		//STMFLASH_Read(SYS_SAVEADDR,(u16*)&sys,sizeof(sys)); //读取密码2
		printf("pwd2=%s",sys.passwd1);
	}
	OLED_Clear();//清屏
	Show_Str(0,48,128,16,"密码修改成功 !",16,0);
	OLED_Refresh_Gram();//更新显示
	delay_ms(1000);
}
//设置时间
void Set_Time(void)
{
//	RTC_TimeTypeDef RTC_TimeStruct;
//	RTC_DateTypeDef calendar;
	u16 year;
	u8 mon,dat,wek,hour,min,sec;
	u16 time5=0;
	u8 tbuf[40];
	int key_num;
	int st=0;
	
//	RTC_GetTime(RTC_Format_BIN,&RTC_TimeStruct);
//	RTC_GetDate(RTC_Format_BIN, &calendar);
	year=calendar.w_year;
	mon=calendar.w_month;
	dat=calendar.w_date;
	wek=calendar.week;
	hour=calendar.hour;
	min=calendar.min;
	sec=calendar.sec;
	OLED_Clear();
	Show_Str(98,38,128,12,"<--",12,0);
	Show_Str(0,52,128,12,"减  加   切换  确定",12,0);
	
	OLED_Refresh_Gram();//更新显示
	while(1)
	{
		time5++;
		key_num=Button4_4_Scan();	
			if(key_num==12 | time5==3000){
				OLED_Clear();//清屏
				return ;
			}
			if(key_num==13){
				switch(st)
				{
					case 0:if(hour>0)hour--;break;
					case 1:if(min>0)min--;break;
					case 2:if(sec>0)sec--;break;
					case 3:if(wek>0)wek--;break;
					case 4:if(year>0)year--;break;
					case 5:if(mon>0)mon--;break;
					case 6:if(dat>0)dat--;break;
				}
			}
			if(key_num==14){
				switch(st)
				{
					case 0:if(hour<23)hour++;break;
					case 1:if(min<59)min++;break;
					case 2:if(sec<59)sec++;break;
					case 3:if(wek<7)wek++;break;
					case 4:if(year<2099)year++;break;
					case 5:if(mon<12)mon++;break;
					case 6:if(dat<31)dat++;break;
				}
			}
			if(key_num==15){
				if(st<7)st++;
				if(st==7)st=0;
			}
			if(key_num==16){
				break;
			}
		if(time5%250==0)
		{
			switch(st)			//闪烁
				{
					case 0:OLED_ShowString(0,0,"  ",24);break;
					case 1:OLED_ShowString(36,0,"  ",24);break;
					case 2:OLED_ShowString(72,0,"  ",24);break;
					case 3:OLED_ShowString(110,12,"   ",12);break;
					case 4:OLED_ShowString(68,26,"    ",12);break;
					case 5:OLED_ShowString(98,26,"  ",12);break;
					case 6:OLED_ShowString(116,26,"  ",12);break;
				}
			OLED_Refresh_Gram();//更新显示
		}
		if(time5%500==0)
		{
			time5=0;
			sprintf((char*)tbuf,"%02d:%02d:%02d",hour,min,sec); 
			OLED_ShowString(0,0,tbuf,24);	
			//RTC_GetDate(RTC_Format_BIN, &calendar);
			sprintf((char*)tbuf,"%04d-%02d-%02d",year,mon,dat); 
			OLED_ShowString(68,26,tbuf,12);		
			sprintf((char*)tbuf,"%s",week[wek]); 
			OLED_ShowString(110,12,tbuf,12);	
			OLED_Refresh_Gram();//更新显示
		}delay_ms(1);
	}
//	RTC_Set_Time(hour,min,sec,RTC_H12_AM);	//设置时间
//	RTC_Set_Date(year,mon,dat,wek);		//设置日期
	RTC_Set(year,mon,dat,hour, min,sec);
	OLED_Clear();
	Show_Str(20,48,128,16,"设置成功!",16,0);
	OLED_Refresh_Gram();//更新显示
	delay_ms(1000);
}

//录入新卡
u8 Add_Rfid(void)
{
	u8 ID;
	u16 time6=0;
	u8 i,key_num,status=1,card_size;
	OLED_Clear();
	Show_Str(0,0,128,16,"=== 录入卡片 ===",16,0);	
	Show_Str(0,20,128,12,"请放入新卡片:",12,0);	
	Show_Str(0,52,128,12,"返回",12,0);
	OLED_Refresh_Gram();//更新显示
	MFRC522_Initializtion();			//初始化MFRC522
	while(1)
	{
		AntennaOn();
		status=MFRC522_Request(0x52, card_pydebuf);			//寻卡
		if(status==0)		//如果读到卡
		{
			printf("rc522 ok\r\n");
			Show_Str(0,38,128,12,"读卡成功!",12,0);
			OLED_Refresh_Gram();//更新显示
			status=MFRC522_Anticoll(card_numberbuf);			//防撞处理			
			card_size=MFRC522_SelectTag(card_numberbuf);	//选卡
			status=MFRC522_Auth(0x60, 4, card_key0Abuf, card_numberbuf);	//验卡
			status=MFRC522_Write(4, card_writebuf);				//写卡(写卡要小心,特别是各区的块3)
			status=MFRC522_Read(4, card_readbuf);					//读卡
			//printf("卡的类型:%#x %#x",card_pydebuf[0],card_pydebuf[1]);
			//卡序列号显,最后一字节为卡的校验码
			printf("卡的序列号:");
			for(i=0;i<5;i++)
			{
				printf("%#x ",card_numberbuf[i]);
			}
			printf("\r\n");
			//卡容量显示,单位为Kbits
			//printf("卡的容量:%dKbits\n",card_size);
			AntennaOff();
			
			OLED_Clear_NOupdate();
			Show_Str(0,12,128,12,"请输入储存ID(0-9):  ",12,0);
			Show_Str(122,52,128,12," ",12,0);
			Show_Str(0,52,128,12,"删除 清空      确认",12,0);
			OLED_Refresh_Gram();//更新显示
				do
					ID=GET_NUM();
				while(!(ID<10));//输入ID必须小于最大容量
			printf("正在录入卡片:%d\r\n",ID);
			OLED_Clear_NOupdate();
			Show_Str(0,38,128,12,"正在录入.",12,0);
			OLED_Refresh_Gram();//更新显示
//			memcpy(sys.cardid[ID],card_numberbuf,5);
			for(i=0;i<5;i++)
			{
				sys.cardid[ID][i] = card_numberbuf[i];
			}
				
			STMFLASH_Write(SYS_SAVEADDR,(u16*)&sys,sizeof(sys));//保存到内部FLASH
//			STMFLASH_Write(0X080f0004,(u32*)card_numberbuf,2);
//			STMFLASH_Read(0X080f0004,(u32*)cardid,1); //读取卡号1
			for(i=0;i<10;i++)
			printf("cardid={%X,%X,%X,%X}\r\n",sys.cardid[i][0],sys.cardid[i][1],sys.cardid[i][2],sys.cardid[i][3]);
			Show_Str(0,38,128,12,"录入成功!",12,0);
			OLED_Refresh_Gram();//更新显示
			delay_ms(1000);
			OLED_Clear();
			return 0;
		}
		key_num=Button4_4_Scan();	
		time6++;
		if(time6%5000==0 | key_num==13)
		{
			OLED_Clear();
			return 1;
		}
	}
}
//rfid卡锁
u8 MFRC522_lock(void)
{
	u8 i,j,status=1,card_size;
	u8 count;
	u8 prtfbuf[64];
	
	AntennaOn();
  	status=MFRC522_Request(0x52, card_pydebuf);			//寻卡
	if(status==0)		//如果读到卡
	{
		if(DisErrCnt())return -1;//错误次数超限
		printf("rc522 ok\r\n");
		status=MFRC522_Anticoll(card_numberbuf);			//防撞处理			
		card_size=MFRC522_SelectTag(card_numberbuf);	//选卡
		status=MFRC522_Auth(0x60, 4, card_key0Abuf, card_numberbuf);	//验卡
		status=MFRC522_Write(4, card_writebuf);				//写卡(写卡要小心,特别是各区的块3)
		status=MFRC522_Read(4, card_readbuf);					//读卡
		//MFRC522_Halt();															//使卡进入休眠状态
		//卡类型显示
		
		//printf("卡的类型:%#x %#x",card_pydebuf[0],card_pydebuf[1]);
		

		//卡序列号显,最后一字节为卡的校验码
		
		count=0;
		
		for(j=0;j<10;j++){
		printf("\r\n卡%d 的序列号:",j);
			for(i=0;i<5;i++)
			{
				printf("%x=%x    ",card_numberbuf[i],sys.cardid[j][i]);
				if(card_numberbuf[i]==sys.cardid[j][i])count++;
			}
		printf("\r\n");
			if(count>=4)
			{
				sys.errCnt = 0;
				OLED_Clear_NOupdate();
				sprintf(prtfbuf,"RFID:%d匹配成功",j);
				Show_Str(12,13,128,20,prtfbuf,12,0); 
				OLED_Refresh_Gram();//更新显示
				delay_ms(500);
				DisUnLock();
				return 0;
			}else count=0;
		}
		{
			sys.errCnt++;//错误次数计数
			
			if(sys.errCnt>MAXERRTIMES)
				sys.errTime = 30; //30秒不能再解锁
			OLED_Clear(); 
			Show_Str(12,13,128,20,"卡片错误",12,0); 
			OLED_Refresh_Gram();//更新显示
			beep_on_mode1();
			OLED_Clear(); 
			OLED_Show_Font(56,48,0);//锁
			DisFlag = 1;
		}
		
		printf("\n");
		//卡容量显示,单位为Kbits
		
		//printf("卡的容量:%dKbits\n",card_size);
		
		
		
		//读一个块的数据显示
//		printf("卡数据:\n");
//		for(i=0;i<2;i++)		//分两行显示
//		{
//			for(j=0;j<9;j++)	//每行显示8个
//			{
//				printf("%#x ",card_readbuf[j+i*9]);
//			}
//			printf("\n");
//		}

	}	
	
	AntennaOff();
	return 1;
}
//显示信息
void Massige(void)
{
	OLED_Clear();
	Show_Str(0,0,128,12,"智能能门锁系统",12,0); 
	
	OLED_Refresh_Gram();//更新显示
	delay_ms(3000);
}

 
 //显示时间
void Display_Data(void)
{
	static u8 t=1;	
	u8 tbuf[40];
	if(t!=calendar.sec)
	{
		t=calendar.sec;
		sprintf((char*)tbuf,"%02d:%02d:%02d",calendar.hour,calendar.min,calendar.sec); 
		OLED_ShowString(0,0,tbuf,24);	
		//printf(tbuf);
		sprintf((char*)tbuf,"%04d-%02d-%02d",calendar.w_year,calendar.w_month,calendar.w_date); 
		OLED_ShowString(68,26,tbuf,12);		
		//printf(tbuf);
		sprintf((char*)tbuf,"%s",week[calendar.week]); 
		//printf(tbuf);
		OLED_ShowString(110,12,tbuf,12);
		DisFlag = 1;//更新显示
	}
}
 
 //开机信息
void starting(void)
{
	u8 cnt = 0;
	u8 ensure;
	char str[64];			  
	u8 key;
//	OLED_Show_Image(0);	//image
//	OLED_Refresh_Gram();//更新显示
	Show_Str(16,12,128,16,"智能门锁系统",16,0);
	OLED_Refresh_Gram();//更新显示
	delay_ms(2000);
	
/*********************************开机信息提示***********************************/
#if USE_FINGERPRINT
	OLED_Clear();
	Show_Str(0,0,128,12,"fingerprint system!",12,0); 
	Show_Str(0,12,128,12,"connect to as608",12,0);
	OLED_Refresh_Gram();//更新显示
	while(PS_HandShake(&AS608Addr))//与AS608模块握手
	{
		cnt++;if(cnt>10)break;
		delay_ms(400);
		Show_Str(0,24,128,12,"connect failed! ",12,0);
		OLED_Refresh_Gram();//更新显示
		delay_ms(800);
		Show_Str(0,24,128,12,"connect to as608  ",12,0);	
		printf("connect to as608..\r\n");
				OLED_Refresh_Gram();//更新显示
	}
	if(cnt>10)Show_Str(0,24,128,12,"connect failed!",12,0);	
	
	OLED_Refresh_Gram();//更新显示
	sprintf(str,"baud:%d  addr:%x",usart2_baund,AS608Addr);
	Show_Str(0,36,128,12,(u8*)str,12,0);
	OLED_Refresh_Gram();//更新显示
	ensure=PS_ValidTempleteNum(&ValidN);//读库指纹个数
	if(ensure!=0x00)
		printf("ERR:010\r\n");
		//ShowErrMessage(ensure);//显示确认码错误信息	
	ensure=PS_ReadSysPara(&AS608Para);  //读参数 
//	if(ensure==0x00)
//	{
		sprintf(str,"capacity:%d  Lv: %d",AS608Para.PS_max-ValidN,AS608Para.PS_level);
		Show_Str(0,48,128,12,(u8*)str,12,0);
		OLED_Refresh_Gram();//更新显示
//	}
//	else
//		ShowErrMessage(ensure);	//显示确认码错误信息	
	
//	delay_ms(1000);
//
#endif
	OLED_Clear();
}

 
void SysPartInit(void )   //系统参数初始化 
{
		STMFLASH_Read(SYS_SAVEADDR,(u16*)&sys,sizeof(sys)); //读取
		if(sys.HZCFlag != 980706)
		{
			memset(&sys,0,sizeof(sys));
			sys.HZCFlag = 980706;
			strcpy((char *)sys.passwd1, "123456");//密码
			strcpy((char *)sys.passwd2, "980706");//密码
			STMFLASH_Write(SYS_SAVEADDR,(u16*)&sys,sizeof(sys));//保存到内部FLASH
			printf("初始化配置成功\r\n");
		}else
		{
			printf("欢迎使用智能门锁\r\n");
		}
}
 
 

总结

本项目通过STM32控制多个外设,结合指纹识别、门禁卡与密码开锁三种开锁方式,构建了一个智能门锁系统。系统实现了多种安全措施,如数据存储、指纹验证、密码保护、门禁卡管理等,能够有效地提升安全性和用户体验。需要获取完整资料的,可以私信留言我,记得先点赞关注收藏先喔,完整资料如图所示:

相关推荐
7yewh1 小时前
嵌入式产品级-超小尺寸热成像相机(从0到1 硬件-软件-外壳)
单片机·嵌入式硬件·mcu·数码相机·物联网
esmember1 小时前
电路研究9——GPRS用的AT命令手册
嵌入式硬件
冰糖小新新1 小时前
ELF2开发板(飞凌嵌入式)基本使用的搭建
嵌入式硬件
列兵阿甘2 小时前
嵌入式Linux驱动开发之pinctrl和gpio子系统
linux·驱动开发·嵌入式硬件
小猪写代码2 小时前
STM32 FreeROTS 任务创建和删除实验(静态方法)
stm32·单片机·嵌入式硬件
Try1harder3 小时前
联德胜w801开发板(四)实现腾讯云mqtt的订阅和发布
单片机·嵌入式硬件·物联网
UIUI4 小时前
Visual Studio Code + Stm32 (IAR)
ide·vscode·stm32
工程师平哥10 小时前
cmake foreach 条件判断
c语言·单片机·嵌入式硬件·mcu
小猪写代码10 小时前
STM32 FreeRTOS任务通知
stm32·单片机·嵌入式硬件