目录

前言:程序包下载

一、简要的过程

二、涉及的知识点

三、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;   //遍历清零
       }
}
 
 
 
 
 

四、矩阵键盘的详解

五、串口屏的详解