当前位置:   article > 正文

基于STM32F4的智能门锁系统_基于stm32智能门锁

基于stm32智能门锁

前言

本文主要对项目的搭建过程及实现效果进行介绍,应用代码较少,后续有空我会单独分类贴出

一、项目背景

在消费升级渗透在各个领域的今天,国民消费发生着巨大的变化,与每个人息息相关的家居行业也是如此。现今,越来越多的智能家居产品出现在普通老百姓的生活中,智能照明、智能窗帘、智能扫地机器人等各种智能产品都给人们的生活带来了极大的便利。智能门锁作为智能家居中重要的一环,也成为消费者家居智能化的重要选择。智能相比市面的机械门锁更加安全、更智能、更人性化而得到市场的认可,在智能门锁行业里,不少世界500强企业也在智能门锁上进行产品布局,像中国小米公司就生产智能门锁,致力打造智慧家庭,市场智能门锁能够支持五种解锁方式,支持指纹、手机、门禁卡、按键密码、钥匙解锁功能。可以说是智能家庭必不可少的成员。

在这里插入图片描述
注:图片来源:http://www.szjiuding.com/products/297.html

二、项目所预想功能

1、可通过(通过手机)指纹模块增删家庭成员的指纹信息,增删是否成功的相关信息显示在OLED屏幕上
2、在指纹匹配过程中,如果采集的指纹与指纹模块库相匹配,OLED显示匹配成功,并转动步进电机一圈(或者打开继电器)
3、可通过按键设定智能门锁密码,密码可设置为两个(密码六位),如果匹配两个中的一个成功,即可开锁,也可通过按键修改密码,所有的操作过程显示于OLED中
4、实现RFID与手机解锁(蓝牙解锁)
5、虚位密码解锁

三、外置硬件准备

1、0.96寸OLED模块IIC接口(四针)
2、单片机键盘 按键 矩阵 4*4 4X4 A键盘 16键
3、3路继电器模块
4、MFRC-522 RC522 RFID射频 IC卡感应模块
5、HC-06主从机蓝牙模块无线串口通讯
6、AS608指纹模块

四、项目开发

简介及涉及协议

可以实现RFID刷卡、蓝牙连接解锁、指纹解锁同步进行验证,按下中断后可进行键盘输入密码解锁,进入功能选择界面后有两种模式进行功能选择,一是通过手机蓝牙进行操控,二是使用键盘进行操控。总共有三种功能可供选择,1、录入新指纹、2、删除指纹、3、修改密码;涉及协议:SPI、IIC、FALSH。

蓝牙模块

1、蓝牙接线图

2、使用说明:

(1)打开串口助手软件及蓝牙HC-06AT命令详解.pdf资料,配置串口软件波特率:9600(有可能不一定是9600,可能是115200或者是38400),需要修改蓝牙的名字,修改指令如下:
AT+NAMECHEN(AT+NAME:AT指令 CHEN:蓝牙名字)
`(2)安装蓝牙调试助手,设定好指令,使用手机输入蓝牙密码连接蓝牙,
打开手机上蓝牙串口助手软件,并连接蓝牙。即可手机与蓝牙通信。
注意:使用主从机6针蓝牙模块时,插入电脑USB接口前,需要长摁模块上的按键;在开发板上连接时,
系统复位后若蓝牙没反应,应重新拔插蓝牙模块引脚。

3、蓝牙代码

USART3.C
#include "usart3.h"
#include "string.h"
/**************************************
引脚说明

PB10  ---- USART3_TX(发送端)
PB11 ---- USART3_RX(接收端)
MyBaudRate 波特率

**************************************/
u8 USART3_RX_BUF[USART3_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
u16 USART3_RX_STA=0;       //接收状态标记	
u8 rx_flag=0;
void Usart3_Init(int MyBaudRate)
{
	//GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); //使能GPIOB时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//使能USART3时钟
 
	//串口3对应引脚复用映射
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_USART3); //GPIOB10复用为USART3
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_USART3); //GPIOB11复用为USART3
	
	//USART3端口配置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10| GPIO_Pin_11; //GPIOB10与GPIOB11
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化PB10,PB11

   //USART3 初始化设置
	USART_InitStructure.USART_BaudRate = MyBaudRate;//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  USART_Init(USART3, &USART_InitStructure); //初始化串口1
	
  USART_Cmd(USART3, ENABLE);  //使能串口1 
	
	//USART_ClearFlag(USART1, USART_FLAG_TC);
	

	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启相关中断

	//Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;//串口3中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;		//子优先级2
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、

}

void USART3_IRQHandler(void)                	//串口3中断服务程序
{
	u8 Res;
	//GPIO_ResetBits(GPIOF, GPIO_Pin_9);
	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是::结尾)
	{
		Res =USART_ReceiveData(USART3);//(USART1->DR);	//读取接收到的数据
		
		if((USART3_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART3_RX_STA&0x4000)//接收到了0x0d
			{
				if(Res!=':')USART3_RX_STA=0;//接收错误,重新开始
				else 
				{
					USART3_RX_STA|=0x8000;	//接收完成了
					rx_flag = 1;            //蓝牙接收标志
				}					
			}
			else //还没收到0X0D
			{	
				if(Res==':')USART3_RX_STA|=0x4000;
				else
				{
					USART3_RX_BUF[USART3_RX_STA&0X3FFF]=Res ;
					USART3_RX_STA++;
					if(USART3_RX_STA>(USART3_REC_LEN-1))USART3_RX_STA=0;//接收数据错误,重新开始接收	  
				}		 
			}
		}   		 
  } 

} 
//检查字符串是否与接收数据匹配
u8 Usart3_cherk(char *buf)
{
	printf("%s",USART3_RX_BUF);
	if(memcmp(USART3_RX_BUF,buf,6)==0)	
		{
		USART3_RX_STA=0;
		memset(USART3_RX_BUF,0,strlen((const char *)USART3_RX_BUF));
		return 0;
	  }
	else return 1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
蓝牙连接函数
//手机蓝牙解锁密码1
						if(rx_flag==1) //蓝牙信号标志
						{
						Error=Usart3_cherk((char*)Pwd);         
						if(Error==0)
							{	
							printf("蓝牙解锁中\r\n");
							Con();
							BEEP_ON;
							delay_ms(200);
							BEEP_OFF;
							printf("蓝牙解锁成功\r\n");
							OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP2);
							rx_flag=0;
							goto MENU;					
							}
							else 
							OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);//锁
							Error=Usart3_cherk((char*)Pwd2);
							if(Error==0)
							{
							printf("蓝牙解锁中\r\n");
							Con();
							BEEP_ON;
							delay_ms(200);
							BEEP_OFF;
							printf("蓝牙解锁成功\r\n");
							OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP2); //刷解锁成功图片
							rx_flag=0;
							goto MENU;				
						}
						else 
						OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);//锁
						}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

RFID卡

1、RFID卡连接图

在这里插入图片描述

2、RFID模块简介

MF522-AN模块采用Philips MFRC522原装芯片设计读卡电路,使用方便,成本低廉,适用于设备开发、读卡器开发等高级应用的用户、需要进行射频卡终端设计/生产的用户。本模块可直接装入各种读卡器模具。模块采用电压为3.3V,通过SPI接口简单的几条线就可以直接与用户任何CPU主板相连接通信,可以保证模块稳定可靠的工作、读卡距离远;

3、代码部分

由于购买时就配置有示例代码,可直接使用,我这里只贴出主函数中应用部分

//MFRC522测试函数
int MFRC522Test(void)
{
	u8 i,j,status=1,card_size;
	u8 count;
	AntennaOn();
  status=MFRC522_Request(0x52, card_pydebuf);			//寻卡
	if(status==0)		//如果读到卡
	{
		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("卡的类型:%d %d \r\n",card_pydebuf[0],card_pydebuf[1]);
		

		//卡序列号显,最后一字节为卡的校验码
		printf("卡的序列号:");
		count=0;
		for(i=0;i<5;i++)
		{
			printf("%d ",card_numberbuf[i]);
			if(card_numberbuf[i]==cardid[i])
			{
			count++;
			}
			printf("%d",count);
		}
		printf("\r\n");
		if(count==5)
		{
			printf("rfid 匹配成功,解锁 \r\n");

			return 0;
		}
		
		printf("\n");
		//卡容量显示,单位为Kbits
		
		printf("\r\n卡的容量:%dKbits\r\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();
	delay_s(1);
	return 1;
	
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

指纹模块

1、接线原理图

在这里插入图片描述

模块代码

AS608指纹模块代码的移植和初始化实现可以根据厂家提供的资料完成,移植过程如果有空我会单独出一期进行讲解,下面展示的是我的指纹应用代码部分

录指纹
//录指纹
void Add_FR(void)
{
	u8 i,ensure ,processnum=0;
	unsigned char word;
	int key_num;
	u16 ID;
	u16 UID[3]={0};
  OLED_CLS();//清屏
	while(1)
	{
		key_num=Key_Value();	
		if(key_num==68)
			{
		OLED_CLS();//清屏
			return ;
		}
		switch (processnum)
		{
			case 0:
				OLED_CLS();//清屏
				i++;
				for(word=28;word<32;word++)
			{
				OLED_ShowCN(0+(word-28)*16,4,word);//请按指纹
			}
			  printf("录入指纹");
				ensure=PS_GetImage();
				if(ensure==0x00) 
				{
					ensure=PS_GenChar(CharBuffer1);//生成特征
					if(ensure==0x00)
					{
						OLED_CLS();//清屏
						printf("指纹正常");
						for(word=32;word<36;word++)
						{
							OLED_ShowCN(0+(word-32)*16,4,word);//指纹正常
						}
						i=0;
						processnum=1;//跳到第二步						
					}else ShowErrMessage(ensure);					
				}else ShowErrMessage(ensure);
				OLED_CLS();//清屏
				break;
			
			case 1:
				i++;
        printf("请再按一次指纹");
				for(word=36;word<43;word++)
						{
							OLED_ShowCN(0+(word-36)*16,4,word);//请再按一次指纹
						}			
				ensure=PS_GetImage();
				if(ensure==0x00) 
				{
					ensure=PS_GenChar(CharBuffer2);//生成特征
					if(ensure==0x00)
					{
						OLED_CLS();//清屏
						printf("指纹正常");
						for(word=32;word<36;word++)
						{
							OLED_ShowCN(0+(word-32)*16,4,word);//指纹正常
						}
						i=0;
						processnum=2;//跳到第三步
					}else ShowErrMessage(ensure);	
				}else ShowErrMessage(ensure);		
				OLED_CLS();//清屏
				break;

			case 2:		
			  printf("对比两次指纹");
				for(word=43;word<49;word++)
						{
							OLED_ShowCN(0+(word-42)*16,4,word);//对比两次指纹
						}			
				ensure=PS_GetImage();
				ensure=PS_Match();
				if(ensure==0x00) 
				{
					OLED_CLS();//清屏
					printf("两次指纹相同");
					for(word=49;word<55;word++)
						{
							OLED_ShowCN(0+(word-49)*16,4,word);//两次指纹相同
						}
					processnum=3;//跳到第四步
				}
				else 
				{
					OLED_CLS();//清屏
          printf("重新录入");
					for(word=55;word<59;word++)
						{
							OLED_ShowCN(0+(word-55)*16,4,word);//对比设备,重新录入
						} 					
					ShowErrMessage(ensure);
					i=0;
					OLED_CLS();//清屏
					processnum=0;//跳回第一步		
				}
				delay_ms(1200);
				OLED_CLS();//清屏
				break;

			case 3:
      printf("生成指纹模板");
			OLED_CLS();//清屏
			for(word=59;word<65;word++)
						{
							OLED_ShowCN(0+(word-59)*16,4,word);//生成指纹模板
						}			
				ensure=PS_RegModel();
				if(ensure==0x00) 
				{
					OLED_CLS();//清屏
					printf("生成指纹模板成功");
					for(word=65;word<73;word++)
						{
							OLED_ShowCN(0+(word-65)*16,4,word);//生成指纹模板成功
						}
					processnum=4;//跳到第五步
				}else {processnum=0;ShowErrMessage(ensure);}
				delay_ms(1200);
				break;
				
			case 4:	
			OLED_CLS();//清屏
			printf("请输入储存ID");
			for(word=73;word<80;word++)
						{
							OLED_ShowCN(0+(word-73)*16,0,word);//请输入储存ID
						};
					ID=GET_NUM();
						printf("ID:%d",ID);
						sprintf(UID,"%d",ID);
				OLED_ShowStr(65,4,UID,2);
				ensure=PS_StoreChar(CharBuffer2,ID);//储存模板
				if(ensure==0x00) 
				{			
          OLED_CLS();//清屏
					printf("录指纹成功");
					for(word=80;word<85;word++)
						{
							OLED_ShowCN(0+(word-80)*16,4,word);//录指纹成功
						};
						OLED_ShowStr(20,4,word,2);
					PS_ValidTempleteNum(&ValidN);//读库指纹个数
					printf("指纹个数为%d",ValidN);
					delay_ms(1500);
					//OLED_Clear();	
					return ;
				}else {processnum=0;ShowErrMessage(ensure);}
				OLED_CLS();//清屏				
				break;				
		}
		delay_ms(400);
		if(i==10)//超过10次没有按手指则退出
		{
			OLED_CLS();//清屏
			break;
		}				
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
刷指纹
//刷指纹
int press_FR(void)
{
	SearchResult seach;
	u8 ensure;
	char *str;
	ensure=PS_GetImage();
	OLED_CLS();//清屏
	//Show_Str(0,0,128,16,"正在检测指纹",16,0);
	if(ensure==0x00)//获取图像成功 
	{	
		ensure=PS_GenChar(CharBuffer1);
		printf("%d\r\n",ensure);
		if(ensure==0x00) //生成特征成功
		{		
			
			ensure=PS_HighSpeedSearch(CharBuffer1,0,AS608Para.PS_max,&seach);
			printf("%d\r\n",ensure);
			if(ensure==0x00)//搜索成功
			{				
				//OLED_Clear();
				printf("解锁中\r\n");	
				BEEP_ON;
				delay_ms(200);
				BEEP_OFF;
				Con();				
				printf("已解锁\r\n");
				sprintf(str,"ID:%d      匹配分:%d",seach.pageID,seach.mathscore);
				printf("%d",seach.pageID);
				OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP2);//开锁
				delay_ms(500);
				OLED_CLS();//清屏
				return 0;
			}
			else {
				ShowErrMessage(ensure);	
				delay_ms(1000);
				OLED_CLS();//清屏
				return -1;
			}				
	  }
		else
			ShowErrMessage(ensure);	
	 delay_ms(2000);
	OLED_CLS();//清屏
		
	}
	return -1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
删指纹
//删除指纹
void Del_FR(void)
{
	u8  ensure;
	u16 num;
	int i;
	OLED_CLS();//清屏
	for(i=85;i<91;i++)
			{
				OLED_ShowCN(0+(i-85)*16,0,i);//清空指纹库
			}
	for(i=91;i<97;i++)
			{
				OLED_ShowCN(0+(i-91)*16,4,i);//删除单个指纹
			}
			OLED_ShowStr(113,0,"2",2); 
			OLED_ShowStr(113,4,"3",2);
	delay_ms(50);
	while(1)
	{
		num=Key_Value();//获取返回的数值
				if(num)
				{
					switch(num)
						{
							case '1':goto MENU;           				//返回主页面
							case '2':ensure=PS_Empty();  break;  //清空指纹库		
							case '3':ensure=Del_Name();  break;		//删除单个指纹 
						}
						break;
				}
	}
	printf("%d\r\n",ensure);
	if(ensure==0)
	{
		OLED_CLS();//清屏	
			for(i=105;i<111;i++)
			{
				OLED_ShowCN(22+(i-105)*16,4,i);//删除成功
			}	
	}
  else
		ShowErrMessage(ensure);	
 
	PS_ValidTempleteNum(&ValidN);//读库指纹个数
	delay_ms(1200);
	
  MENU:	
	OLED_CLS();//清屏
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

OLED显示屏

1、OLED屏接线图

在这里插入图片描述

2、使用方法

移植厂家提供的核心代码文件,再利用取模软件进行取模,拷贝到codetab.h文件中的储存函数中,
进行函数调用即可实现字体在屏幕上显示。
在这里插入图片描述

3、实现代码

int main(void)
{
	unsigned char i;
	extern const unsigned char BMP1[];
	
	
	//NVIC分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	Delay_Init();
	Led_Init();

	Usart1_Init(115200);

	I2C_Configuration();
	OLED_Init();

	//显示字符
//	OLED_Fill(0x00);//全屏灭
//	OLED_ShowStr(0,4,"Hello Tech",1);				//测试8*16字符
//	while(1);
	
	//显示汉字
//	OLED_Fill(0x00);//全屏灭
//	for(i=5;i<9;i++)
//	{
//		OLED_ShowCN(22+(i-5)*16,0,i);//测试显示中文
//	}
//	while(1);
	
	//显示图片
	//OLED_Fill(0x00);//全屏灭
	//OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);//测试BMP位图显示
	//while(1);
	OLED_CLS();//清屏
	
	while(1)
	{
	
		//OLED_Fill(0xFF);//全屏点亮
		//delay_s(2);
		//OLED_Fill(0x00);//全屏灭
		//delay_s(2);
		for(i=0;i<5;i++)
		{
			OLED_ShowCN(22+i*16,0,i);//测试显示中文
		}
		//delay_s(2);
		OLED_ShowStr(0,3,"HelTec Automation",1);//测试6*8字符
		OLED_ShowStr(0,4,"Hello Tech",2);				//测试8*16字符
		//delay_s(2);
		//OLED_CLS();//清屏
		//OLED_OFF();//测试OLED休眠
		//delay_s(2);
		//OLED_ON();//测试OLED休眠后唤醒
		//OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);//测试BMP位图显示
		//delay_s(2);
	
	}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

4X4矩阵键盘实现

1、矩阵键盘原理图

在这里插入图片描述在这里插入图片描述

2、键盘实现原理

最常见的矩阵键盘是4*4键盘,其实现方法是将16个按键按照4x4矩阵方式连接,如上图所示。从连接方式来看,有4根行线和4根列线。每个行线和列线的交汇处就是一个按键位。这样总共有8根线就可以实现16个按键的检测,比一个按键连接一个I/O口节省了一半的I/O端口。

我本次设计的是通过寄存器的方式实现4*4按键的输入,采用逐列扫描的方式,并编写了每次按下一个按键都要进行消抖处理,从按下到松开按键只发送一位i数据;

3、实现代码

#include <button4_4.h>
#include <delay.h>
#include <stdio.h>

u8 only;                   //一次按键只打印一次标志位

/*********************************************************************
*按键用的PC6-PC9,PC11,PB6,PE5,PE6
*PC6-PC9为推挽输出
*PC11,PB6,PE5,PE6为下拉输入
*********************************************************************/

void Button_Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
     
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);                       //使能C端口时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;     
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_OUT;                               //输出模式
    GPIO_InitStructure.GPIO_OType    = GPIO_OType_PP;                               //推挽式输出
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_UP;                                   //上拉
    GPIO_InitStructure.GPIO_Speed    = GPIO_Speed_50MHz;                               //50MHZ
     GPIO_Init(GPIOC, &GPIO_InitStructure);                                       //初始化
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);          //使能C端口时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;      
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_IN;                      //输入模式
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_DOWN;                  //下拉
     GPIO_Init(GPIOC, &GPIO_InitStructure);                          //初始化
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);          //使能B端口时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;      
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_IN;                      //输入模式
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_DOWN;                  //下拉
     GPIO_Init(GPIOB, &GPIO_InitStructure);                          //初始化
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);          //使能E端口时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6;      
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_IN;                      //输入模式
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_DOWN;                  //下拉
     GPIO_Init(GPIOE, &GPIO_InitStructure);                          //初始化    

}


/*********************************************************************
*函数说明: 按键扫描
*返回值  :  按键值
*参数    :  void
**********************************************************************/
int Key_Scan(void)
{
    u16 keyValue;                                    //按键值

      GPIO_Write(GPIOC,(GPIOC->ODR & 0xfc3f )| 0x0040);//检索第一列
      if((GPIOC->IDR & 0x0800) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOC->IDR & 0x0800) != 0x0000)
          {
              only = 1;
              while((GPIOC->IDR & 0x0800) != 0x0000);
              keyValue='1';
          }
      }
      if((GPIOB->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOB->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOB->IDR & 0x0040) != 0x0000);
              keyValue='4';
          }
      }
      if((GPIOE->IDR & 0x0020) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0020) != 0x0000)
          {
              only = 1;
              while((GPIOE->IDR & 0x0020) != 0x0000);
              keyValue='7';
          }
      }
      if((GPIOE->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOE->IDR & 0x0040) != 0x0000);
              keyValue='*';
          }
      }
      
      GPIO_Write(GPIOC,(GPIOC->ODR & 0xfc3f )| 0x0080);检索第二列
      if((GPIOC->IDR & 0x0800) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOC->IDR & 0x0800) != 0x0000)
          {
              only = 1;
              while((GPIOC->IDR & 0x0800) != 0x0000);
              keyValue='2';
          }
      }
      if((GPIOB->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOB->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOB->IDR & 0x0040) != 0x0000);
              keyValue='5';
          }
      }
      if((GPIOE->IDR & 0x0020) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0020) != 0x0000)
          {
              only = 1;
              while((GPIOE->IDR & 0x0020) != 0x0000);
              keyValue='8';
          }
      }
      if((GPIOE->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOE->IDR & 0x0040) != 0x0000);
              keyValue='0';
          }
      }
      
      GPIO_Write(GPIOC,(GPIOC->ODR & 0xfc3f )| 0x0100);//检索第三列
      if((GPIOC->IDR & 0x0800) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOC->IDR & 0x0800) != 0x0000)
          {
              only = 1;
              while((GPIOC->IDR & 0x0800) != 0x0000);
              keyValue='3';
          }
      }
      if((GPIOB->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOB->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOB->IDR & 0x0040) != 0x0000);
              keyValue='6';
          }
      }
      if((GPIOE->IDR & 0x0020) != 0x0000)
      {
          delay_ms(5);//延时消抖
           if((GPIOE->IDR & 0x0020) != 0x0000)
           {
              only = 1;
              while((GPIOE->IDR & 0x0020) != 0x0000);
              keyValue='9';
           }
      }
      if((GPIOE->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOE->IDR & 0x0040) != 0x0000);
              keyValue='#';
          }
      }
      
      GPIO_Write(GPIOC,(GPIOC->ODR & 0xfc3f )| 0x0200);//检索第四列
      if((GPIOC->IDR & 0x0800) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOC->IDR & 0x0800) != 0x0000)
          {
              only = 1;
              while((GPIOC->IDR & 0x0800) != 0x0000);
              keyValue='A';
          }
      }
      if((GPIOB->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOB->IDR & 0x0040) != 0x0000)
          {
              only = 1;
              while((GPIOB->IDR & 0x0040) != 0x0000);
              keyValue='B';
          }
      }
      if((GPIOE->IDR & 0x0020) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0020) != 0x0000)
          {
              only = 1;
              while((GPIOE->IDR & 0x0020) != 0x0000);
              keyValue='C';
          }
      }
      if((GPIOE->IDR & 0x0040) != 0x0000)
      {
          delay_ms(5);//延时消抖
          if((GPIOE->IDR & 0x0040) != 0x0000)
          {              
              only = 1;
              while((GPIOE->IDR & 0x0040) != 0x0000);
              keyValue='D';
          }
      }
      
    return keyValue;
}

int Key_Value(void)
{
	u16 keyValue;
	keyValue = Key_Scan();
  delay_ms(50);
  if(only == 1)              //按一次打印一次
  {
    printf("%c",keyValue);        //这里写显示的方式,把接收显示出来
		only = 0;
		return keyValue;
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237

FLASH储存

1、FLASH原理

Flash内部存储器,内存器件的一种,是一种非易失性( Non-Volatile )内存。
flash闪存是非易失存储器,可以对称为块的存储器单元块进行擦写和再编程。任何flash器件的写入操作只能在空或已擦除的单元内进行,所以大多数情况下,在进行写入操作之前必须先执行擦除。

在这里插入图片描述

2、实现过程

使用Flash储存的目的是为了实现对数据进行保护,当我们对密码、指纹、ID卡号进行修改后,系统突然掉电或者关闭,进行Flash储存后,重新启动程序时进行读取操作,密码就为重新设置的密码。达到修改密码保存的目的。

3、代码部分

使用开发板配套的Flash例程就可以实现,调用Flash_write()函数储存即可
每次开机初始化使用Flash_Read()读取密码。

#include "stmflash.h"



static uint32_t GetSector(uint32_t Address)
{
	uint32_t sector = 0;

	if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
	{
	  sector = FLASH_Sector_0;  
	}
	else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
	{
	  sector = FLASH_Sector_1;  
	}
	else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
	{
	  sector = FLASH_Sector_2;  
	}
	else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
	{
	  sector = FLASH_Sector_3;  
	}
	else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
	{
	  sector = FLASH_Sector_4;  
	}
	else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
	{
	  sector = FLASH_Sector_5;  
	}
	else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
	{
	  sector = FLASH_Sector_6;  
	}
	else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
	{
	  sector = FLASH_Sector_7;  
	}

	return sector;
}






//函数声明
void Flash_write(u32 addr, u8 *write_buff, u32 len)
{

	u32 FLASH_USER_START_ADDR, FLASH_USER_END_ADDR;
	u32 uwStartSector, uwEndSector, uwSectorCounter, uwAddress;
	
	/* Unlock the Flash *********************************************************/
	/* Enable the flash control register access */
	//FLASH解锁
	FLASH_Unlock();
	  
	/* Erase the user Flash area ************************************************/
	/* area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR */

	/* Clear pending flags (if any) */  
	//清空标志位
	FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | 
					FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR); 

	//计算开始地址
	FLASH_USER_START_ADDR = addr;
	//计算结束地址
	FLASH_USER_END_ADDR = FLASH_USER_START_ADDR+len;
	
	/* Get the number of the start and end sectors */
	//获取开始与结束的扇区
	uwStartSector = GetSector(FLASH_USER_START_ADDR);
	uwEndSector = GetSector(FLASH_USER_END_ADDR);

	/* Strat the erase operation */
	//开始擦写扇区赋值给uwSectorCounter
	uwSectorCounter = uwStartSector;
	
	//循环擦除扇区
	while (uwSectorCounter <= uwEndSector) 
	{
	  /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
		 be done by word */ 
	  if (FLASH_EraseSector(uwSectorCounter, VoltageRange_3) != FLASH_COMPLETE)
	  { 
		/* Error occurred while sector erase. 
		   User can add here some code to deal with this error  */
			printf("erase failure\r\n");
			return ;
	  }
	  /* jump to the next sector */

	 uwSectorCounter += 8;
	  
	}

	/* Program the user Flash area word by word ********************************/
	/* area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR */
	//开始地址赋值给uwAddress
	uwAddress = FLASH_USER_START_ADDR;
	
	//循环写数据
	while (uwAddress < FLASH_USER_END_ADDR)
	{
		//按字节写入FLASH当中
	  if (FLASH_ProgramByte(uwAddress, *write_buff) == FLASH_COMPLETE)
	  {
		  //FLASH地址加1
		uwAddress = uwAddress + 1;
		  //数据地址空间加1
		  write_buff++;
	  }
	  else
	  { 
			printf("erase failure\r\n");
			return ;
	  }
	}

	/* Lock the Flash to disable the flash control register access (recommended
	   to protect the FLASH memory against possible unwanted operation) */
	
	//FLASH加锁
	FLASH_Lock(); 

}

void Flash_Read(u32 addr, u8 *read_buff, u32 len)
{
	
	u32 FLASH_USER_START_ADDR, FLASH_USER_END_ADDR, uwAddress;
	
	
	//计算开始地址
	FLASH_USER_START_ADDR = addr;
	//计算结束地址
	FLASH_USER_END_ADDR = FLASH_USER_START_ADDR+len;	
	
	 uwAddress = FLASH_USER_START_ADDR;
	 
	 
	//循环读数据
	 while (uwAddress < FLASH_USER_END_ADDR)
	 {
	   *read_buff = *(__IO uint8_t*)uwAddress;


		  //FLASH地址加1
		uwAddress = uwAddress + 1;
		  //数据地址空间加1
		  read_buff++;
	 }  


}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161

虚位密码实现

1、虚位密码的原理

“虚位密码技术”,就是在正确的密码前面和后面加上任意位数的数字,只要中间【部分品牌是头或者尾】有连续正确的密码就可开门,这样就能有效防止密码泄漏。

只需要不改变真实密码顺序,前后或中间插入多个数字都可以实现开锁。比如正确密码如果是123456,输入时可以加入(8)(6)(7)123456(0)(2)(3),注意括号内为加入的其他数字。

2、虚位密码代码

//密码锁
int password(void)
{
	int i=0,satus=0,work;
	u8 key_num;
	u16 num=0,num2=0,time3=0;
	u8 pwd[11]={0};
	u8 hidepwd[11]="          ";
  OLED_CLS();//清屏
	for(work=123;work<128;work++)
			{
				OLED_ShowCN(22+(work-123)*16,0,work);//请输入密码
			}
	while(1)
	{
		key_num=Key_Value();	
		if(key_num)
		{	
			time3=0;
			if(key_num>=49 && key_num<58 && i>=0 && i<10)//‘1-9’键
				{  
				pwd[i]=key_num;
				printf("%c",pwd[i]);
				i++;
				printf("%d",i);
			}	
			if(key_num==48 && i>=0 && i<10)//‘0’键
				{ 
        int m=0;					
			  printf("%c",pwd[i]);
				i++;
				printf("%d",i);
			}
			if(key_num==68)
			break;  //‘Enter’键
			if(i==1)
			{
				OLED_ShowStr(32,4,"*",2);
			}
			if(i==2)
			{
				OLED_ShowStr(32,4,"**",2);
			}
			if(i==3)
			{
				OLED_ShowStr(32,4,"***",2);
			}
			if(i==4)
			{
				OLED_ShowStr(32,4,"****",2);
			}
			if(i==5)
			{
				OLED_ShowStr(32,4,"*****",2);
			}
			if(i==6)
			{
				OLED_ShowStr(32,4,"******",2);
			}
		}
		
	}	
	printf("%s \r\n",pwd);
	printf("现在第一密码是%s",Pwd);
	for(i=0; i<12; i++) //验证密码  //虚位密码最多输入12位
	{  
		if(pwd[i]==Pwd[num])
		{
			printf("%c",pwd[i]);
			num++;
		}
			else num=0;
		if(num==6)
			break;
	}
	printf("现在第二密码是%s",Pwd2);
	for(i=0; i<12; i++)//验证密码 
	{   
		if(pwd[i]==Pwd2[num2])num2++;
		else num2=0;
		if(num2==6)
			break;
	}
	if(num==6 | num2==6)
		{
		OLED_CLS();//清屏
		printf("解锁中");
    BEEP_ON;
	  delay_ms(200);
		BEEP_OFF;
		Con();//电机正转
		OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP2);	
		printf("已解锁");	
		delay_ms(1500);
		OLED_CLS();//清屏
		return 0;
	}
		else 
			{
			OLED_CLS();//清屏
			printf("密码错误");
				for(work=126;work<129;work++)
			{
				OLED_ShowCN(0+(work-126)*16,4,work);//密码错误
			}
			delay_ms(1500);
			OLED_CLS();//清屏
			return -1;
		}
	
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111

主函数

main

以下为我未进行封装的主函数,这样可以更好的理解整个系统的实现过程

//锁屏界面
		MMMD:
		OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);
	  
			while(1)
			{
						MFRC522_Initializtion();
						Error = MFRC522Test();
						//MFRC522解锁					
						if(Error==0)
						{
						BEEP_ON;
						delay_ms(200);
						BEEP_OFF;
						Con();//电机正转
						OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP2);//开锁
						goto MENU;	
					  }
						else 
						OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);//锁
					//手机蓝牙解锁密码1
						if(rx_flag==1)
						{
						Error=Usart3_cherk((char*)Pwd);         
						if(Error==0)
							{	
							printf("蓝牙解锁中\r\n");
							Con();
							BEEP_ON;
							delay_ms(200);
							BEEP_OFF;
							printf("蓝牙解锁成功\r\n");
							OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP2);
							rx_flag=0;
							goto MENU;					
							}
							else 
							OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);//锁
							Error=Usart3_cherk((char*)Pwd2);
							if(Error==0)
							{
							printf("蓝牙解锁中\r\n");
							Con();
							BEEP_ON;
							delay_ms(200);
							BEEP_OFF;
							printf("蓝牙解锁成功\r\n");
							OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP2);
							rx_flag=0;
							goto MENU;				
						}
						else 
						OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);//锁
						}
							
					//指纹解锁
					if(PS_Sta)	//检测PS_Sta状态,如果有手指按下
					{						
						Error=press_FR();//刷指纹
						if(Error==0)
						{
							goto MENU;
						}
						else 
						OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);//锁
					}
					//密码锁
					if(rx_jp_flag==1)
					{
					key_num=Key_Value();	//按键扫描
					if(key_num >=0)
					{
						Error=password();
						if(Error==0)
						{
							rx_jp_flag=0;
							goto MENU;	
						}
						else 
						OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);//锁
				   }
				 }
				}
		//主界面
			MENU:
				OLED_Fill(0x00);//全屏灭
				for(i=6;i<10;i++)
			{
				OLED_ShowCN(22+(i-5)*16,0,i);//功能选择
			}
			for(i=10;i<16;i++)
			{
				OLED_ShowCN(22+(i-10)*16,2,i);//一录入指纹
			}
			for(i=16;i<22;i++)
			{
				OLED_ShowCN(22+(i-16)*16,4,i);//二删除指纹
			}
			for(i=22;i<28;i++)
			{
				OLED_ShowCN(22+(i-22)*16,6,i);//三修改密码
			}
			while(1)
			{
				if(rx_flag == 1)
				{
					rx_flag =0;
					printf("%s",USART3_RX_BUF);
					buf=atoi(USART3_RX_BUF);				
					printf("%d",buf);	
					if(buf)
				{
					switch(buf)
						{
							case 1:Add_FR();		break;//录指
							case 2:Del_FR();		break;//删指纹
							case 3:SetPassworld();break;//修改密码
							case 4:rx_flag = 0;memset(buf,0,strlen((const char *)buf)); memset(USART3_RX_BUF,0,strlen((const char *)USART3_RX_BUF));Rok();goto MMMD;//返回主界面
						}
						rx_flag = 0;
						memset(buf,0,strlen((const char *)buf));
						USART3_RX_STA=0;
						memset(USART3_RX_BUF,0,strlen((const char *)USART3_RX_BUF));
						goto MENU;		
				}
				
			}
				
				//printf("主界面 \r\n");
				if(rx_jp_flag==1)
				{
				key_num=Key_Value();	//按键扫描
				if(key_num)
				{
					switch(key_num)
						{
							case '1':Add_FR();		break;//录指
							case '2':Del_FR();		break;//删指纹
							case '3':SetPassworld();break;//修改密码
						  case '4':rx_jp_flag=0;Rok();goto MMMD;
						}
						rx_jp_flag=0;
						goto MENU;
				}
				}
				
			}
				 
	} //whlie 
}//main
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150

总结

本次项目的难点在于如果对各个未接触过的模块进行初始化,上电进行调试,十分考验个人自主移植厂家提供代码能力以及整合网络资料的能力,实验各个独立模块功能的实现;然后就是进行模块的整合,一个一个模块的添加,一步一步解决出现的问题,不建议同时将4个模块整合到开发板上。应用逻辑代码简单容易实现;后续可以进行低功耗处理,整体代码可以使用FreeRTOS重新封装编写。
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/878274
推荐阅读
相关标签
  

闽ICP备14008679号