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

news2025/1/21 20:02:39

目录

项目演示

项目概述

硬件组成:

功能实现

1. 开锁模式

1.1 按键密码开锁

1.2 门禁卡开锁

1.3 指纹开锁

2. 功能备注

3. 硬件模块工作流程

3.1 步进电机控制

3.2 蜂鸣器提示

3.3 OLED显示

3.4 指纹与卡片管理

项目源代码分析

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

1.1 开机界面

1.2 主界面

1.3 开锁功能

2. 指纹录入与删除

3.门禁卡的录入

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 开机界面
void starting(void)
{
    OLED_Clear();
    Show_Str(16,12,128,16,"智能门锁系统",16,0);
    OLED_Refresh_Gram();
    delay_ms(2000);
}

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

1.2 主界面
			/********************主界面**************************/

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 开锁功能

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

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

蓝牙密码开锁:

						//手机蓝牙解锁密码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);//锁
						}
						

按键密码开锁: 

//密码锁
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;
		}
	
}

指纹开锁:

//刷指纹
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;	
}

门禁卡开锁:

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

2. 指纹录入与删除

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

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

3.门禁卡的录入

//录入新卡
u8 Add_Rfid(void)
{
    //录入卡片逻辑
    ......
}

4. 数据存储与恢复

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

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

完整的main.c文件

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2279994.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024年度总结:从后端Java到全栈成长的蜕变

目录 前言1. 用数据与实践书写成长篇章2. 技术与生活的双重蜕变3. 技术的进阶与生活的绽放 前言 今年是我入行的第十年&#xff0c;也是记录在CSDN平台上的第五年。这五年来&#xff0c;我始终坚持记录成长的点滴&#xff0c;将个人事业与博客创作紧密相连。一路走来&#xff0…

行人识别检测数据集,yolo格式,PASICAL VOC XML,COCO JSON,darknet等格式的标注都支持,准确识别率可达99.5%

作者简介&#xff1a; 高科&#xff0c;先后在 IBM PlatformComputing从事网格计算&#xff0c;淘米网&#xff0c;网易从事游戏服务器开发&#xff0c;拥有丰富的C&#xff0c;go等语言开发经验&#xff0c;mysql&#xff0c;mongo&#xff0c;redis等数据库&#xff0c;设计模…

Web3 游戏周报(1.13 - 1.19)

回顾上周的区块链游戏概况&#xff0c;查看 Footprint Analytics 与 ABGA 最新发布的数据报告。 【1.13–1.19】Web3 游戏行业动态 索尼区块解决方案实验室 (Sony BSL) 宣布其以太坊 L2 区块链 Soneium 主网上线。Hyve Labs 融资 275 万美元&#xff0c;推动 Web3 游戏基础设…

Java RSA加密工具类(含密钥对生成和根据私钥计算公钥)

RSA算法是一种常用的非对称加密算法&#xff0c;它具有以下主要特点&#xff1a; 1.非对称性&#xff1a;RSA 使用一对密钥——公钥和私钥。公钥用于加密&#xff0c;私钥用于解密&#xff0c;也可以反过来使用私钥签名、公钥验证。相对于对称加密的单一密钥&#xff0c;非对称…

无数据库开源Wiki引擎WikiDocs

简介 什么是 WikiDocs &#xff1f; WikiDocs 是一个无数据库的开源 Markdown 文件平面 Wiki 引擎。它旨在提供一个简单、灵活且易于使用的 Wiki 解决方案&#xff0c;允许用户创建和管理文档而无需依赖传统数据库。 主要特点 无数据库&#xff1a;使用纯文本文件存储数据&am…

Spring Boot 配置(官网文档解读)

目录 摘要 Spring Boot 配置加载顺序 配置文件加载顺序 Spring Boot 配置加载方式 Value Value 注解简单示例 ConfigurationProperties 启动 ConfigurationProperties ConfigurationProperties 验证 ConfigurationProperties 与 Value 对比 Autowired Autowired 自…

Comment(爆破+git泄漏+二次注入)

通过爆破密码的后三位&#xff0c;获得账号为&#xff1a;zhangwei666 F12查看控制台 使用bugscanteam的githack工具&#xff0c;下载泄漏的源码&#xff0c;根据控制台的提示&#xff0c;完整源码还在历史的commit中 git log –reflog 查看历史记录 查看最新的提交记录&#…

C++otlv4连接sql serveer使用记录(注意点)

C使用otlv4在做插入时&#xff0c;有一些设计的坑需要注意 插入数据&#xff1a; 当要给表中插入单个字符时&#xff0c;数据库表设计使用varchar(1)是合理的&#xff0c;但是otlv4一直报错char。 后续查很久才知道&#xff0c;otlv4所写的绑定的字符数组的长度应该实际数组…

2024又是一年的CSDN之旅-总结过去展望未来

一、前言 一年就这样在忙忙碌碌的工作和生活中一晃而过&#xff0c;总结今年在CSDN上发表的博客&#xff0c;也有上百篇之多&#xff0c;首先感谢CSDN这个平台&#xff0c;能让我有一个地方记录工作中的点点滴滴&#xff0c;也在上面学到了不少知识&#xff0c;解决了工作中遇到…

JDK长期支持版本(LTS)

https://blogs.oracle.com/java/post/the-arrival-of-java-23 jdk长期支持版本&#xff08;LTS&#xff09;&#xff1a;JDK 8、11、17、21&#xff1a;

大数据学习(37)- Flink运行时架构

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主哦&#x1f91…

“AI 大模型内容安全审核软件系统:守护网络世界的卫士

在如今这个信息爆炸的互联网时代&#xff0c;网络上的内容那是五花八门、层出不穷。这时候&#xff0c;咱就得靠 AI 大模型内容安全审核软件系统来给咱把把关了。 咱就说社交媒体平台吧&#xff0c;每天都有海量的用户在上面发布文字、图片、视频啥的。要是没有一个靠谱的审核系…

pyspark连接clickhouse数据库的方式(其它数据库同样适用)

目录 一、背景简记二、pyspark连接clickhouse方式记录三、结语参考学习博文 一、背景简记 实际工作中&#xff0c;大部分所用的数据存储地址都是在数据库中&#xff0c;如我司现在常用的数据库是clickhouse&#xff0c;相关数据的统计分析都在此上操作。如果想用pyspark连接cl…

C 语言雏启:擘画代码乾坤,谛观编程奥宇之初瞰

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。* 这一课主要是让大家初步了解C语言&#xff0c;了解我们的开发环境&#xff0c;main函数&#xff0c;库…

nacos2.3.0 接入pgsql或其他数据库

首先尝试使用官方插件进行扩展&#xff0c;各种报错后放弃&#xff0c;不如自己修改源码吧。 一、官方解决方案 1、nocos 文档地址&#xff1a;Nacos 配置中心简介, Nacos 是什么 | Nacos 官网 2、官方解答&#xff1a;nacos支持postgresql数据库吗 | Nacos 官网 3、源码下载地…

随遇随记篇

vue 函数 unref() 获取原始值 ref 定义的属性 需要 .value 才能拿到值&#xff0c;unref 直接返回原始值&#xff1b;若属性不是ref 定义的&#xff0c;也是直接返回原始值&#xff1b; /* description: 是否必填*/required?: boolean | Ref<boolean>.....let value …

网站HTTP改成HTTPS

您不仅需要知道如何将HTTP转换为HTTPS&#xff0c;还必须在不妨碍您的网站自成立以来建立的任何搜索排名权限的情况下进行切换。 为什么应该从HTTP转换为HTTPS&#xff1f; 与非安全HTTP于不同&#xff0c;安全域使用SSL&#xff08;安全套接字层&#xff09;服务器上的加密代…

微软Win10 RP 19045.5435(KB5050081)预览版发布!

系统之家1月20日最新报道&#xff0c;微软面向Release Preview频道的Windows Insider项目成员&#xff0c;发布了适用于Windows10 22H2版本的KB5050081更新&#xff0c;更新后系统版本号将升至19045.5435。本次更新增加了对GB18030-2022标准的支持&#xff0c;同时新版日历将为…

从提供的 package.json 文件可以看出,项目已经集成了 vue-cli-service lint --fix,并且配置了相关的工具和脚本

文章目录 1. 确认 vue-cli-service lint 已集成2. 确认 lintOnSave 是否启用示例&#xff1a;vue.config.js 3. 确认 ESLint 配置4. 确认 Git 钩子配置5. 如何实现保存时自动修复&#xff08;1&#xff09;启用 lintOnSave&#xff08;2&#xff09;配置编辑器的 ESLint 插件&a…

2024年博客之星主题创作|Android 开发:前沿技术、跨领域融合与就业技能展望

目录 引言 一、推动 Android 应用创新的核心力量 1.1 人工智能与机器学习的崛起 1.2 增强现实&#xff08;AR&#xff09;与虚拟现实&#xff08;VR&#xff09;的应用扩展 1.3 5G技术的推动 1.4 跨平台开发技术的成熟 1.4.1 React Native 1.4.2 Flutter 1.4.3 Taro …