本帖最后由 凌净清河 于 2018-12-11 12:04 编辑
重新编辑说明:取消了回复才能下载的限制,取消了下载付黑币的设置。
另外我建立了一个STC 51单片机初学者提升qq群,如果你想在单片机的道路上从菜鸟走到入门,欢迎加群和大家共同成长。群刚开始建立,人数尚少,内有资料不断完善中。群聊号码:873434536
特注:群不盈利、无广告、没有强制活动、没有潜规则,仅为个人兴趣和专业方向使然。
声明:
0.基本版代码相对冗余,但仍然请大家在转载、分享时提及原作者,非常感谢
1.设计使用STC15W4K48S4制作,在无需修改管理员密码的版本中可以使用IAP的单片机代替
2.本程序和设计为最基本版,只有简单的密码开锁和管理功能,更多更完善功能的版本请期待本人的后续帖子(虽然已经设计完成,但还是预计2019年1月份,考完研之后才能够整理发出)
3.由于是初稿,所以程序的结构上比较混乱,本人只保证其可以运行并且没有明显的BUG、不保证程序可读性,但是大家可以自取所需功能
4.本版本只是一个“预热”,请高手勿喷,至少也请看完1、2个月后的第二版之后再说;
请初学者不要仿制,毕竟这个版本还非常非常LOW,远远没有达到使用标准,也没有进行功能的优化、逻辑的论证、程序的精简,这些将在第二版中体现出来。
设计亮点:
1.使用OLED12864屏幕显示,具有用户菜单和管理员菜单,直观明了的设置使用流程(菜单未使用结构体或链表)
2.用户密码存储加密,使用BKDR哈希值计算并存储,防止从24C02中窃取密码
3.放弃传统的矩阵键盘,使用ADC键盘,连接上更加方便
4.如3项所示,密码为16进制,最大输入16位
5.对于添加了管理员密码的版本,使用内部EEPROM存储管理员密码(在本版本中,管理员密码明文存储)
简易操作说明:
上电进入用户模式锁定状态,在锁定状态下输入密码后,使用KEY1键确认,KEY2键取消,若密码正确,在按下确认键的时候会显示正确提示信息,松开按键进入用户菜单
如果用户模式下密码连续输入错误5次则自动锁死,此时可以重新上电清空错误计数或者进入管理员模式立即解锁,这种锁定不会自动解锁
在用户菜单下不进行任何操作5秒则自动上锁,使用KEY3、KEY4键进行选项的上下选择,KEY1键执行,KEY2键取消,在用户模式下按KEY2键取消会返回上锁状态
在用户模式锁定状态下,若硬件开关Hardware_Switch(P4^5)置0,按下KEY1键进入管理员认证,管理员密码输入流程与用户相同,密码正确则进入管理菜单
在管理员菜单下可以进行各样高权限操作,这些操作在程序上对用户模式屏蔽。
在管理模式菜单中各项选项的功能和操作说明如下:
1.立即解除锁定
该选项将用户模式错误计数变量清零,没有提示信息,按下确认键即可
2.修改用户密码
在管理员状态下修改用户密码不需要确认,直接输入新密码确定即立即生效,在输入密码时按下取消键原密码不改变
3.修改管理密码
修改管理密码需要两步:身份认证和输入新密码。在任何一步按下取消键原密码不改变
4.常开常关选项
当停用密码锁时返回用户状态时继电器常开
当启用密码锁时用户模式正常
5.版本信息
用于记录或显示某些信息,这些信息允许在编程阶段修改
6.退出管理模式
选择此项按确定键和在任意项上按返回键效果一致,均回到管理员身份验证状态,希望回到用户模式时可以在管理员非密码修改模式下拔除Hardware_Switch(P4^5)跳帽或将其置高
考虑到的意外情况:
如果在关机时将AT24C02替换,且没有存储准确的信息,开机上电用户模式会自动锁死,需要管理员重置用户密码
实现机制:在AT24C02中不仅存放了用户密码的HASH值,也存入了4个字节的用户ID信息,这信息与烧录在程序中的用户ID信息必须一致,才能够通过上电检测,否则使用户锁定标志位有效
版本缺陷:
由于本版本是最初学习时尝试设计的,所以有一些问题和缺陷,随着后续的修改和测试逐渐发现的,但是已经无心更改。现列出所有问题如下所示:
1.继电器控制引脚的位定义未在包含文件语句(#include)之前,使得其他文件中对继电器的操作是直接给P00赋值,而非使用JDQ这个位定义名称,修改时需要注意;
2.继电器的控制三极管采用了NPN型,但是后来发现这样会导致上电吸合一次,在第二版中修正了这个错误但是本版本仍然保留;
3.本版本中设定密码开锁后5秒自动关锁,这个在程序中可以修改,需要注意一下;
4.按键按下会导致程序死循环,原因是仅仅使用了最简单的按键判断:即假设每个独立按键按下之后都会立即松开;
5.本版本中未添加时间修改函数,程序的时间是在下载程序的时候掐点矫正的,第二版会添加该功能。
单片机源程序如下:
- #include<STC15.H>
- #include<intrins.h>
- sbit LED1=P3^0;
- sbit LED2=P3^1;
- sbit KEY1=P3^2;
- sbit KEY2=P3^3;
- sbit KEY3=P2^1;
- sbit KEY4=P2^2;
- //由于后续包含的文件中可能用到上述位定义故将这部分位定义放在包含文件的语句之前
- #include"OLED_Display.c"
- #include"DS1302_Driver.c"
- #include"AT24C02_Driver.c"
- #include"BKDR_HASH_Fuction.c"
- sbit JDQ=P0^0;//继电器引脚
- sbit Hardware_Switch=P4^5;//管理员/用户硬件开关 用户:1 管理员:0
- //扩展作用域
- extern unsigned char hash_result[4];
- //运行数组
- unsigned char user_ID[4]={0x92,0x5A,0xA0,0xC1};
- unsigned char version[4]={0,9,0,8};//版本信息(自定义)
- unsigned char Administrator_Password[16]={0,1,0,15,0,0,0,0,0,0,0,0,0,0,0,0};//管理员密码存放数组
- unsigned char User_Password_Putin[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//用户密码输入临时存放数组
- unsigned char Admin_Password_Putin[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//管理员密码输入临时存放数组
- unsigned char Admin_Password_New_Temp[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//管理员密码修改时,新密码临时存放数组,可以考虑与输入临时存放数组复用
- //运行变量
- unsigned int ADC_DATA;//读取到的ADC转换值
- unsigned char ADC_value=0;//设置一个读取到的按键位置值。位置值由电路连接确定,各个按键位置值由所连电阻分压大小依次顺序排列
- unsigned char ADC_keyvalue=0;//读取到的ADC按键设定值。按键位置由电路而定可能并不规整,设定值为自定的各按键数值
- unsigned char first_num=1;//管理模式第一项菜单标号
- //运行计数
- unsigned char choose=1;//用户菜单选择号,用于记录当前选中的菜单项目序号,默认在第一项位置
- unsigned char cnt_user_putin_wrong=0;//用户输入错误计数
- unsigned char t1_cnt=0;//定时器1运行计数
- //运行标志位
- bit flag_Identity=1;//身份标志位,表明当前所处身份状态 用户:1 管理员:0
- bit En_Standby=1;//待机状态有效标志位(使能) 有效:1 无效:0
- bit En_Admin=0;//管理员模式下管理有效标志位(使能) 有效:1 无效:0
- bit User_Locker=0;//用户输入错误导致的锁定有效 有效:1 无效:0
- bit Admin_Info=0;//管理员提示开关,在用户待机状态下显示某些信息 有效:1 无效:0
- bit _ReLock=0;//自动锁定标志位,显示定时器是否已经到达计时时间 是:1 否:0
- /*##############################################################################################
- 设计名称:电子锁设计
- 设计者:清河
- 版本:9.8.1
- 详情:已经初步完成功能设定,添加自动锁定功能,并排除BUG。丰富了注释内容。
- 添加用户的断电密码记忆功能和密码加密存储功能,添加开机AT24C02判断
- 掉电存储构想:
- 在每一次更新用户密码时将新密码hash值存放进存储器中,管理员密码明文存储
- 加密存储构想:
- 使用加密函数将用户密码加密后存储,核对密码时通过加密函数求出特征值和存储器中的比对
- 存储安全性保证:为防止换用AT24C02导致使用不便或达到非法开锁的目的,分别使用AT24C02存储用户的密码HASH值
- 片外EEPROM:存放用户密码的HASH值,并存入检测字节,在系统启动时检测AT24C02是否有被改动过以提高系统安全性
- 扩展:如果有用户个性化的设置,也可以如此存放,便于管理
- 平台:STC15W4K48S4
- 硬件部分
- 独立按键:共4个,用于进行各项调整
- ADC键盘:用于输入密码,本作品中可以输入16进制的密码,较平常10位密码更加安全,只要程序和电路做相应的修改,也可以实现在AD可分辨的情况下上百的按键键位
- DS1302:配电池,实现断电走时,用于待机显示,如果在关机时取下电池或者替换DS1302则会出错,需要重新烧录程序初始化DS1302
- LED指示灯:指示所处状态,本作品中进入用户模式则LED1亮,进入管理员模式则LED2亮
- AT24C02:实现断电密码记忆功能,用于记录用户密码的HASH值
- 软件部分
- 使用定时器0实现对DS1302数据的定时读取,间隔50ms,以便更新当前的显示值
- 使用定时器1在用户解锁成功时定时上锁,设置的超时时间为5秒
- 操作说明:
- 上电进入用户模式锁定状态,在锁定状态下输入密码后,使用KEY1键确认,KEY2键取消,若密码正确,在按下确认键的时候会显示正确提示信息,松开按键进入用户菜单
- 如果用户模式下密码连续输入错误5次则自动锁死,此时可以重新上电清空错误计数或者进入管理员模式立即解锁,这种锁定不会自动解锁
- 在用户菜单下不进行任何操作5秒则自动上锁,使用KEY3、KEY4键进行选项的上下选择,KEY1键执行,KEY2键取消,在用户模式下按KEY2键取消会返回上锁状态
- 在用户模式锁定状态下,若硬件开关Hardware_Switch(P4^5)置0,按下KEY1键进入管理员认证,管理员密码输入流程与用户相同,密码正确则进入管理菜单
- 在管理员菜单下可以进行各样高权限操作,这些操作在程序上对用户模式屏蔽。
- 在管理模式菜单中各项选项的功能和操作说明如下:
- 1.立即解除锁定
- 该选项将用户模式错误计数变量清零,没有提示信息,按下确认键即可
- 2.修改用户密码
- 在管理员状态下修改用户密码不需要确认,直接输入新密码确定即立即生效,在输入密码时按下取消键原密码不改变
- 3.修改管理密码
- 修改管理密码需要两步:身份认证和输入新密码。在任何一步按下取消键原密码不改变
- 4.常开常关选项
- 当停用密码锁时返回用户状态时继电器常开
- 当启用密码锁时用户模式正常
- 5.版本信息
- 用于记录或显示某些信息,这些信息允许在编程阶段修改
- 6.退出管理模式
- 选择此项按确定键和在任意项上按返回键效果一致,均回到管理员身份验证状态,希望回到用户模式时可以在管理员非密码修改模式下拔除Hardware_Switch(P4^5)跳帽或将其置高
- 考虑到的意外情况:
- 如果在关机时将AT24C02替换,且没有存储准确的信息,开机上电用户模式会自动锁死,需要管理员重置用户密码
- 实现机制:在AT24C02中不仅存放了用户密码的HASH值,也存入了4个字节的用户ID信息,这信息与烧录在程序中的用户ID信息必须一致,才能够通过上电检测,否则使用户锁定标志位有效
- 特别注意:继电器部分在本版本程序中没有考虑到上电初始控制电平的问题,上电瞬间会吸合一次,建议将所有JDQ位反向控制,并将OLED_Display.c中对P00的控制相应更改。
- 更改后外围电路上应采用PNP典型控制电路即P口低电平时继电器打开,否则关闭
- 经过再三考虑,不添加密码重置功能,即在添加掉电存储的程序版本中,一旦忘记用户密码和管理密码则无法找回,只能通过刷固件的方式重置密码以提高整体安全性
- 但是后期若能够添加指纹识别等模块,通过该个人生物识别的机制更改管理密码会使安全性得到很大的提升
- ##############################################################################################*/
- void delay(unsigned int cnt)//调用该函数进行一段时间的延时
- {
- while(cnt--);
- }
- unsigned char KeyScan()
- {
- unsigned char ADC_keyvalue=0;//读取到的ADC按键设定值
- ADC_CONTR=0xea;//开始转换
- delay(1000);//这段暂停的时间用于等待AD转换完成
- switch(ADC_value)
- {
- case 0:ADC_keyvalue=12;break;
- case 1:ADC_keyvalue=13;break;
- case 2:ADC_keyvalue=14;break;
- case 3:ADC_keyvalue=15;break;
- case 4:ADC_keyvalue=11;break;
- case 5:ADC_keyvalue=10;break;
- case 6:ADC_keyvalue=9;break;
- case 7:ADC_keyvalue=8;break;
- case 8:ADC_keyvalue=4;break;
- case 9:ADC_keyvalue=5;break;
- case 10:ADC_keyvalue=6;break;
- case 11:ADC_keyvalue=7;break;
- case 12:ADC_keyvalue=3;break;
- case 13:ADC_keyvalue=2;break;
- case 14:ADC_keyvalue=1;break;
- case 15:ADC_keyvalue=0;break;
- default:ADC_keyvalue=16;break;
- }
- return ADC_keyvalue;
- }
- unsigned char Modify_User_Password()//用户密码更改函数,用于获取新值赋给用户密码数组
- {
- unsigned char i;
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle7,1);//显示标题:修改密码
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar3,1);//显示横线
- }
- OLED_Show_CHinese(4,CCInfo5,1);//显示说明文字:请输入新密码:
-
- for(i=0;i<16;)//进入输密码的环节
- {
- OLED_Show_Number(0,6,User_Password_Putin,i,1);//显示输入的值
- if(KeyScan()!=16)
- {
- delay(5000);
- if(KeyScan()!=16)
- {
- User_Password_Putin[i]=KeyScan();//记录每一次输入的值
- i++;
- }
- while(KeyScan()!=16);//等待按键松开
- }
-
- if(KEY1==0||i==16)//如果确定键按下或输满16位
- {
- delay(5000);
- if(KEY1==0||i==16)
- {
- unsigned char k=0;
- Password_BKDRHASH_Calculation(User_Password_Putin,16);//对输入的值求HASH值,保存在hash_result数组中
- Save_User_Password();//保存新数据
- for(k=0;k<16;k++)
- {
- User_Password_Putin[k]=0;//清空用户输入
- }
- }
- while(!KEY1);
- OLED_Clear();//清屏,清屏放在此处可以使密码正确的提示信息在按键松开前一直显示
- break;//立即退出输入密码的环节
- }
-
- if(KEY2==0)//如果取消键按下
- {
- delay(5000);
- if(KEY2==0)
- {
- unsigned char j;
- for(j=0;j<16;j++)
- {
- User_Password_Putin[j]=0;//清空用户输入
- }
- OLED_Clear();//清屏
- }
- while(!KEY2);
- break;//立即退出输入密码的环节
- }
- }
- return 0;
- }
- unsigned char Modify_Admin_Password()//管理员密码修改,包括2个步骤:身份认证、密码修改,其中任何一步都可以由取消键退出
- {
- unsigned char i;
- OLED_Clear();
- OLED_Display_Administrator_Onload();
-
- for(i=0;i<16;)//进入输密码的环节
- {
- if(KeyScan()!=16)
- {
- delay(5000);
- if(KeyScan()!=16)
- {
- Admin_Password_Putin[i]=KeyScan();//记录每一次输入的值
- OLED_Show_sChar(i*8,6,sChar1,1);//显示*
- i++;
- }
- while(KeyScan()!=16);//等待按键松开
- }
-
- if(KEY1==0||i==16)//如果确定键按下或输入位数满
- {
- delay(5000);
- if(KEY1==0||i==16)
- {
- unsigned char k=0,t=0;
- for(k=0;k<16;k++)
- {
- if(Admin_Password_Putin[k]==Administrator_Password[k])//核对明文密码
- {
- t++;//每有一个位置同,则t自增
- }
- }
-
- if(t==16)//密码正确,可以进行修改密码的操作
- {
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle7,1);//显示标题:修改密码
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar3,1);//显示横线
- }
- OLED_Show_CHinese(4,CCInfo5,1);//显示说明文字:请输入新密码:
- while(!KEY1);
-
- for(i=0;i<16;)//进入输密码的环节
- {
- OLED_Show_Number(0,6,Admin_Password_New_Temp,i,1);//显示输入的值
- if(KeyScan()!=16)
- {
- delay(5000);
- if(KeyScan()!=16)
- {
- Admin_Password_New_Temp[i]=KeyScan();//记录每一次输入的值
- i++;
- }
- while(KeyScan()!=16);//等待按键松开
- }
-
- if(KEY1==0||i==16)//如果确定键按下或输满16位
- {
- delay(5000);
- if(KEY1==0||i==16)
- {
- unsigned char k=0,t=0;
- for(k=0;k<16;k++)
- {
- Administrator_Password[k]=Admin_Password_New_Temp[k];//存入新密码
- Admin_Password_New_Temp[k]=0;//清空输入
- }
- }
- while(!KEY1);
- OLED_Clear();//清屏,清屏放在此处可以使密码正确的提示信息在按键松开前一直显示
- break;//立即退出输入密码的环节
- }
-
- if(KEY2==0)//如果取消键按下
- {
- delay(5000);
- if(KEY2==0)
- {
- unsigned char j;
- for(j=0;j<16;j++)
- {
- Admin_Password_New_Temp[j]=0;//清空用户输入
- }
- OLED_Clear();//清屏
- }
- while(!KEY2);
- break;//立即退出输入密码的环节
- }
- }
- }
- else//密码错误
- {
- for(k=0;k<16;k++)
- {
- Admin_Password_Putin[k]=0;//清空管理员输入
- }
- OLED_Clear();
- }
- }
- while(!KEY1);
- goto END;//结束输入
- }
-
- if(KEY2==0)//如果取消键按下
- {
- delay(5000);
- if(KEY2==0)
- {
- unsigned char j;
- for(j=0;j<16;j++)
- {
- Admin_Password_Putin[j]=0;//清空管理员输入
- }
- OLED_Clear();
- }
- while(!KEY2);
- goto END;//结束输入
- }
- }
- END:return 0;
- }
- void sys_init()//系统初始化
- {
- P1M1=0x00;
- P1M0=0x00;
- P3M1=0x00;
- P3M0=0x00;
- P2M1=0x00;
- P2M0=0x00;
- P4M1=0x00;
- P4M0=0x00;
- P5M0=0x00;
- P5M1=0x00;
- P0M1=0x00;
- P0M0=0x00;//对于STC15W4K32S4系列的单片机,对IO的初始化操作必须要有
-
- TMOD=0x11;//设置定时器模式
- EA=1;//开启总中断
- TL0=0x00;//设置定时初值
- TH0=0x28;//设置定时初值
- ET0=1;//允许定时器0中断
- TR0=1;//定时器0开始计时
-
- TL1=0x00;//设置定时初值
- TH1=0x28;//设置定时初值
- ET1=1;//允许定时器1中断
- TR1=0;//定时器1开始计时
-
- P1ASF=0x04;//将P1^2设置为模拟输入
- ADC_CONTR=0xe7;//开启ADC电源,设置为最快转换速度,停止转换,选取P1^2作为ADC输入
- ADC_RES=0;//清除结果寄存器
- /*ADRJ=0;//ADC_RES[7:0]存放高8位ADC结果,ADC_RES[1:0]存放低2位ADC结果 EADC=1;//A/D转换中断允许 PADC=1;//设置A/D转换中断优先级为最高*/
- //CLK_DIV=0X20;
- EADC=1;
- PADC=1;
- }
- void sys_Pretreat()//系统预处理
- {
- //Ds1302Init();//首次上电对DS1302做初始化
- OLED_Init();//初始化OLED
- OLED_Clear();//OLED清屏
- JDQ=0;//继电器给低电平
-
- /*在此处添加上电AT24C02检测*/
- for(t1_cnt=0;t1_cnt<8;t1_cnt++)//将t1_cnt作为临时计时变量
- {
- AT24C02_Read_Array[t1_cnt]=AT24C02_Read(0xA0,t1_cnt+1);
- Delay1ms();
- }
- for(t1_cnt=0;t1_cnt<4;t1_cnt++)//将t1_cnt作为临时计时变量
- {
- if(AT24C02_Read_Array[t1_cnt]!=user_ID[t1_cnt])//如果从AT24C02中读出的用户ID和程序中设定值不同说明器件被更替,用户锁定,需要重新设置密码
- {
- User_Locker=1;
- }
- }
- t1_cnt=0;//使用后重置t1_cnt
- }
- void main()
- {
- sys_init();
- sys_Pretreat();
- while(1)
- {
- if(flag_Identity)//身份状态
- {//用户模式
- if(En_Standby)
- {//上锁的待机状态
- LED1=1;LED2=1;
- if(Admin_Info)
- {
- unsigned char i;
- OLED_Show_CHinese(0,CCInfo6,1);//显示说明文字:继电器已启用
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar4,1);//显示横线
- }
- OLED_Show_CHinese(4,CCText1,1);//显示说明文字:解锁由管理员初始
- }
- else
- {
- OLED_Display_Standby();//用户模式下,上锁时的待机显示
- }
-
- if(KeyScan()!=16&&En_Standby&&(!User_Locker))//如果在某一时刻ADC键盘有了输入并且用户没有锁定则继续探测
- {
- delay(5000);
- if(KeyScan()!=16&&En_Standby)
- {
- unsigned char i;
- User_Password_Putin[0]=KeyScan();//那么重新捕获这个值
- while(KeyScan()!=16);//等待按键松开
- OLED_Clear();//OLED清屏
- OLED_Display_Put_In_Password();//显示密码输入界面
- OLED_Show_sChar(0,6,sChar1,1);//显示*
- for(i=1;i<16;)//进入输密码的环节
- {
- if(KeyScan()!=16)
- {
- delay(5000);
- if(KeyScan()!=16)
- {
- User_Password_Putin[i]=KeyScan();//记录每一次输入的值
- OLED_Show_sChar(i*8,6,sChar1,1);//显示*
- i++;
- }
- while(KeyScan()!=16);//等待按键松开
- }
-
- if(KEY1==0||i==16)//如果确定键按下或输满16位
- {
- delay(5000);
- if(KEY1==0||i==16)
- {
- unsigned char k=0,t=0;
- Password_BKDRHASH_Calculation(User_Password_Putin,16);//对输入的值求HASH值,保存在hash_result数组中
-
- if(HASH_Compare())//密码正确
- {
- En_Standby=0;//不再是待机状态
- JDQ=1;//开启继电器
- OLED_Clear();
- OLED_Display_Right_Password();
- t1_cnt=0;
- TR1=1;//定时器1开始计时
- }
- else//密码错误
- {
- En_Standby=1;//仍在待机状态
- cnt_user_putin_wrong++;//错误计数增加一次
- if(cnt_user_putin_wrong==5)
- {
- User_Locker=1;//用户锁定有效
- cnt_user_putin_wrong=0;//但错误计数置0,这样一来在管理员模式下只需要关心用户锁定标志位即可
- }
- }
-
- for(k=0;k<16;k++)
- {
- User_Password_Putin[k]=0;//清空用户输入
- }
-
- HASH_Result_Clear();//清空哈希计算结果
- }
- while(!KEY1);
- OLED_Clear();//清屏,清屏放在此处可以使密码正确的提示信息在按键松开前一直显示
- goto A;//立即退出输入密码的环节
- }
-
- if(KEY2==0)//如果取消键按下
- {
- delay(5000);
- if(KEY2==0)
- {
- unsigned char j;
- for(j=0;j<16;j++)
- {
- User_Password_Putin[j]=0;//清空用户输入
- }
- OLED_Clear();//清屏
- HASH_Result_Clear();//清空哈希计算结果
- }
- while(!KEY2);
- goto A;//立即退出输入密码的环节
- }
- }
- A: _nop_();
- }
- }
-
- if(KEY1==0)//待机状态下KEY1是管理员入口开关
- {
- delay(8000);
- if(KEY1==0)
- {
- if(Hardware_Switch==0)
- {
- OLED_Clear();
- flag_Identity=0;
- }
- }
- while(!KEY1);
- }
- }
- else
- {//解锁的待机状态
- OLED_User_Mode();//用户模式菜单动态显示
- LED1=0;LED2=1;
- if(KEY1==0)//确定按键
- {
- delay(5000);
- if(KEY1==0)
- {
- switch(choose)
- {
- case 1:
- JDQ=0;//关闭继电器
- TR1=0;//定时器1停止计时
- TL1=0x00;//设置定时初值
- TH1=0x28;//设置定时初值
- t1_cnt=0;
- En_Standby=1;//重新回到上锁状态
- break;
- case 2:
- while(!KEY1);//等待按键松开,若不加此句可能导致Modify_User_Password()瞬间运行完,用户密码变为0
- choose=1;//重置菜单选择位
- TR1=0;//定时器1停止计时
- TL1=0x00;//设置定时初值
- TH1=0x28;//设置定时初值
- t1_cnt=0;
- Modify_User_Password();
- TR1=1;//定时器1开始计时
- break;
- }
- }
- while(!KEY1);
- OLED_Clear();
- }
-
- if(KEY2==0)//取消按键
- {
- delay(5000);
- if(KEY2==0)
- {
- choose=1;//重置菜单选择位
- JDQ=0;//关闭继电器
- TR1=0;//定时器1停止计时
- TL1=0x00;//设置定时初值
- TH1=0x28;//设置定时初值
- t1_cnt=0;
- En_Standby=1;//重新回到上锁状态
- }
- while(!KEY2);
- OLED_Clear();
- }
-
- if(_ReLock)//自动上锁判断
- {
- En_Standby=1;//重新回到上锁状态
- _ReLock=0;//重置标志位
- TR1=0;//关闭定时器1
- TL1=0x00;//设置定时初值
- TH1=0x28;//设置定时初值
- t1_cnt=0;//重置定时器1运行计数
- OLED_Clear();//此处的清屏使用户菜单在待机界面没有残留
- }
- }
- }
- else
- {//管理员状态确认
- if(Hardware_Switch==0)
- {//管理员模式
- if(En_Admin)//管理有效
- {
- OLED_Admin_Mode();//管理模式菜单动态显示
- LED1=1;LED2=0;
- if(KEY1==0)//确定按键
- {
- delay(5000);
- if(KEY1==0)
- {
- switch(choose)
- {
- case 1:
- User_Locker=0;//解除用户锁定
- break;
- case 2:
- while(!KEY1);//等待按键松开,若不加此句可能导致Modify_User_Password()瞬间运行完,用户密码变为0
- Modify_User_Password();
- break;
- case 3:
- while(!KEY1);//等待按键松开,若不加此句可能导致Modify_Admin_Password()瞬间运行完,管理密码变为0
- Modify_Admin_Password();
- break;
- case 4:
- OLED_Admin_onoff_Mode();//常开常关选项
- break;
- case 5:
- OLED_Display_System_Information();//显示版本信息
- break;
- case 6:
- En_Admin=0;//管理无效
- break;
- }
- }
- while(!KEY1);
- OLED_Clear();
- }
-
- if(KEY2==0)//取消按键
- {
- delay(5000);
- if(KEY2==0)
- {
- En_Admin=0;//管理无效
- }
- while(!KEY2);
- OLED_Clear();
- }
- }
- else//管理无效
- {
- OLED_Display_Administrator_Onload();
- LED1=1;LED2=1;
- if(KeyScan()!=16&&(!En_Admin))//如果在某一时刻ADC键盘有了输入
- {
- delay(5000);
- if(KeyScan()!=16&&(!En_Admin))
- {
- unsigned char i;
- Admin_Password_Putin[0]=KeyScan();//那么重新捕获这个值
- while(KeyScan()!=16);//等待按键松开
- OLED_Show_sChar(0,6,sChar1,1);//显示*
-
- for(i=1;i<16;)//进入输密码的环节,如果前面有对第一位密码的捕获操作,则此处的循环从1开始15次
- {
- if(KeyScan()!=16)
- {
- delay(5000);
- if(KeyScan()!=16)
- {
- Admin_Password_Putin[i]=KeyScan();//记录每一次输入的值
- OLED_Show_sChar(i*8,6,sChar1,1);//显示*
- i++;
- }
- while(KeyScan()!=16);//等待按键松开
- }
-
- if(KEY1==0||i==16)//如果确定键按下或输入位数满
- {
- delay(5000);
- if(KEY1==0||i==16)
- {
- unsigned char k=0,t=0;
- for(k=0;k<16;k++)
- {
- if(Admin_Password_Putin[k]==Administrator_Password[k])//核对明文密码
- {
- t++;//每有一个位置同,则t自增
- }
- }
-
- if(t==16)//密码正确
- {
- En_Admin=1;//管理有效
- }
- else//密码错误
- {
- En_Admin=0;//管理无效
- }
-
- for(k=0;k<16;k++)
- {
- Admin_Password_Putin[k]=0;//清空管理员输入
- }
- OLED_Clear();
- }
- while(!KEY1);
- goto B;//立即退出输入密码的环节
- }
-
- if(KEY2==0||Hardware_Switch==1)//如果取消键按下或硬件标志位被置1
- {
- delay(5000);
- if(KEY2==0||Hardware_Switch==1)
- {
- unsigned char j;
- for(j=0;j<16;j++)
- {
- Admin_Password_Putin[j]=0;//清空管理员输入
- }
- OLED_Clear();
- }
- while(!KEY2);
- goto B;//立即退出输入密码的环节
- }
- }
- }
- }
- B: _nop_();
- }
- }
- else//如果硬件标志位被置1
- {
- OLED_Clear();
- En_Admin=0;//管理无效
- choose=1;//由于管理模式菜单和用户模式共用一个选择项,并且菜单显示和choose有关,所以如果不重置菜单选中位,菜单长度的不同会导致用户显示的失败
- first_num=1;/*如果第一项菜单标号first_num改为全局变量,那么在此处将它置1可以保证每一次进入管理菜单是默认选中第一项*/
- flag_Identity=1;//返回用户状态
- }
- }
- }
- }
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
密码锁基本版 凌净清河.zip
(260.4 KB, 下载次数: 233)
|