數字密碼鎖的詳解之梳理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;   //遍歷清零
	   }
}





四、矩陣鍵盤的詳解

五、串口屏的詳解

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章