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

目录

项目演示

项目概述

硬件组成:

功能实现

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(三)线性代数之二阶和三阶行列式详解

在前端开发中&#xff0c;尤其是在WebGL、图形渲染、或是与地图、模型计算相关的应用场景里&#xff0c;行列式的概念常常在计算变换矩阵、进行坐标变换或进行图形学算法时被使用。理解二阶和三阶行列式对于理解矩阵运算、旋转、平移等操作至关重要。下面&#xff0c;我将结合具…

基于GRU实现股价多变量时间序列预测(PyTorch版)

前言 系列专栏:【深度学习:算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域,讨论了各种复杂的深度神经网络思想,如卷积神经网络、循环神经网络、生成对抗网络、门控循环单元、长短期记…

【EdgeAI实战】(1)STM32 边缘 AI 生态系统

【EdgeAI实战】&#xff08;1&#xff09;STM32 边缘 AI 生态系统 【EdgeAI实战】&#xff08;1&#xff09;STM32 边缘 AI 生态系统 1. STM32 边缘人工智能1.1 X-CUBE-AI 扩展包1.2 STM32 AI Model Zoo1.3 ST AIoT Craft 2. STM32N6 AI 生态系统 (STM32N6-AI)2.1 STM32N6 AI 产…

DeepSeek-R1性能如何?如何使用DeepSeek-R1和o1 Pro模型

我们一起来看看DeepSeek-R1模型和OpenAI o1模型的能力如何&#xff1f;接下来&#xff0c;我们先看数据结果&#xff0c;然后再实际体验&#xff0c;我们今天就让他们写个python爬虫脚本来爬取所有有关孙颖莎和樊振东的相关报道和图片。 DeepSeek-R1 DeepSeek介绍自己说 &quo…

FunASR语言识别的环境安装、推理

目录 一、环境配置 1、创建虚拟环境 2、安装环境及pytorch 官网&#xff1a;pytorch下载地址 3、安装funasr之前&#xff0c;确保已经安装了下面依赖环境: python代码调用&#xff08;推荐&#xff09; 4、模型下载 5、启动funasr服务 二、 客户端连接 2.1 html连接 …

【Elasticsearch】 Ingest Pipeline `processors`属性详解

在Elasticsearch中&#xff0c;Ingest Pipeline 的 processors 属性是一个数组&#xff0c;包含一个或多个处理器&#xff08;processors&#xff09;。每个处理器定义了一个数据处理步骤&#xff0c;可以在数据索引之前对数据进行预处理或富化。以下是对 processors 属性中常见…

架构思考与实践:从通用到场景的转变

在当今复杂多变的商业环境中&#xff0c;企业架构的设计与优化成为了一个关键议题。本文通过一系列随笔&#xff0c;探讨了业务架构的价值、从通用架构到场景架构的转变、恰如其分的架构设计以及如何避免盲目低效等问题。通过对多个实际案例的分析&#xff0c;笔者揭示了架构设…

消息队列实战指南:三大MQ 与 Kafka 适用场景全解析

前言&#xff1a;在当今数字化时代&#xff0c;分布式系统和大数据处理变得愈发普遍&#xff0c;消息队列作为其中的关键组件&#xff0c;承担着系统解耦、异步通信、流量削峰等重要职责。ActiveMQ、RabbitMQ、RocketMQ 和 Kafka 作为市场上极具代表性的消息队列产品&#xff0…

win32汇编环境,怎么得到磁盘的盘符

;运行效果 ;win32汇编环境,怎么得到磁盘的盘符 ;以下代码主要为了展示一下原理&#xff0c;应用GetLogicalDrives、GetLogicalDriveStrings函数、屏蔽某些二进制位、按双字节复制内容等。以下代码最多查8个盘&#xff0c;即返回值中的1个字节的信息 ;直接抄进RadAsm可编译运行。…

微软预测 AI 2025,AI Agents 重塑工作形式

1月初&#xff0c;微软在官网发布了2025年6大AI预测&#xff0c;分别是&#xff1a;AI模型将变得更加强大和有用、AI Agents将彻底改变工作方式、AI伴侣将支持日常生活、AI资源的利用将更高效、测试与定制是开发AI的关键以及AI将加速科学研究突破。 值得一提的是&#xff0c;微…

网络编程套接字(二)

目录 TCP网络程序 服务端初始化 创建套接字 服务端绑定 服务端监听 服务端启动 服务端获取连接 服务端处理请求 客户端初始化 客户端启动 发起连接 发起请求 网络测试 多进程版TCP网络程序 捕捉SIGCHLD信号 孙子进程提供服务 多线程版TCP网络程序 线程池版TC…

网站HTTP改成HTTPS

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

渗透测试--攻击常见的Web应用

本文章咱主要讨论&#xff0c;常见Web应用的攻击手法&#xff0c;其中并不完全&#xff0c;因为Web应用是在太多无法囊括全部&#xff0c;但其中的手法思想却值得我们借鉴&#xff0c;所以俺在此做了记录&#xff0c;希望对大家有帮助&#xff01;主要有以下内容&#xff1a; 1…

外包公司名单一览表(成都)

大家好&#xff0c;我是苍何。 之前写了一篇武汉的外包公司名单&#xff0c;评论区做了个简单统计&#xff0c;很多人说&#xff0c;在外包的日子很煎熬&#xff0c;不再想去了。 有小伙伴留言说有些外包会强制离职&#xff0c;不行就转岗&#xff0c;让人极度没有安全感。 这…

2025 最新flutter面试总结

目录 1.Dart是值传递还是引用传递&#xff1f; 2.Flutter 是单引擎还是双引擎 3. StatelessWidget 和 StatefulWidget 在 Flutter 中有什么区别&#xff1f; 4.简述Dart语音特性 5. Navigator 是什么&#xff1f;在 Flutter 中 Routes 是什么&#xff1f; 6、Dart 是不是…

Spring Boot安全加固:基于Spring Security的权限管理

引言 在当今数字化时代&#xff0c;随着企业信息化程度的不断提高&#xff0c;应用程序的安全性成为了一个至关重要的问题。Spring Boot 作为 Java 生态系统中广泛使用的开发框架&#xff0c;以其简洁、高效的特点深受开发者的喜爱。然而&#xff0c;仅仅依靠 Spring Boot 的默…

论文笔记(六十二)Diffusion Reward Learning Rewards via Conditional Video Diffusion

Diffusion Reward Learning Rewards via Conditional Video Diffusion 文章概括摘要1 引言2 相关工作3 前言4 方法4.1 基于扩散模型的专家视频建模4.2 条件熵作为奖励4.3 训练细节 5 实验5.1 实验设置5.2 主要结果5.3 零样本奖励泛化5.4 真实机器人评估5.5 消融研究 6 结论 文章…

工业缺陷检测实战——基于深度学习YOLOv10神经网络PCB缺陷检测系统

基于深度学习YOLOv10神经网络PCB缺陷检测系统&#xff0c;其能识别六种PCB缺陷&#xff1a;names {0:missing_hole, 1:mouse_bite, 2:open_circuit, 3:short, 4:spur, 5:spurious_copper} CH_names [缺失孔,鼠标咬伤,开路,短路,杂散,伪铜] 具体图片见如下&#xff1a; 第一步…

React+AntDesign实现类似Chatgpt交互界面

以下是一个基于React和Ant Design搭建的简单ChatGPT风格前端交互界面代码框架示例&#xff0c;该示例实现了基本的用户输入、发送请求以及展示回复的功能。假设后端有一个模拟接口来处理请求并返回回复。 1. 项目初始化&#xff1a; 确保你已经安装了Node.js和npm。通过以下命…

FANUC机器人系统镜像备份与恢复的具体步骤(图文)

FANUC机器人系统镜像备份与恢复的具体步骤(图文) 镜像备份: 如下图所示,进入文件—工具—切换设备,找到插入的U盘UT1, 如下图所示,进入U盘目录后,创建目录,这里目录名称为11, 如下图所示࿰