目录

前言:程序包下载

一、简要的过程

二、涉及的知识点

三、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      0x00void 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();      //串口初始化USART1Key_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);                   //延时500msOLED_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);       //延时500msOLED_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);                   //延时500msLED_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);                 //延时500msOLED_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);                   //延时500msFlag_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);                   //延时500msLED_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);                 //延时500msOLED_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;   //遍历清零}
}

四、矩阵键盘的详解

五、串口屏的详解

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

  1. 陶晶驰stm32_陶晶驰HMI3.5寸串口屏的详解之梳理F4总结系列准备篇(二)

    基于stm32的串口屏教程.用过的人都说好,哈哈哈,减少了我们很多不太必要的麻烦步骤. 程序资料包CSDN下载地址:https://download.csdn.net/download/qq_3835 ...

  2. x.509数字证书编码详解

    转自:http://blog.sina.com.cn/s/blog_49b531af0102eahs.html x.509数字证书编码详解 一. X.509数字证书的编码 X.509证书的结构是用AS ...

  3. python正则表达式提取数字比较好_python正则表达式从字符串中提取数字的思路详解...

    python从字符串中提取数字 使用正则表达式,用法如下: ## 总结 ## ^ 匹配字符串的开始. ## $ 匹配字符串的结尾. ## \b 匹配一个单词的边界. ## \d 匹配任意数字. ## ...

  4. Python Tkinter——数字拼图游戏详解版

    Python Tkinter 实践系列--数字拼图游戏详解版 import random #Python中的random是一个标准库用于生成随机数.随机整数.还有随机从数据集取数据. import t ...

  5. C语言中的字符串转数字函数常见问题详解

    目录 C语言中的字符串转数字函数常见问题详解 字符串转整形 atoi函数 字符串转长整形 strtol函数, C语言中的字符串转数字函数常见问题详解 字符串转整形 atoi函数 函数原型: int a ...

  6. php 获取手机特征码,【新人学习】按键精灵获取数字特征码实例详解

    按键精灵获取数字特征码实例详解 运行环境:分辨率:1440x900 色深:32位 操作系统:Windows XP 按键精灵版本:7.00.3730 @兄弟工程师01未评2009/3/19//做这东西主 ...

  7. linux文件属性644到755,linux系统文件夹数字权限设置详解644、755、777

    linux系统文件夹数字权限设置详解644.755.777 ,左至右,第一位数字代表文件所有者的权限,第二位数字代表同组用户的权限,第三位数字代表其他用户的权限. 而具体的权限是由数字来表示的,读取的 ...

  8. (4)top详解 (每周一个linux命令系列)

    (4)top详解 (每周一个linux命令系列) linux命令 top详解 引言:今天的命令是用来看cpu信息的top top 我们先看man top top - display Linux pro ...

  9. 详解Linux运维工程师打怪升级篇

    详解 Linux 运维工程师打怪升级篇 积累经验篇 做运维也快4年多了,就像游戏打怪升级,升级后知识体系和运维体系也相对变化挺大,学习了很多新的知识点. 运维工程师 是从一个呆逼进化为苦逼再成长为牛逼 ...

最新文章

  1. Vue中使用form表单提交刷新问题
  2. 通过先序和中序数组生成后续数组
  3. minicap_工具使用
  4. Hibernate视频学习笔记(3)常用映射标签及属性
  5. robomaster裁判系统服务器,2018裁判系统调试组网完全攻略
  6. Google Earth 和MS Virtual Earth:虚拟地球简介
  7. linux中断响应时间太慢_Linux中的进程调度有哪些核心概念?
  8. 团队文化中的害群之马
  9. svm神经网络葡萄酒matlab,SVM神经网络的数据分类预测-葡萄酒种类识别
  10. python生成简单二维码_使用Python生成个性二维码
  11. 【文献阅读未遂】Understanding data storage and ingestion for large-scale deep recommendation model training
  12. Android 9 Audio系统笔记:AudioFlinger音频流处理流程
  13. Untiy AVpro
  14. 怎样用电脑收发短信?
  15. 【XSY2508】【BZOJ4424】Fairy(二分图)
  16. STM32——三原色
  17. Synology NAS多媒体(Photo Station管理照片)
  18. Java课程设计记录——虚拟校园系统
  19. Jprofile连接远程机器
  20. ubuntu 18.04 安装 ROS

热门文章

  1. C++ fstream 创建文件
  2. Trinity简介(1)--用于无参考基因组的转录组de novo组装
  3. 假如自家APP被苹果下架了 你会怎么处理?
  4. java身高排队问题_抓狂的java之小朋友排队
  5. 苹果新规,微信面临下架?一文看懂苹果与腾讯“相亲相爱相杀”
  6. WSL(Ubuntu20.04)与其图形界面安装配置
  7. 牛客寒假基础集训营 | Day1 D题—hanayo和米饭
  8. java和vue募捐网水滴筹项目捐款爱心系统筹款系统
  9. oracle云怎么购买,使用免费的Oracle云服务-创建云主机
  10. SAP中采购订单交货己完成相关逻辑和控制原理分析