STM32项目设计:基于STM32指纹密码锁

一、项目功能概述

STM32项目设计:基于STM32指纹密码锁_第1张图片

1、可通过指纹模块增删查改家庭成员的指纹信息,增删查改是否成功的相关信息显示在TFTLCD屏幕,可存储500个指纹信息。
2、在指纹匹配过程中,如果采集的指纹与指纹模块库相匹配,TFTLCD显示“刷指纹成功,确有此人ID”,此时指示灯亮。
3、可以密码解锁(密码6位),如果匹配成功,即可开锁,显示“密码正确”,指示灯亮。
4、如果密码错误或者没有识别到指纹,指示灯灭,蜂鸣器报警。
5、支持TFTLCD触摸屏校准。
6、显示温湿度。
资料下载地址:基于STM32指纹密码锁

二、材料选择

1、正点原子F103精英板
STM32项目设计:基于STM32指纹密码锁_第2张图片
2、正点原子3.5寸TFTLCD屏
STM32项目设计:基于STM32指纹密码锁_第3张图片
3、正点原子LB301电容式指纹模块

STM32项目设计:基于STM32指纹密码锁_第4张图片
4、DHT11温湿度模块
STM32项目设计:基于STM32指纹密码锁_第5张图片

三、原理图设计

LB301模块连接图
STM32项目设计:基于STM32指纹密码锁_第6张图片
DHT11模块连接图

VCC DATA GND
3.3V PA11 GND

四、成品展示

1、上电界面
需要进行触摸屏校准按K1,不需要则按K0。
STM32项目设计:基于STM32指纹密码锁_第7张图片
2、触摸屏校准
按下K1进入触摸屏校准界面,总共四个对角点,依次按下就行,按好后进入主界面。
STM32项目设计:基于STM32指纹密码锁_第8张图片
3、主界面

STM32项目设计:基于STM32指纹密码锁_第9张图片
4、指纹采集界面
指纹采集时需要将手指放在指纹模块上,指纹采集成功后,需要在键盘上输入录入指纹ID,然后按Enter进行保存。
STM32项目设计:基于STM32指纹密码锁_第10张图片
4、指纹识别成功界面
将手指放在模块上进行识别,识别成功显示“刷指纹成功,确有此人ID”,二极管亮,识别失败显示“没有搜索到指纹”,二极管灭蜂鸣器报警!

STM32项目设计:基于STM32指纹密码锁_第11张图片

STM32项目设计:基于STM32指纹密码锁_第12张图片
5、密码解锁界面
首先点击屏幕的密码解锁,输入6位数密码,正确密码为“55555”,如果密码匹配失败显示“密码错误”,匹配成功显示“密码正确”。
STM32项目设计:基于STM32指纹密码锁_第13张图片
STM32项目设计:基于STM32指纹密码锁_第14张图片
6、删指纹界面

支持单个指纹删除和指纹清空两种功能

STM32项目设计:基于STM32指纹密码锁_第15张图片
STM32项目设计:基于STM32指纹密码锁_第16张图片

源码设计

main.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "lcd.h"
#include "key.h"
#include "beep.h"
#include "touch.h"	  
#include "malloc.h" 
#include "usmart.h"  
#include "sdio_sdcard.h"    
#include "w25qxx.h"    
#include "ff.h"  
#include "exfuns.h"    
#include "fontupd.h"
#include "text.h"	
#include "usart2.h"
#include "LB301.h"
#include "timer.h"
#include "string.h"



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

SysPara LB301Para;//指纹模块LB301参数
u16 ValidN;//模块内有效指纹个数
u8** kbd_tbl;
const  u8* kbd_menu[15]={"删指纹"," 密码解锁","录指纹","1","2","3","4","5","6","7","8","9","DEL","0","Enter",};//按键表
const  u8* kbd_delFR[15]={"返回"," ","清空指纹","1","2","3","4","5","6","7","8","9","DEL","0","Enter",};//按键表

void CheckPassword(uint8_t key_val);//密码检查
void Add_FR(void);	//录指纹
void Del_FR(void);	//删除指纹
void press_FR(void);//刷指纹
void ShowErrMessage(u8 ensure);//显示确认码错误信息
void LB301_load_keyboard(u16 x,u16 y,u8 **kbtbl);//加载虚拟键盘
u8  LB301_get_keynum(u16 x,u16 y);//获取键盘数
u16 GET_NUM(void);//获取数值
uint8_t shidu = 0;
uint8_t wendu = 0;
char mStrtemp[20];

char mStrhum[20];

uint8_t mFingerErr= 0;
uint8_t mPasswordErr = 0;

int main(void)
{    
	u8 ensure;
	u8 key_num;
	char *str;	
	u16 count = 0;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init();  	//初始化延时函数
	uart_init(115200);	//初始化串口1波特率为115200,用于支持USMART
	usart2_init(usart2_baund);//初始化串口2,用于与指纹模块通讯
	BEEP_Init();  			//初始化蜂鸣器
	led_init();
	DHT11_Init();
	KEY_Init();					//按键初始化 
 	LCD_Init();					//LCD初始化 	
	W25QXX_Init();			//初始化W25Q128
	tp_dev.init();			//初始化触摸屏
	usmart_dev.init(72);		//初始化USMART
	my_mem_init(SRAMIN);		//初始化内部内存池 
	exfuns_init();			//为fatfs相关变量申请内存  
 	f_mount(fs[1],"1:",1);  //挂载FLASH.
	POINT_COLOR=RED;
	while(font_init()) 			//检查字库
	{	    
		LCD_ShowString(60,50,240,16,16,"Font Error!");
		delay_ms(200);				  
		LCD_Fill(60,50,240,66,WHITE);//清除显示
		
		delay_ms(200);	
	}
	if(!(tp_dev.touchtype&0x80))//如果是电阻屏
	{
		Show_Str_Mid(0,30,"是否进行触摸屏校准",16,240);
		POINT_COLOR=BLUE;
		Show_Str_Mid(0,60,"是:KEY1   否:KEY0",16,240);	
		while(1)
		{
			key_num=KEY_Scan(0);
			if(key_num==KEY0_PRES)
				break;
			if(key_num==KEY1_PRES)
			{
				LCD_Clear(WHITE);
				TP_Adjust();  	 //屏幕校准 
				TP_Save_Adjdata();//保存校准参数
				break;				
			}
		}
	}

	/*加载指纹识别实验界面*/
	LCD_Clear(WHITE);
	POINT_COLOR=RED;
	Show_Str_Mid(0,20,"智能锁防盗控制系统",16,240);	 
	//Show_Str_Mid(0,460,"       金陵科技学院毕业设计",16,240);	
	//Show_Str_Mid(0,20,"正点原子 @ALIENTEK",16,240);				    	 
 	POINT_COLOR=BLUE;
	Show_Str_Mid(0,40,"与LB301模块握手....",16,240);	
	while(PS_GetImage() == 0xff)//与LB301模块握手(读取图像指令有数据返回说明模块已经连接)
	{
		delay_ms(400);
		LCD_Fill(0,40,240,80,WHITE);
		Show_Str_Mid(0,40,"未检测到模块!!!",16,240);
		delay_ms(800);
		LCD_Fill(0,40,240,80,WHITE);
		Show_Str_Mid(0,40,"尝试连接模块...",16,240);
			
	}
	LCD_Fill(30,40,240,100,WHITE);
	Show_Str_Mid(0,40,"通讯成功!!!",16,240);
	str=mymalloc(SRAMIN,30);
	sprintf(str,"波特率:%d   地址:%x",usart2_baund,LB301Addr);
	//Show_Str(0,60,240,16,(u8*)str,16,0);
	ensure=PS_ValidTempleteNum(&ValidN);//读库指纹个数
	if(ensure!=0x00)
		ShowErrMessage(ensure);//显示确认码错误信息	
	ensure=PS_ReadSysPara(&LB301Para);  //读参数 
	if(ensure==0x00)
	{
		mymemset(str,0,50);
		sprintf(str,"库容量:%d     对比等级: %d",LB301Para.PS_max-ValidN,LB301Para.PS_level);
		//Show_Str(0,80,240,16,(u8*)str,16,0);
	}
	else
		ShowErrMessage(ensure);	
	myfree(SRAMIN,str);
	LB301_load_keyboard(0,170,(u8**)kbd_menu);//加载虚拟键盘
	while(1)
	{
		key_num=LB301_get_keynum(0,170);	
		if(key_num)
		{
			if(key_num==1)Del_FR();		//删指纹
			
			if(key_num==3)Add_FR();		//录指纹	
			 CheckPassword(key_num);
		}
		//查询刷指纹
		if(++count > 5) 
		{
			count = 0;
			press_FR();		
			DHT11_Read_Data(&wendu,&shidu);//获取温湿度值
			
		}
		delay_ms(1);
			sprintf(mStrtemp,"%d",wendu );
			sprintf(mStrhum, "%d",shidu);
			Show_Str(150,60,240,16,(u8*)mStrhum,16,0);
			Show_Str(150,80,240,16,(u8*)mStrtemp,16,0);
			
			Show_Str_Mid(0,60,"湿度:",16,220);
			Show_Str_Mid(0,80,"温度:",16,220);

	} 	
}


//加载按键界面(尺寸x,y为240*150
//x,y:界面起始坐标(240*320分辨率的时候,x必须为0
void LB301_load_keyboard(u16 x,u16 y,u8 **kbtbl)
{
	u16 i;
	POINT_COLOR=RED;
	kbd_tbl=kbtbl;
	LCD_Fill(x,y,x+240,y+150,WHITE);
	LCD_DrawRectangle(x,y,x+240,y+150);						   
	LCD_DrawRectangle(x+80,y,x+160,y+150);	 
	LCD_DrawRectangle(x,y+30,x+240,y+60);
	LCD_DrawRectangle(x,y+90,x+240,y+120);
	POINT_COLOR=BLUE;
	for(i=0;i<15;i++)
	{
		if(i==1)//按键表第2个‘:’不需要中间显示
			Show_Str(x+(i%3)*80+2,y+7+30*(i/3),80,30,(u8*)kbd_tbl[i],16,0);	
		else
			Show_Str_Mid(x+(i%3)*80,y+7+30*(i/3),(u8*)kbd_tbl[i],16,80);
	} 
}
//按键状态设置
//x,y:键盘坐标
//key:键值(0~14)
//sta:状态,0,松开;1,按下;
void LB301_key_staset(u16 x,u16 y,u8 keyx,u8 sta)
{		  
	u16 i=keyx/3,j=keyx%3;
	if(keyx>16)return;
	if(sta &&keyx!=1)//按键表第2个‘:’不需要清除
		LCD_Fill(x+j*80+1,y+i*30+1,x+j*80+78,y+i*30+28,GREEN);
	else if(keyx!=1)
		LCD_Fill(x+j*80+1,y+i*30+1,x+j*80+78,y+i*30+28,WHITE);
	if(keyx!=1)//不是‘:’
		Show_Str_Mid(x+j*80,y+7+30*i,(u8*)kbd_tbl[keyx],16,80);	
}
//得到触摸屏的输入
//x,y:键盘坐标
//返回值:1~15,对应按键表)
u8 LB301_get_keynum(u16 x,u16 y)
{
	u16 i,j;
	static u8 key_x=0;//0,没有任何按键按下
	u8 key=0;
	tp_dev.scan(0); 		 
	if(tp_dev.sta&TP_PRES_DOWN)//触摸屏被按下
	{	
		for(i=0;i<5;i++)
		{
			for(j=0;j<3;j++)
			{
			 	if(tp_dev.x[0]<(x+j*80+80)&&tp_dev.x[0]>(x+j*80)&&tp_dev.y[0]<(y+i*30+30)&&tp_dev.y[0]>(y+i*30))
				{	
					key=i*3+j+1;	 
					break;	 		   
				}
			}
			if(key)
			{	   
				if(key_x==key)key=0;
				else 
				{
					LB301_key_staset(x,y,key_x-1,0);
					key_x=key;
					LB301_key_staset(x,y,key_x-1,1);
				}
				break;
			}
	  }  
	}else if(key_x) 
	{
		LB301_key_staset(x,y,key_x-1,0);
		key_x=0;
	} 
	return key; 
}
//获取键盘数值
u16 GET_NUM(void)
{
	u8  key_num=0;
	u16 num=0;
	while(1)
	{
		key_num=LB301_get_keynum(0,170);	
		if(key_num)
		{
			if(key_num==1)return 0xFFFF;//‘返回’键
			if(key_num==3)return 0xFF00;//		
			if(key_num>3&&key_num<13&&num<99)//1-9’键(限制输入3位数)
				num =num*10+key_num-3;		
			if(key_num==13)num =num/10;//‘Del’键			
			if(key_num==14&&num<99)num =num*10;//0’键
			if(key_num==15)return num;  //‘Enter’键
		}
		//LCD_ShowNum(80+15,170+7,num,6,16);
	}	
}
//显示确认码错误信息
void ShowErrMessage(u8 ensure)
{
	LCD_Fill(0,120,lcddev.width,160,WHITE);
	Show_Str_Mid(0,120,(u8*)EnsureMessage(ensure),16,240);
}
//录指纹
void Add_FR(void)
{
	u8 i=0,ensure ,processnum=1,pressCout=1, str_buffer[40];
	u16 ID;
	while(1)
	{
		switch (processnum)
		{
			case 1: //连续按压4次指纹分别存到4个charBuffer里 
				i++;
				LCD_Fill(0,100,lcddev.width,160,WHITE);
				sprintf((char*)str_buffer,"请按指纹(%d)",pressCout);
				Show_Str_Mid(0,100,str_buffer,16,240);
				ensure=PS_GetImage();
				if(ensure==0x00) 
				{
					i=0;
					BEEP=1;
					delay_ms(100);//这里需要延时一下,模块内部处理图像需要时间
					ensure=PS_GenChar(pressCout);//生成特征
					BEEP=0;
					if(ensure==0x00)
					{
						LCD_Fill(0,120,lcddev.width,160,WHITE);
						Show_Str_Mid(0,120,"指纹正常",16,240);
						pressCout++;
						if(pressCout >=5)
						{
							pressCout = 0;
							processnum=2;//跳到第二步
						}							
					}else ShowErrMessage(ensure);				
				}else ShowErrMessage(ensure);						
				break;
			
			case 2:
				LCD_Fill(0,100,lcddev.width,160,WHITE);
				Show_Str_Mid(0,100,"生成指纹模板",16,240);
				ensure=PS_RegMB();
				if(ensure==0x00) 
				{
					LCD_Fill(0,120,lcddev.width,160,WHITE);
					Show_Str_Mid(0,120,"生成指纹模板成功",16,240);
					processnum=3;//跳到第三步
				}else {processnum=0;ShowErrMessage(ensure);}
				delay_ms(1200);
				break;
				
			case 3:	
				LCD_Fill(0,100,lcddev.width,160,WHITE);
				Show_Str_Mid(0,100,"请输入储存ID,按Enter保存",16,240);
				Show_Str_Mid(0,120,"0=< ID <=499",16,240);
				do
					ID=GET_NUM();
				while(!(ID<LB301Para.PS_max));//输入ID必须小于模块容量最大的数值
				ensure=PS_StoreMB(CharBuffer1,ID);//储存模板
				if(ensure==0x00) 
				{			
					LCD_Fill(0,100,lcddev.width,160,WHITE);					
					Show_Str_Mid(0,120,"录入指纹成功",16,240);
					PS_ValidTempleteNum(&ValidN);//读库指纹个数
					//LCD_ShowNum(56,80,LB301Para.PS_max-ValidN,3,16);//显示剩余指纹容量
					delay_ms(1500);
					LCD_Fill(0,100,240,160,WHITE);
					return ;
				}else {processnum=0;ShowErrMessage(ensure);}					
				break;				
		}
		delay_ms(200);
		if(i>=20)//超过20次没有按手指则退出
		{
			LCD_Fill(0,100,lcddev.width,160,WHITE);
			break;	
		}				
	}
}





#define USE_AUTO_IDETIFY  1 // 1使用自动验证方式  0使用分布式验证方式

//刷指纹
void press_FR(void)
{
	SearchResult seach;
	u8 ensure;
	char *str;
#if (USE_AUTO_IDETIFY == 1) //自动验证指纹	
	ensure=PS_AutoIdentify(&seach);
	if(ensure==0x00)//自动验证成功
	{
		BEEP=1;
		LCD_Fill(0,100,lcddev.width,160,WHITE);
		Show_Str_Mid(0,100,"刷指纹成功",16,240);
		str=mymalloc(SRAMIN,2000);
		sprintf(str,"确有此人,ID:%d  匹配得分:%d",seach.pageID,seach.mathscore);
		Show_Str_Mid(0,140,(u8*)str,16,240);
		myfree(SRAMIN,str);
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);//输出0,打开LED灯
		delay_ms(500);
		BEEP=0;//关闭蜂鸣器
		GPIO_SetBits(GPIOB,GPIO_Pin_5);//输出0,关闭LED灯
		LCD_Fill(0,100,lcddev.width,160,WHITE);
	}
	else if(ensure != 0xff)
	{
		BEEP=1;
		ShowErrMessage(ensure);
		delay_ms(500);
		BEEP=0;//关闭蜂鸣器
		LCD_Fill(0,100,lcddev.width,160,WHITE);
		GPIO_SetBits(GPIOB,GPIO_Pin_5);//输出0,关闭LED灯
	}
#else  //分布式验证指纹
	ensure=PS_GetImage();
	if(ensure==0x00)//获取图像成功 
	{	
		BEEP=1;//打开蜂鸣器	
		delay_ms(100);//这里需要延时一下,模块内部处理图像需要时间
		ensure=PS_GenChar(CharBuffer1);
		if(ensure==0x00) //生成特征成功
		{		
			BEEP=0;//关闭蜂鸣器	
			ensure=PS_Search(CharBuffer1,0,299,&seach);//LB301Para.PS_max
			if(ensure==0x00)//搜索成功
			{				
				LCD_Fill(0,100,lcddev.width,160,WHITE);
				Show_Str_Mid(0,100,"刷指纹成功",16,240);				
				str=mymalloc(SRAMIN,2000);
				sprintf(str,"确有此人,ID:%d  匹配得分:%d",seach.pageID,seach.mathscore);
				Show_Str_Mid(0,140,(u8*)str,16,240);
				myfree(SRAMIN,str);
			}
			else 
				ShowErrMessage(ensure);					
		}
		else
			ShowErrMessage(ensure);
		delay_ms(500);
		BEEP=0;//关闭蜂鸣器
		LCD_Fill(0,100,lcddev.width,160,WHITE);
	}
#endif
}

//删除指纹
void Del_FR(void)
{
	u8  ensure;
	u16 num;
	LCD_Fill(0,100,lcddev.width,160,WHITE);
	Show_Str_Mid(0,100,"删除指纹",16,240);
	Show_Str_Mid(0,120,"请输入指纹ID按Enter发送",16,240);
	Show_Str_Mid(0,140,"0=< ID <=499",16,240);
	delay_ms(50);
	LB301_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)
	{
		LCD_Fill(0,120,lcddev.width,160,WHITE);
		Show_Str_Mid(0,140,"删除指纹成功",16,240);		
	}
  else
		ShowErrMessage(ensure);	
	delay_ms(1200);
	PS_ValidTempleteNum(&ValidN);//读库指纹个数
//	LCD_ShowNum(56,80,LB301Para.PS_max-ValidN,3,16);
MENU:	
	LCD_Fill(0,100,lcddev.width,160,WHITE);
	delay_ms(50);
	LB301_load_keyboard(0,170,(u8**)kbd_menu);
}



你可能感兴趣的:(单片机,c语言,stm32,嵌入式硬件)