数字密码锁的详解之梳理F4总结系列逻辑篇(三)

目录

前言:程序包下载

一、简要的过程

二、涉及的知识点

三、main.c函数

四、矩阵键盘的详解

五、串口屏的详解

前言:程序包下载

下载方式一:CSDN下载:https://download.csdn.net/download/qq_38351824/12128803

下载方式二:微信公众号:① 关注Tech云   ② 回复 数字密码锁  文章最后有下载链接

一、简要的过程

--->输入开机密码(输入三次错误后,需要输入管理员密码)

--->输入正确后进入主程序

--->通过独立按键进入修改密码的模式

--->输入管理员密码(输入三次错误后,冻结60s才能接着输入)

--->输入正确后进入开始修改密码

--->填写修改的密码

--->检测密码是否修正成功

--->断电重启后,再次输入密码

--->密码修改成功

二、涉及的知识点

1、C语言

结构体、数组、指针、条件语句、循环语句

2、STM32F429

IO读写、SPI、IIC、USART

三、main.c函数

/**
  ******************************************************************************
  * @file    main.c
  * @author  Sumjess
  * @version V1.0
  * @date    2019-05-xx
  * @brief   MDK5.27
  ******************************************************************************
  * @attention
  *
  * 实验平台   :STM32 F429 
  * CSDN Blog  :https://blog.csdn.net/qq_38351824
  * 微信公众号 :Tech云
  *
  ******************************************************************************
  */
  
#include "sum_common.h"
#include "bsp_4X4key.h" 
#include "OLED_Show.h"
#include "bsp_HIM.h"
#include "bsp_i2c_ee.h"

#include "OLED.h"

#define  pass_num 6
#define  EEP_Firstpage      0x00

void input_passw(void);
void input_change(void);
struct{
		int standard_pass[pass_num] ;   //用户密码
		int manage_pass[pass_num];      //管理员密码
		int input_pass[pass_num];       //用户键入密码
}password={{0,1,2,3,4,5},{1,2,3,4,5,6},{0}};

	int Key_val=0;
		
	struct{
		int count;   //输入密码位数
		int show;    //用*显示密码位数
	  int pairing; //输入密码和正确密码的匹配数量
		int pairing2;//输入密码和正确密码的匹配数量
  } input_test = { 0, 0 , 0 , 0};  //密码位数把控及显示、密码比对结构体
	
	struct{
		int verification;   //密码验证完毕
		int succeed;        //密码正确
	  int Admin;          //管理员密码
		int ERROR_count;    //错误次数
  } Flag = { 0, 1 , 0, 0};  //标志位结构体	

	struct{
		int verification;   //密码验证完毕
		int succeed;        //密码正确
		int change;         //密码修改准备开始
		int ERROR_count;    //错误次数
		int test;           //测试是否密码修改成功
  } Flag_change = { 0, 1 , 0, 0, 0};  //修改密码标志位结构体	
	
	struct{
		int one;   //密码验证完毕
		int two;        //密码正确
	  int three;          //管理员密码
		int four;    //错误次数
  } Flag_Del = { 0, 0 , 0, 0};  //标志位结构体
	

int main(void)
{ 
	
	
 	SysTick_Init();	 	        //时钟初始化  
	LED_GPIO_Config();	      //板载LED初始化                     
	LED_PURPLE;               //紫灯亮---开始初始化,请不要进行操作
	I2C_EE_Init();
	
  Debug_USART_Config();	    //串口初始化USART1
	Key_GPIO_Config();
	OLED_Init();
	
  Key4X4_GPIO_Config();     //矩阵键盘4X4初始化
	LED_YELLOW;               //黄灯亮---初始化结束,初始化成功,可以开始操作   
  input_passw();            //输入开机密码


	while(1) 
  {  
		 input_change();			  //修改开机密码

   }
}

///////////////////////////////////////////////////////修改开机密码//////////////////////////////////////////////////////
void input_change(void)
{
	if(Key_Scan(GPIOA,GPIO_Pin_0))  //修改密码的按键是否按下
	{
		while(Flag_change.succeed)    //密码是否修改成功
		{
			SHOW_Password_change();     //显示修改密码
			Key_val=KEY_Scan();         //键值获取
			if(Key_val!=NO_press)       //确保有按键按下
			{ 
				if(Key_val<=9)            //确保是0-9的数字
				{ 											
					if(input_test.count<pass_num)  //确保输入数字不超过pass_num(6)位
					{  
						*(password.input_pass+input_test.count) =	Key_val; //移位存储数据,指针指向数组的首地址(password.input_pass[0])然后通过自加变量input_test.count进行移位。
						++input_test.count;                                //input_test.count自加
						input_test.show=input_test.count;		               //用*显示密码位数
						for(;input_test.show>0;input_test.show--)          //用*显示密码位数
							OLED_ShowChar(32+input_test.show*8,5,'*');         //用*显示密码位数
					}
				}
				//////////////////////////////////////////////////////
				if(Key_val==10)    //确保是A,相当于确认键,开始比对密码
				{
					for(int b=0;b<pass_num;b++)  //遍历比对
					{ 
						if(*(password.input_pass+b) == *(password.manage_pass+b)) //是否比对成功
							input_test.pairing++;						                        //如果成功,匹配数量加一
					 }			
					Flag_change.verification = 1;                               //比对完毕,开始测试密码是否符合要求
				 }			
			}
			////////////////////////////////////////////////////////////////////////////////////////////////////////////	
			if(Flag_change.verification)         //开始测试密码是否符合要求
			{ 
				Flag_change.verification=0;        //清空标志位
				if(input_test.pairing==pass_num)   //如果六位密码都对
				{ 
					LED_GREEN;                       //绿灯通过
					Flag_change.change=1;            //密码成功开始修改密码标志位
					SHOW_Password_OK(); 	           //显示密码通过
					Delay_ms(500);                   //延时500ms
					OLED_Clear();                    //清屏
				}
			else
			{
				LED_RED;                         //红灯警报
				input_test.count=0;              //清空输入密码位数
				input_test.pairing=0;            //清空配对数量
				for(int c=0;c<pass_num;c++)      //遍历输入数据数组清零
				{     
					*(password.input_pass+c)=0;      //清空用户输入的错误密码
					SHOW_Password_error();           //显示输入密码错误
					Delay_ms(500);                   //延时500ms
				}
				OLED_Clear();                      //清屏
			 } 
			}
			if(Flag_change.change)            //密码修改完毕,开始检测
			{
				Flag_change.change=0;           //清空标志位
				input_test.count=0;             //清空输入密码位数
				LED_WHITE;                      //白灯亮
			while(1)
			{
				SHOW_Password_new();           //显示请输入新密码
				Key_val=KEY_Scan();            //键值获取
				if(Key_val!=NO_press)          //确保有按键按下
					if(Key_val<=9)               //确保是0-9的数字
					{
						if(input_test.count<pass_num)   //确保输入数字不超过pass_num(6)位
						{ 
							*(password.standard_pass+input_test.count) =	Key_val; //移位存储数据,指针指向数组的首地址(password.standard_pass[0])然后通过自加变量input_test.count进行移位。
							++input_test.count;                                //input_test.count自加
							input_test.show=input_test.count;		               //显示密码
							OLED_ShowNum(32+input_test.show*8,6,Key_val,1,16); //显示密码
						}
					}
			//////////////////////////////////////////////////////
			if(Key_val==10)    //确保是A,相当于确认键,开始比对密码
			{
					//将I2c_Buf_Write中顺序递增的数据写入EERPOM中 
	        I2C_EE_BufferWrite( password.standard_pass, EEP_Firstpage, 6);
					OLED_Clear();        //清屏
					Flag_change.test=1;  //打开测试程序的标志位
					SHOW_pass_succ();    //显示密码修改成功
					Delay_ms(500);       //延时500ms
					OLED_Clear();        //清屏
					Flag_change.succeed=0;//清空密码修改成功标志位 
					break;
				}	
			}
		 }
	}

		if(Flag_change.test)      //密码修改测试
		{
			input_test.count=0;     //清空输入位数 
			Flag.ERROR_count=0;     //清空输错次数
			for(int b=0;b<pass_num;b++)  //遍历清空数组
				*(password.input_pass+b) = 0;
			while(1)
			{		       
			  SHOW_Password_user();  //请输入用户密码
				Key_val=KEY_Scan();    //键值获取
				if(Key_val!=NO_press)  //确保有按键按下
				{  
					if(Key_val<=9)       //确保是0-9的数字
					{ 
						if(input_test.count<pass_num)  //确保输入数字不超过pass_num(6)位
						{  
							*(password.input_pass+input_test.count) =	Key_val; //移位存储数据,指针指向数组的首地址(password.input_pass[0])然后通过自加变量input_test.count进行移位。
							++input_test.count;                                //input_test.count自加
							input_test.show=input_test.count;		               //用*显示密码位数
							for(;input_test.show>0;input_test.show--)          //用*显示密码位数
								OLED_ShowChar(32+input_test.show*8,5,'*');         //用*显示密码位数
						}
					}
					//////////////////////////////////////////////////////
					if(Key_val==10)    //确保是A,相当于确认键,开始比对密码
					{
						//将EEPROM读出数据顺序保持到I2c_Buf_Read中
						I2C_EE_BufferRead(password.standard_pass, EEP_Firstpage, 6); ;
						for(int b=0;b<pass_num;b++)  //遍历比对
						{  
							if(*(password.input_pass+b) == *(password.standard_pass+b)) //是否比对成功
								input_test.pairing++;						                          //如果成功,匹配数量加一			
							}			
						Flag.verification = 1;                                      //比对完毕,开始测试密码是否符合要求
					}			
				}
				////////////////////////////////////////////////////////////////////////////////////////////////////////////	
				if(Flag.verification)    //开始测试密码是否符合要求
				{ 
						Flag.verification=0;//清空标志位 
						if(input_test.pairing==pass_num)   //如果六位密码都对
						{                                  
							Flag.succeed=0;                  //打开密码成功标志位
							SHOW_Password_OK(); 	           //显示密码通过
							Delay_ms(500);                   //延时500ms
							LED_GREEN;                       //绿灯通过
						}
					else
					{
						LED_RED;                         //红灯警报
						++Flag.ERROR_count;              //错误次数累加
						input_test.count=0;              //清空输入密码位数
						input_test.pairing=0;            //清空配对数量
						for(int c=0;c<pass_num;c++)      //遍历
						{     
							*(password.input_pass+c)=0;      //清空用户输入的错误密码
							SHOW_Password_error();           //显示输入密码错误
							Delay_ms(500);                   //延时500ms                     
						}  
						OLED_Clear();                    //清屏
						if(Flag.ERROR_count>=3)          //检测密码输错次数
						{          
							Flag.ERROR_count=0;            //清空密码输错次数
							SHOW_clock_one();              //显示锁住一分钟
							Delay_ms(500);                 //延时500ms
							OLED_Clear();                  //清屏

							for(int time=0;time<60;time++) //倒计时一分钟
							{
								SHOW_clock_one();              //显示锁住一分钟
								Delay_ms(1000);
								OLED_ShowNum(32,6,60-time,2,16);//实时显示倒计时 
							}
						}
					}
				}
			}	
		}
	}
}


///////////////////////////////////////////////////////输入开机密码//////////////////////////////////////////////////////
void input_passw(void)
{
	while(Flag.succeed)      //密码是否正确
	{   
		SHOW_Password_prompt();//显示请输入密码
		Key_val=KEY_Scan();    //键值获取

		if(Flag.Admin)         //是否进入管理员模式
		{          
			if(Key_val!=NO_press)//确保有按键按下
			{  
			//////////////////////////////////////////////////////
			if(Key_val<=9)       //确保是0-9的数字 
			{ 
				if(input_test.count<pass_num)   //确保输入数字不超过pass_num(6)位
				{  
					*(password.input_pass+input_test.count) =	Key_val; //移位存储数据,指针指向数组的首地址(password.input_pass[0])然后通过自加变量input_test.count进行移位。
					++input_test.count;                                //input_test.count自加
					input_test.show=input_test.count;		               //用*显示密码位数
					for(;input_test.show>0;input_test.show--)          //用*显示密码位数
						OLED_ShowChar(32+input_test.show*8,5,'*');         //用*显示密码位数
				}
			}
			//////////////////////////////////////////////////////
			if(Key_val==10)     //确保是A,相当于确认键,开始比对密码
			{
				//将EEPROM读出数据顺序保持到I2c_Buf_Read中
				I2C_EE_BufferRead(password.standard_pass, EEP_Firstpage, 6); 			
				for(int b=0;b<pass_num;b++)  //遍历比对
				{ 
					if(*(password.input_pass+b) == *(password.manage_pass+b)) //是否比对成功
						input_test.pairing++;						                        //如果成功,匹配数量加一
				}			
				Flag.verification = 1;                                      //比对完毕,开始测试密码是否符合要求
				}			
			}
			////////////////////////////////////////////////////////////////////////////////////////////////////////////	
			if(Flag.verification)         //开始测试密码是否符合要求
			{ 
				Flag.verification=0;        //清空标志位
				if(input_test.pairing==pass_num)   //如果六位密码都对
				{ 
					LED_GREEN;                       //绿灯通过
					Flag.succeed=0;                  //打开密码成功标志位
					Flag.Admin=0;                    //清空管理员模式标志位
					SHOW_Password_OK(); 	           //显示密码通过
					Delay_ms(500);                   //延时500ms
					Flag_Del.one=1;
				}
				else
				{
					LED_RED;                         //红灯警报
					input_test.count=0;              //清空输入密码位数
					input_test.pairing=0;            //清空配对数量
					for(int c=0;c<pass_num;c++)      //遍历
					{     
						*(password.input_pass+c)=0;    //清空用户输入的错误密码
						SHOW_Password_error();         //显示输入密码错误
						Delay_ms(500);                 //延时500ms
					}
					OLED_Clear();                    //清屏
				} 
			}
		}
		else                   //是否进入用户模式
		{		                 
			if(Key_val!=NO_press)//确保有按键按下
			{  
			//////////////////////////////////////////////////////
				if(Key_val<=9)       //确保是0-9的数字
				{ 
					if(input_test.count<pass_num)   //确保输入数字不超过pass_num(6)位
					{  
						*(password.input_pass+input_test.count) =	Key_val; //移位存储数据,指针指向数组的首地址(password.input_pass[0])然后通过自加变量input_test.count进行移位。
						++input_test.count;                                //input_test.count自加
						input_test.show=input_test.count;		               //用*显示密码位数
						for(;input_test.show>0;input_test.show--)          //用*显示密码位数
							OLED_ShowChar(32+input_test.show*8,5,'*');       //用*显示密码位数
					}
				}
			//////////////////////////////////////////////////////
			if(Key_val==10)                                          //确保是A,相当于确认键,开始比对密码
			{
				//将EEPROM读出数据顺序保持到I2c_Buf_Read中
				I2C_EE_BufferRead(password.standard_pass, EEP_Firstpage, 6); 
				for(int b=0;b<pass_num;b++)                            //遍历比对
				{  
				if(*(password.input_pass+b) == *(password.standard_pass+b)) //是否比对成功
					input_test.pairing++;						                          //如果成功,匹配数量加一
				if(*(password.input_pass+b) == *(password.manage_pass+b))   //是否比对成功
					input_test.pairing2++;						                        //如果成功,匹配数量加一				
				}			
				Flag.verification = 1;                                      //比对完毕,开始测试密码是否符合要求
			 }			
		  }
			////////////////////////////////////////////////////////////////////////////////////////////////////////////	
			if(Flag.verification)                                         //开始测试密码是否符合要求
			{ 
				Flag.verification=0;																				//清空标志位
			if((input_test.pairing==pass_num)||(input_test.pairing2==pass_num))   
			{                                  //如果六位密码都对
				Flag.succeed=0;                  //打开密码成功标志位
				SHOW_Password_OK(); 	           //显示密码通过
				Delay_ms(500);                   //延时500ms
				LED_GREEN;                       //绿灯通过
				Flag_Del.one=1;                  //清空标志位和缓存数组数据
			}
			else
			{
				LED_RED;                         //红灯警报
				++Flag.ERROR_count;              //错误次数累加
				input_test.count=0;              //清空输入密码位数
				input_test.pairing=0;            //清空配对数量
				for(int c=0;c<pass_num;c++)      //遍历
				{     
					*(password.input_pass+c)=0;      //清空用户输入的错误密码
					SHOW_Password_error();           //显示输入密码错误
					Delay_ms(500);                   //延时500ms                     
				 }  
				OLED_Clear();                      //清屏
				if(Flag.ERROR_count>=3)            //检测密码输错次数
				{          
					Flag.ERROR_count=0;            //清空密码输错次数
					SHOW_Password_state();         //显示进入管理员模式
					Delay_ms(500);                 //延时500ms
					OLED_Clear();                  //清屏
					Flag.Admin=1;                  //进入管理员模式
				 }
			  }
			 }
			}
		}
		if(Flag_Del.one==1)                 //清空标志位和缓存数组数据
		{
			OLED_Clear();                     //清屏
			Flag_Del.one=0;			              //只清除一次
			input_test.count=0;               //清空输入密码位数
			for(int b=0;b<pass_num;b++)       //遍历清零
				*(password.input_pass+b) = 0;   //遍历清零
	   }
}





四、矩阵键盘的详解

五、串口屏的详解

发布了357 篇原创文章 · 获赞 693 · 访问量 40万+

猜你喜欢

转载自blog.csdn.net/qq_38351824/article/details/104131912
F4