|
本版本是第一版功能的延伸和扩展。配合B站上传的视频更佳。
B站搜索你从未见过的密码锁(第二版)(UP凌净清河)即可查到相关视频()。
视频有演示过程,有助于理解程序,强烈建议观看。
另外我建立了一个STC 51单片机初学者提升qq群,如果你想在单片机的道路上从菜鸟走到入门,欢迎加群和大家共同成长。群刚开始建立,人数尚少,内有资料不断完善中。群聊号码:873434536
特注:群不盈利、无广告、没有强制活动、没有潜规则,仅为个人兴趣和专业方向使然。
请先参阅第一版的说明:http://www.51hei.com/bbs/dpj-144690-1.html
声明:
0.第二版代码仍冗余,但仍然请大家在转载、分享时提及原作者,非常感谢
1.设计使用STC15W4K48S4制作,由于管理员密码存储在内部EEPROM中,故请勿使用IAP、IRC版本的单片机,否则会导致无法修改管理员密码
2.本版本已经可以作为课程设计使用了,但是仍然有斟酌的空间,下文将展示出功能上欠妥的部分,供使用者注意
3.设计目的是给密码锁课题的课设、毕设者提供一个完善的思路,可以看到在淘宝上目前还没有这样功能齐全,界面明了的密码锁。本设计若放在淘宝,有没有买的不敢说,但是按照功能的定价超过300是可以的,此处提供给大家免费使用,唯一要求是不要用于盈利(写给淘宝抄设计用来卖的家伙们,当然,我反正也管不了)。
4.注意两点:其一,首次下载先在初始化函数中清除掉管理员密码写入的语句注释符,编译写入后,将此语句注释后再次编译下载方可正常使用。仅首次,以后就再也不用如此操作了。其二,初次使用AT24C02是不能通过合法性检测的,锁会自动锁死,进入管理员菜单后先修改用户密码,再执行一次“立即解除锁定”,即可正常使用。
器件/功能清单:
1.本作品使用了如下模块(各模块的位定义见源代码):
2.OLED12864(SPI)
3.火焰探测模块(三线制)
4.BMP180温度气压传感模块(5线)
5.RC522射频卡识别模块
6.ADC键盘典型连接方式(STC手册上的典型电路)
7.DS1302,不带涓流充电(使用1N4148使电池单向供电)
8.AT24C02,硬件地址0xA0
9.继电器(JQC-3FF)
10.单片机采用STC15W4K48S4,使用到的片内资源有定时器0、定时器1、AD转换器、EEPROM等。
设计亮点:
1.使用OLED12864屏幕显示,具有用户菜单和管理员菜单,直观明了的设置使用流程(菜单未使用结构体或链表)
2.用户密码存储加密,使用BKDR哈希值计算并存储,防止从24C02中窃取密码
3.放弃传统的矩阵键盘,使用ADC键盘,连接上更加方便
4.如3项所示,密码为16进制,最大输入16位
5.对于添加了管理员密码的版本,使用内部EEPROM存储管理员密码(在本版本中,管理员密码明文存储)
6.添加新器件BMP180,用于显示温度和气压
7.添加新器件RC522,并且配有完整的设置菜单,其权限小于密码方式,开锁时间为5秒
8.添加新功能火焰探测,仅是提供一个接口或思路,用于特殊情况的开锁模式
9.修正了第一版中继电器的错误驱动方式,改成PNP驱动
版本缺陷:
1.关于设计针对的锁类型。因为射频卡的开锁有时长限制,所以可以看出该锁管理系统是针对可以自动开关的滑动门设计的,只是简化了门锁的模型和样式,换成继电器供直观显示
2.本版本中设定密码开锁后5秒自动关锁,这个在程序中可以修改,但是没有提供手动修改的接口,可以自行添加
3.对按键的消抖和判断部分仍然延续了第一版,因为好久之前的设计了,懒得改。按键按下会导致程序死循环,原因是仅仅使用了最简单的按键判断:即假设每个独立按键按下之后都会立即松开
4.采用的时间芯片为DS1302,有误差,可以自行改为DS3231
5.BMP180部分,即状态信息部分对数据的处理似乎有BUG,但是因为是第二版,也懒得改了
局限性:
1.RC522射频卡只判断了卡号,存储也是基于卡号的信息。所以,虽然原则上,某些银行卡、校园卡、公交卡都可以作为本设计射频卡部分的“钥匙”,但是也对安全造成了一定的威胁
2.采用的时间芯片支持时间不是到永远
3.AT24C02最大可以存储30张卡的信息,宏定义里面最大设置为30,要是换器件的话,驱动部分的器件地址和页写方式也要跟着换,记得注意
4.承上,AT24C02中数据搜索是按页枚举,效率很低,数量小倒也无所谓了,但是数量很多的话,势必影响效率
5.设计完全没有考虑到成本和功耗哟
LOCKER.C
- #include<STC15.H>
- #include<intrins.h>
- sbit LED1=P3^0;
- sbit LED2=P3^1;
- sbit KEY1=P3^2;
- sbit KEY2=P3^7;
- sbit KEY3=P2^1;
- sbit KEY4=P2^6;
- sbit JDQ=P0^0;//继电器引脚
- sbit OLED_CS=P1^3; //片选
- sbit OLED_RST=P1^5;//复位
- sbit OLED_DC=P1^4;//数据/命令控制
- sbit OLED_SCL=P1^7;//时钟 D0(SCLK)
- sbit OLED_SDIN=P1^6;//D1(MOSI) 数据
- sbit Hardware_Switch=P4^5;//管理员/用户硬件开关 用户:1 管理员:0
- sbit Fire_Sensor=P0^6;//火焰传感器位,有火焰为1,无火焰为0
- #include"DS1302_Driver.c"
- #include"BKDR_HASH_Fuction.c"
- #include"AT24C02_Driver.c"
- #include"OLED_Display.c"
- #include"Internal_EEPROM_Fuction.c"
- //运行数组
- unsigned char device_ID[4]={0x92,0x5A,0xA0,0xCA};
- 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 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
- bit En_Fire_Sensor=1;//火焰传感器允许位 有效:1 无效:0
- bit En_RFID=1;//射频卡读取允许位 有效:1 无效:0
- /*########################################################################################
- 设计名称:密码锁设计 第二版
- 设计者:清河
- 版本:A1.0
- 最后封装日期:2018-08-20
- 设备内置ID:0x925AA0CA
- 管理员初始密码010F(00000000)
- 平台:STC15W4K48S4
- 硬件部分
- 独立按键:共4个,用于进行各项调整
- ADC键盘:用于输入密码,本作品中可以输入16进制的密码,较平常10进制密码更加安全,只要程序和电路做相应的修改,也可以实现在AD可分辨的情况下上百的按键键位
- DS1302:配电池,实现断电走时,用于待机显示,如果在关机时取下电池或者替换DS1302则上电自动初始化
- LED指示灯:指示所处状态,本作品中进入用户模式则LED1亮,进入管理员模式则LED2亮
- AT24C02:实现断电密码记忆功能,用于记录用户密码的HASH值和注册的卡信息
- RC522:用于实现刷卡开锁
- 软件部分
- 使用定时器0实现对DS1302数据的定时读取,间隔50ms,以便更新当前的显示值
- 使用定时器1在用户解锁成功时定时上锁,设置的超时时间为5秒
- ########################################################################################*/
- 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;
- Password_BKDRHASH_Calculation(Admin_Password_Putin,16);
- for(k=0;k<16;k++)
- {
- Admin_Password_Putin[k]=0;//清空管理员输入,为后续输入做准备
- }
-
- if(Admin_HASH_Compare())//密码正确,可以进行修改密码的操作
- {
- 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_Putin,i,1);//显示输入的值
- if(KeyScan()!=16)
- {
- delay(5000);
- if(KeyScan()!=16)
- {
- Admin_Password_Putin[i]=KeyScan();//记录每一次输入的值
- i++;
- }
- while(KeyScan()!=16);//等待按键松开
- }
-
- if(KEY1==0||i==16)//如果确定键按下或输满16位
- {
- delay(5000);
- if(KEY1==0||i==16)
- {
- Password_BKDRHASH_Calculation(Admin_Password_Putin,16);//计算新管理员密码的HASH值
- IAP_Clear_Sector(IAP_ADDRESS);//在写入之前进行块擦除操作,否则可能写入失败
- Delay2ms();
- Save_Admin_Password();//保存新数据
- for(k=0;k<16;k++)
- {
- Admin_Password_Putin[k]=0;//清空管理员输入
- }
- }
- while(!KEY1);
- OLED_Clear();//清屏,清屏放在此处可以使密码正确的提示信息在按键松开前一直显示
- break;//立即退出输入密码的环节
- }
-
- if(KEY2==0)//如果取消键按下
- {
- delay(5000);
- if(KEY2==0)
- {
- for(k=0;k<16;k++)
- {
- Admin_Password_Putin[k]=0;//清空管理员输入
- }
- OLED_Clear();//清屏
- }
- while(!KEY2);
- break;//立即退出输入密码的环节
- }
- }
- }
- else//密码错误
- {
- 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;
- P2M1=0x00;
- P2M0=0x00;
- P3M1=0x00;
- P3M0=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()//系统预处理
- {
- Init_Determine();//DS1302上电自动初始化判断
- //IAP_Clear_Sector(IAP_ADDRESS);//首次下载对EEPROM擦除
- //Admin_Password_Init();//首次下载存入管理员预置密码
- OLED_Init();//初始化OLED
- OLED_Clear();//OLED清屏
- RFID_init();//射频卡初始化
- Init_BMP180();//BMP180初始化
- JDQ=1;
-
- //上电AT24C02检测
- AT24C02_Page_Read(0xA0,1);//读取用户模式密码的页
- for(t1_cnt=0;t1_cnt<4;t1_cnt++)//将t1_cnt作为临时计时变量
- {
- if(AT24C02_Read_Array[t1_cnt]!=device_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=0;//开启继电器
- OLED_Clear();
- OLED_Display_Right_Password();
- }
- 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);
- }
-
- if(En_RFID)
- {
- if(Card_Check())
- {
- unsigned char i;
- JDQ=0;//开启继电器
- OLED_Clear();
- TR1=1;
- while(!_ReLock)
- {
- OLED_Show_CHinese(0,CCTitle21,1);//显示标题:识别成功
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar4,1);//显示横线
- }
- OLED_Show_CHinese(6,CCInfo6,1);//显示说明文字:继电器已启用
- }
- OLED_Clear();
- _ReLock=0;//重置标志位
- TR1=0;//关闭定时器1
- TL1=0x00;//设置定时初值
- TH1=0x28;//设置定时初值
- t1_cnt=0;//重置定时器1运行计数
- }
- }
-
- if(En_Fire_Sensor==1&&Fire_Sensor==0)//如果火焰探测使能并且探测到火焰
- {
- delay(5000);
- if(En_Fire_Sensor==1&&Fire_Sensor==0)
- {
- unsigned char i;
- JDQ=0;//开启继电器
-
- /*此处显示报警提示信息*/
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle11,1);//显示标题:火焰探测
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar4,1);//显示横线
- }
- OLED_Show_CHinese(6,CCInfo6,1);//显示说明文字:继电器已启用
-
- while(1)
- {
- /*此处添加警报检查和解除函数*/
- if(KEY1==0||KEY2==0||KEY3==0||KEY4==0)//若有按键按下
- {
- delay(5000);
- if(KEY1==0||KEY2==0||KEY3==0||KEY4==0)
- {
- JDQ=1;//关闭继电器
- while(KEY1==0||KEY2==0||KEY3==0||KEY4==0);
- goto FIREQUTE;
- }
- }
- }
- FIREQUTE: OLED_Clear();//清屏
- }
- }
- }
- else
- {//解锁的待机状态
- OLED_User_Mode();//用户模式菜单动态显示
- LED1=0;LED2=1;
- if(KEY1==0)//确定按键
- {
- delay(5000);
- if(KEY1==0)
- {
- switch(choose)
- {
- case 1:
- JDQ=1;//关闭继电器
- 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=1;//关闭继电器
- 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_Admin_RFID_Mode();//射频卡开关选项
- break;
- case 6:
- Time_Set();//时间修改
- break;
- case 7:
- OLED_Display_System_Information();//显示状态信息
- break;
- case 8:
- OLED_Admin_firesensor_Mode();//火焰探测开关选项
- break;
- case 9://重置用户数据
- AT24C02_IIC_Format(0xFF);
- 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;
- Password_BKDRHASH_Calculation(Admin_Password_Putin,16);
-
- if(Admin_HASH_Compare())//密码正确
- {
- 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: if(KEY2==0)//取消按键,和置硬件标志位是一样的程序,简单复制过来的,成品可以删除
- {
- delay(5000);
- if(KEY2==0)
- {
- OLED_Clear();
- En_Admin=0;//管理无效
- choose=1;//由于管理模式菜单和用户模式共用一个选择项,并且菜单显示和choose有关,所以如果不重置菜单选中位,菜单长度的不同会导致用户显示的失败
- first_num=1;/*如果第一项菜单标号first_num改为全局变量,那么在此处将它置1可以保证每一次进入管理菜单是默认选中第一项*/
- flag_Identity=1;//返回用户状态
- }
- while(!KEY2);
- OLED_Clear();
- }
- }
- }
- else//如果硬件标志位被置1
- {
- OLED_Clear();
- En_Admin=0;//管理无效
- choose=1;//由于管理模式菜单和用户模式共用一个选择项,并且菜单显示和choose有关,所以如果不重置菜单选中位,菜单长度的不同会导致用户显示的失败
- first_num=1;/*如果第一项菜单标号first_num改为全局变量,那么在此处将它置1可以保证每一次进入管理菜单是默认选中第一项*/
- flag_Identity=1;//返回用户状态
- }
- }
- }
- }
- void GetTime() interrupt 1//使用定时器0每隔约50ms获取一次时间信息
- {
- TL0=(65536-50000)/256;//设置定时初值
- TH0=(65536-50000)%256;//设置定时初值
- Ds1302ReadTime();//读取DS1302时间信息
- time_procressing();//将读取到的时间转换为十进制数据,存放在time_trans数组中
- time_assign();//将得到的值放置在显示数组中
- }
- void ReLock() interrupt 3
- {
- TL1=0x00;//设置定时初值
- TH1=0x28;//设置定时初值
- t1_cnt++;
- if(t1_cnt==100)
- {
- _ReLock=1;//置标志位
- JDQ=1;//关闭继电器
- t1_cnt=0;
- }
- }
- void ADC_Routine() interrupt 5//中断发生证明AD转换的结束
- {
- ADC_CONTR&=!0x10;//清除ADC中断标志,例程
- ADC_DATA=ADC_RES*4+ADC_RESL;
- if(ADC_DATA<90&&ADC_DATA>50)
- ADC_value=0;
- else if(ADC_DATA<150&&ADC_DATA>112)
- ADC_value=1;
- else if(ADC_DATA<220&&ADC_DATA>176)
- ADC_value=2;
- else if(ADC_DATA<290&&ADC_DATA>220)
- ADC_value=3;
- else if(ADC_DATA<370&&ADC_DATA>304)
- ADC_value=4;
- else if(ADC_DATA<400&&ADC_DATA>368)
- ADC_value=5;
- else if(ADC_DATA<464&&ADC_DATA>432)
- ADC_value=6;
- else if(ADC_DATA<528&&ADC_DATA>496)
- ADC_value=7;
- else if(ADC_DATA<592&&ADC_DATA>560)
- ADC_value=8;
- else if(ADC_DATA<656&&ADC_DATA>624)
- ADC_value=9;
- else if(ADC_DATA<720&&ADC_DATA>688)
- ADC_value=10;
- else if(ADC_DATA<784&&ADC_DATA>752)
- ADC_value=11;
- else if(ADC_DATA<848&&ADC_DATA>816)
- ADC_value=12;
- else if(ADC_DATA<912&&ADC_DATA>880)
- ADC_value=13;
- else if(ADC_DATA<976&&ADC_DATA>944)
- ADC_value=14;
- else if(ADC_DATA<1024&&ADC_DATA>1007)
- ADC_value=15;
- else ADC_value=16;
- }
复制代码 OLED_DISPLAY.C(和显示有关的功能函数)
- /*
- 此文件中将来自OLED_Fuction.c中的显示函数按程序状态封装,调用时更新特定显示
- */
- #include"OLED_Fuction.c"
- #include"RFID_Fuction.c"
- #include"BMP180_Fuction.c"
- extern unsigned char display_hour[];
- extern unsigned char display_minute[];
- extern unsigned char display_month[];
- extern unsigned char display_day[];
- extern unsigned char display_year[];
- extern unsigned char display_second[];
- extern unsigned char display_week;
- extern unsigned char Space_State[4];
- extern long BMP180_Temperature;
- extern long BMP180_Pressure;
- extern unsigned char choose;
- extern unsigned char first_num;
- extern bit User_Locker;
- extern bit Admin_Info;
- extern bit En_Fire_Sensor;
- extern bit En_RFID;
- void OLED_Admin_RFID_Manage(void);
- void delay2(unsigned int cnt)//调用该函数进行一段时间的延时
- {
- while(cnt--);
- }
- /*####################################################用户状态函数##############################################*/
- void OLED_Display_Standby()//待机状态,显示定时器0获取的时间或通知已锁信息
- {
- unsigned char i;
- OLED_Show_CHinese(0,CCTitle1,1);//显示标题:当前已锁
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar3,1);//显示横线
- }
- OLED_Show_Number(8,4,display_year,4,1);
- OLED_Show_cChar(40,4,cChar1,1);//年
- OLED_Show_Number(56,4,display_month,2,1);
- OLED_Show_cChar(72,4,cChar2,1);//月
- OLED_Show_Number(88,4,display_day,2,1);
- OLED_Show_cChar(104,4,cChar3,1);//日
- OLED_Show_Number(32,6,display_hour,2,1);
- OLED_Show_sChar(48,6,sChar2,1);//:
- OLED_Show_Number(56,6,display_minute,2,1);
- OLED_Show_sChar(72,6,sChar2,1);//:
- OLED_Show_Number(80,6,display_second,2,1);
- }
- void OLED_Display_Put_In_Password()//用户模式下输入密码的静态显示
- {
- unsigned char i;
- OLED_Show_CHinese(0,CCTitle1,1);//显示标题:当前已锁
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar4,1);//显示横线
- }
- OLED_Show_CHinese(4,CCInfo1,1);//显示说明文字:请输入密码:
- }
- void OLED_Display_Right_Password()//用户模式下输入密码正确的静态提示信息
- {
- unsigned char i;
- OLED_Show_CHinese(0,CCTitle3,1);//显示标题:密码正确
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar4,1);//显示横线
- }
- OLED_Show_CHinese(6,CCInfo6,1);//显示说明文字:继电器已启用
- }
- void OLED_User_Mode()//用户模式菜单动态显示,因为容量小于等于3个,一屏可以放得下,所以不加滚屏功能,仅在两个选项中跳动
- {
- OLED_Show_CHinese(0,CCTitle4,0);//显示标题:用户模式
- switch(choose)
- {
- case 1:OLED_Show_CHinese(2,CCList_user_1,0);OLED_Show_CHinese(4,CCList_user_2,1);break;
- case 2:OLED_Show_CHinese(2,CCList_user_1,1);OLED_Show_CHinese(4,CCList_user_2,0);break;
- }
-
- if(KEY3==0)//上调按键
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//选项最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下调按键
- {
- delay2(5000);
- if(KEY4==0)
- {
- choose++;
- if(choose==3)choose=2;//选项最大不能大于2
- }
- while(!KEY4);
- }
- }
- /*######################################################管理员状态函数############################################*/
- void OLED_Display_Administrator_Onload()//管理员登入静态显示
- {
- unsigned char i;
- OLED_Show_CHinese(0,CCTitle5,1);//显示标题:管理模式
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar5,1);//显示横线
- }
- OLED_Show_CHinese(4,CCInfo3,1);//显示说明文字:请输入口令:
- }
- void OLED_Display_Menu(unsigned char menu_num,unsigned char choose)
- {//定制的菜单显示接口函数,用于将菜单变量名和调用它的变量值连接起来,需要知道显示的起始菜单号和当前选中的菜单
- switch(menu_num)
- {
- case 1:
- OLED_Show_CHinese(2,CCList_admin_1,!(choose==1));
- OLED_Show_CHinese(4,CCList_admin_2,!(choose==2));
- OLED_Show_CHinese(6,CCList_admin_3,!(choose==3));
- break;
- case 2:
- OLED_Show_CHinese(2,CCList_admin_2,!(choose==2));
- OLED_Show_CHinese(4,CCList_admin_3,!(choose==3));
- OLED_Show_CHinese(6,CCList_admin_4,!(choose==4));
- break;
- case 3:
- OLED_Show_CHinese(2,CCList_admin_3,!(choose==3));
- OLED_Show_CHinese(4,CCList_admin_4,!(choose==4));
- OLED_Show_CHinese(6,CCList_admin_5,!(choose==5));
- break;
- case 4:
- OLED_Show_CHinese(2,CCList_admin_4,!(choose==4));
- OLED_Show_CHinese(4,CCList_admin_5,!(choose==5));
- OLED_Show_CHinese(6,CCList_admin_6,!(choose==6));
- break;
- case 5:
- OLED_Show_CHinese(2,CCList_admin_5,!(choose==5));
- OLED_Show_CHinese(4,CCList_admin_6,!(choose==6));
- OLED_Show_CHinese(6,CCList_admin_7,!(choose==7));
- break;
- case 6:
- OLED_Show_CHinese(2,CCList_admin_6,!(choose==6));
- OLED_Show_CHinese(4,CCList_admin_7,!(choose==7));
- OLED_Show_CHinese(6,CCList_admin_8,!(choose==8));
- break;
- case 7:
- OLED_Show_CHinese(2,CCList_admin_7,!(choose==7));
- OLED_Show_CHinese(4,CCList_admin_8,!(choose==8));
- OLED_Show_CHinese(6,CCList_admin_9,!(choose==9));
- break;
- }
- }
- void OLED_Admin_Mode()//管理模式菜单动态显示
- {
- //static unsigned char first_num=1;//第一项菜单标号
- OLED_Show_CHinese(0,CCTitle5,0);//显示标题:管理模式
-
- OLED_Display_Menu(first_num,choose);//根据first_num和choose的动态刷新显示函数
-
- if(KEY3==0)//上调按键
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//选项最少不能小于1
- if(choose<first_num)first_num--;
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下调按键
- {
- delay2(5000);
- if(KEY4==0)
- {
- choose++;
- if(choose==10)choose=9;//选项最大不能大于9
- if(choose>first_num+2)first_num++;
- }
- while(!KEY4);
- }
- }
- void OLED_Admin_onoff_Mode()//常开常关选项,因为容量小于等于3个,一屏可以放得下,所以不加滚屏功能,仅在两个选项中跳动
- {
- unsigned char choose_possition;//用于存放进入此级菜单时上一级choose的值
- choose_possition=choose;
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle9,0);//显示标题:开关选项
- while(!KEY1);//等待按键松开
- choose=1;
-
- while(1)
- {
- switch(choose)
- {
- case 1:OLED_Show_CHinese(2,CCList_onoff_1,0);OLED_Show_CHinese(4,CCList_onoff_2,1);break;
- case 2:OLED_Show_CHinese(2,CCList_onoff_1,1);OLED_Show_CHinese(4,CCList_onoff_2,0);break;
- }
-
- if(KEY1==0)//确定按键
- {
- delay2(5000);
- if(KEY1==0)
- {
- switch(choose)
- {
- case 1:
- JDQ=0;//开启继电器,由于继电器所在接口的位定义不再此文件中,故直接使用单片机头文件中的IO口定义
- User_Locker=1;//用户锁定
- Admin_Info=1;//管理员开锁通知开,该提示信息在用户代码处修改
- break;
- case 2:
- JDQ=1;//开启继电器,由于继电器所在接口的位定义不再此文件中,故直接使用单片机头文件中的IO口定义
- User_Locker=0;//用户解锁
- Admin_Info=0;//管理员开锁通知关,该提示信息在用户代码处修改
- break;
- }
- }
- while(!KEY1);
- OLED_Clear();
- goto OUT2;
- }
-
- if(KEY2==0)//取消按键
- {
- delay2(5000);
- if(KEY2==0)
- {
- choose=1;//重置菜单选择位
- }
- while(!KEY2);
- OLED_Clear();
- goto OUT2;
- }
-
- if(KEY3==0)//上调按键
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//选项最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下调按键
- {
- delay2(5000);
- if(KEY4==0)
- {
- choose++;
- if(choose==3)choose=2;//选项最大不能大于2
- }
- while(!KEY4);
- }
- }
- OUT2:choose=choose_possition;//将之前存储的值还给choose以保证上级菜单不出现错乱
- }
- void OLED_Admin_firesensor_Mode()//火焰探测器开关选项,因为容量小于等于3个,一屏可以放得下,所以不加滚屏功能,仅在两个选项中跳动
- {
- unsigned char choose_possition;//用于存放进入此级菜单时上一级choose的值
- choose_possition=choose;
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle11,0);//显示标题:火焰探测
- while(!KEY1);//等待按键松开
- choose=1;
-
- while(1)
- {
- switch(choose)
- {
- case 1:OLED_Show_CHinese(2,CCList_firesensor_1,0);OLED_Show_CHinese(4,CCList_firesensor_2,1);break;
- case 2:OLED_Show_CHinese(2,CCList_firesensor_1,1);OLED_Show_CHinese(4,CCList_firesensor_2,0);break;
- }
-
- if(KEY1==0)//确定按键
- {
- delay2(5000);
- if(KEY1==0)
- {
- switch(choose)
- {
- case 1:
- En_Fire_Sensor=0;//关闭火焰探测器使能位
- break;
- case 2:
- En_Fire_Sensor=1;//使能火焰探测器
- break;
- }
- }
- while(!KEY1);
- OLED_Clear();
- goto FSMENUQUIT;
- }
-
- if(KEY2==0)//取消按键
- {
- delay2(5000);
- if(KEY2==0)
- {
- choose=1;//重置菜单选择位
- }
- while(!KEY2);
- OLED_Clear();
- goto FSMENUQUIT;
- }
-
- if(KEY3==0)//上调按键
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//选项最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下调按键
- {
- delay2(5000);
- if(KEY4==0)
- {
- choose++;
- if(choose==3)choose=2;//选项最大不能大于2
- }
- while(!KEY4);
- }
- }
- FSMENUQUIT:choose=choose_possition;//将之前存储的值还给choose以保证上级菜单不出现错乱
- }
- void OLED_Admin_RFID_Mode()//RFID选项,因为容量小于等于3个,一屏可以放得下,所以不加滚屏功能,仅在3个选项中跳动
- {
- unsigned char choose_possition;//用于存放进入此级菜单时上一级choose的值
- choose_possition=choose;
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle14,0);//显示标题:RFID
- while(!KEY1);//等待按键松开
- choose=1;
-
- while(1)
- {
- switch(choose)
- {
- case 1:OLED_Show_CHinese(2,CCList_RFID_1,0);OLED_Show_CHinese(4,CCList_RFID_2,1);OLED_Show_CHinese(6,CCList_RFID_3,1);break;
- case 2:OLED_Show_CHinese(2,CCList_RFID_1,1);OLED_Show_CHinese(4,CCList_RFID_2,0);OLED_Show_CHinese(6,CCList_RFID_3,1);break;
- case 3:OLED_Show_CHinese(2,CCList_RFID_1,1);OLED_Show_CHinese(4,CCList_RFID_2,1);OLED_Show_CHinese(6,CCList_RFID_3,0);break;
- }
-
- if(KEY1==0)//确定按键
- {
- delay2(5000);
- if(KEY1==0)
- {
- switch(choose)
- {
- case 1:
- En_RFID=0;//关闭射频卡模块使能位
- break;
- case 2:
- En_RFID=1;//使能射频卡模块
- break;
- case 3:
- OLED_Admin_RFID_Manage();
- break;
- }
- }
- while(!KEY1);
- if(choose!=3)
- {
- goto RFIDQUIT;
- }
- else
- {
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle14,0);//显示标题:RFID
- }
- }
-
- if(KEY2==0)//取消按键
- {
- delay2(5000);
- if(KEY2==0)
- {
- choose=1;//重置菜单选择位
- }
- while(!KEY2);
- OLED_Clear();
- goto RFIDQUIT;
- }
-
- if(KEY3==0)//上调按键
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//选项最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下调按键
- {
- delay2(5000);
- if(KEY4==0)
- {
- choose++;
- if(choose==4)choose=3;//选项最大不能大于3
- }
- while(!KEY4);
- }
- }
- RFIDQUIT:choose=choose_possition;//将之前存储的值还给choose以保证上级菜单不出现错乱
- }
- void OLED_Admin_RFID_Manage()//射频管理选项,因为容量小于等于3个,一屏可以放得下,所以不加滚屏功能,仅在3个选项中跳动
- {
- unsigned char choose_manage;//新建一个临时选项变量,与上两层目录无关
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle15,0);//显示标题:管理RFID
- while(!KEY1);//等待按键松开
- choose_manage=1;
-
- while(1)
- {
- switch(choose_manage)
- {
- case 1:
- OLED_Show_CHinese(2,CCList_admin_RFID_1,0);
- OLED_Show_CHinese(4,CCList_admin_RFID_2,1);
- OLED_Show_CHinese(6,CCList_admin_RFID_3,1);break;
- case 2:
- OLED_Show_CHinese(2,CCList_admin_RFID_1,1);
- OLED_Show_CHinese(4,CCList_admin_RFID_2,0);
- OLED_Show_CHinese(6,CCList_admin_RFID_3,1);break;
- case 3:
- OLED_Show_CHinese(2,CCList_admin_RFID_1,1);
- OLED_Show_CHinese(4,CCList_admin_RFID_2,1);
- OLED_Show_CHinese(6,CCList_admin_RFID_3,0);break;
- }
-
- if(KEY1==0)//确定按键
- {
- delay2(5000);
- if(KEY1==0)
- {
- switch(choose_manage)
- {
- case 1:
- /*添加卡函数*/
- Card_Add();
- break;
- case 2:
- /*删除卡函数*/
- Card_Delete();
- break;
- case 3:
- /*对比卡函数*/
- Card_Compare();
- break;
- }
- }
- while(!KEY1);
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle14,0);//显示标题:RFID
- }
-
- if(KEY2==0)//取消按键
- {
- delay2(5000);
- if(KEY2==0)
- {
- choose_manage=1;//重置菜单选择位
- }
- while(!KEY2);
- OLED_Clear();
- goto RFIDMQUIT;
- }
-
- if(KEY3==0)//上调按键
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose_manage--;
- if(choose_manage==0)choose_manage=1;//选项最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下调按键
- {
- delay2(5000);
- if(KEY4==0)
- {
- choose_manage++;
- if(choose_manage==4)choose_manage=3;//选项最大不能大于3
- }
- while(!KEY4);
- }
- }
- RFIDMQUIT: _nop_();
- }
- void OLED_Display_System_Information()//显示BMP180传回的温度气压信息
- {
- unsigned char i;
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle10,1);//显示标题:状态信息
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar4,1);//显示横线
- }
-
- /*在此添加存储容量检测*/
- Storage_Check();
- OLED_Show_cChar(0,4,cChar10,1);//卡
- OLED_Show_cChar(16,4,cChar11,1);//存
- OLED_Show_cChar(32,4,cChar12,1);//储
- OLED_Show_cChar(48,4,cChar8,1);//:
- OLED_Show_sChar(96,4,sChar13,1);///
- OLED_Show_One_Number(80,4,Space_State[0],1);
- OLED_Show_One_Number(88,4,Space_State[1],1);
- OLED_Show_One_Number(104,4,Space_State[2],1);
- OLED_Show_One_Number(112,4,Space_State[3],1);
-
- while(!KEY1);//等待按键松开
-
- while(1)
- {
- /*在此添加温度气压扫描显示函数*/
- BMP180_Calculate();
- OLED_Show_sChar(0,6,sChar9,1);//T
- OLED_Show_sChar(8,6,sChar8,1);//P
- OLED_Show_sChar(16,6,sChar2,1);//:
- OLED_Show_sChar(40,6,sChar11,1);//.
- OLED_Show_sChar(56,6,sChar12,1);//°
- OLED_Show_sChar(64,6,sChar10,1);//C
- OLED_Show_sChar(96,6,sChar11,1);//.
- OLED_Show_sChar(112,6,sChar6,1);//K
- OLED_Show_sChar(120,6,sChar7,1);//p
-
- OLED_Show_One_Number(24,6,BMP180_Temperature/100,1);
- OLED_Show_One_Number(32,6,BMP180_Temperature%100/10,1);
- OLED_Show_One_Number(48,6,BMP180_Temperature%10,1);
-
- if((BMP180_Pressure/100000)!=0)
- {
- OLED_Show_One_Number(72,6,BMP180_Pressure/100000,1);
- }
- OLED_Show_One_Number(80,6,BMP180_Pressure%100000/10000,1);
- OLED_Show_One_Number(88,6,BMP180_Pressure%10000/1000,1);
- OLED_Show_One_Number(104,6,BMP180_Pressure%1000/100,1);
-
- if(KEY1==0)//确定按键
- {
- delay2(5000);
- if(KEY1==0)
- {
- _nop_();
- }
- while(!KEY1);//由于按键只起到返回的作用,此处也可以将第二次if判断去掉,仅使用while判断,但为了整体规范性,就不在意那几个时钟了
- OLED_Clear();
- goto OUT3;
- }
-
- if(KEY2==0)//取消按键
- {
- delay2(5000);
- if(KEY2==0)
- {
- _nop_();
- }
- while(!KEY2);//由于按键只起到返回的作用,此处也可以将第二次if判断去掉,仅使用while判断,但为了整体规范性,就不在意那几个时钟了
- OLED_Clear();
- goto OUT3;
- }
- }
- OUT3:_nop_();
- }
- void Time_Set()//时间修改函数
- {
- bit en_data=1;//数据合法标志位,表示数据检查时的合法:1/不合法:0判断结果
- unsigned char i,choose=1,year_temp;
- unsigned char set_clock[6];
- unsigned char set_date[8];
-
- set_date[0]=display_year[0];
- set_date[1]=display_year[1];
- set_date[2]=display_year[2];
- set_date[3]=display_year[3];
- set_date[4]=display_month[0];
- set_date[5]=display_month[1];
- set_date[6]=display_day[0];
- set_date[7]=display_day[1];
-
- set_clock[0]=display_hour[0];
- set_clock[1]=display_hour[1];
- set_clock[2]=display_minute[0];
- set_clock[3]=display_minute[1];
- set_clock[4]=display_second[0];
- set_clock[5]=display_second[1];//复制运行数组,取待显示每一位
-
-
- /*第一部分,日期设置*/
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle13,1);//显示标题:时间修改
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar4,1);//显示横线
- }
- OLED_Show_CHinese(4,CCInfo7,1);//显示说明文字:请输入年月日:
- while(!KEY1);//确认进入该函数时的按键已经松开
- while(1)
- {
- OLED_DateSet_Display(set_date,choose);//刷新显示时间设置数组,该数组保存设置的时间(按位)
-
- if(KeyScan()<10)//如果在此时有键盘按键按下则更改当前位的值
- {
- delay2(5000);
- if(KeyScan()<10)
- {
- set_date[choose-1]=KeyScan();
- }
- while(KeyScan()!=16);//等待按键松开
- choose++;
- if(choose==9)choose=8;//选项最大不能大于8
- }
-
- if(KEY1==0)//确定按键
- {
- delay2(5000);
- if(KEY1==0)
- {
- _nop_();
- }
- while(!KEY1);
- goto TSB;//跳出当前循环,进入下一循环时间设置
- }
-
- if(KEY2==0)//取消按键,直接退出时间设置函数
- {
- delay2(5000);
- if(KEY2==0)
- {
- _nop_();
- }
- while(!KEY2);
- OLED_Clear();
- goto TIMESETOUT;
- }
-
- if(KEY3==0)//上调按键
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//选项最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下调按键
- {
- delay2(5000);
- if(KEY4==0)
- {
- choose++;
- if(choose==9)choose=8;//选项最大不能大于8
- }
- while(!KEY4);
- }
- }
-
- /*第二部分,时间设置*/
- TSB: choose=1;//重置显示位标志
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle13,1);//显示标题:时间修改
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar4,1);//显示横线
- }
- OLED_Show_CHinese(4,CCInfo8,1);//显示说明文字:请输入时钟:
- while(1)
- {
- OLED_TimeSet_Display(set_clock,choose);//刷新显示时间设置数组,该数组保存设置的时间(按位)
-
- if(KeyScan()<10)//如果在此时有键盘按键按下则更改当前位的值
- {
- delay2(5000);
- if(KeyScan()<10)
- {
- set_clock[choose-1]=KeyScan();
- }
- while(KeyScan()!=16);//等待按键松开
- choose++;
- if(choose==7)choose=6;//选项最大不能大于6
- }
-
- if(KEY1==0)//确定按键
- {
- delay2(5000);
- if(KEY1==0)
- {
- _nop_();
- }
- while(!KEY1);
- goto TSC;//跳出当前循环,进入第三部分
- }
-
- if(KEY2==0)//取消按键,直接退出时间设置函数
- {
- delay2(5000);
- if(KEY2==0)
- {
- _nop_();
- }
- while(!KEY2);
- OLED_Clear();
- goto TIMESETOUT;
- }
-
- if(KEY3==0)//上调按键
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//选项最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下调按键
- {
- delay2(5000);
- if(KEY4==0)
- {
- choose++;
- if(choose==7)choose=6;//选项最大不能大于6
- }
- while(!KEY4);
- }
- }
-
- /*第三部分,拼接判断和写入*/
- TSC:if((set_clock[0]*10+set_clock[1])>24||set_clock[0]>2)//对小时的判断
- {
- en_data=0;
- }
- else
- {
- if(set_clock[0]==2&&set_clock[1]>4)
- {
- en_data=0;
- }
- }
- if((set_clock[2]*10+set_clock[3])>60||set_clock[2]>5)//对分钟的判断
- {
- en_data=0;
- }
- if((set_clock[4]*10+set_clock[5])>60||set_clock[4]>5)//对秒的判断
- {
- en_data=0;
- }
-
- if((set_date[4]*10+set_date[5])>12||set_date[4]>1)//对月份的判断
- {
- en_data=0;
- }
- else
- {
- if(set_date[4]==1&&set_date[5]>2)
- {
- en_data=0;
- }
- if(set_date[4]==0&&set_date[5]==0)
- {
- en_data=0;
- }
- }
- if((set_date[6]*10+set_date[7])>31||set_date[6]>3)//对日子的判断。注意,由于闰年的存在,若出现闰年输入2.29这样的情况会在输入完年份后判断退出
- {
- en_data=0;
- }
-
- if(set_date[0]!=2||set_date[1]!=0)
- {
- en_data=0;
- }
-
- year_temp=set_date[0]*1000+set_date[1]*100+set_date[2]*10+set_date[3];
- if(!Leap(year_temp))//如果不是闰年
- {
- if(set_date[4]==0&&set_date[5]==2&&set_date[6]==2&&set_date[7]==9)//对2.29作出判断
- {
- en_data=0;
- }
- }
-
- if(en_data)
- {
- /*拼接写入数组*/
- time_transmission(set_date,set_clock);
-
- /*写入新时间*/
- TimeReset();
-
- /*提示成功信息*/
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle13,1);//显示标题:时间修改
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar4,1);//显示横线
- }
- OLED_Show_CHinese(4,CCInfo15,1);//显示说明文字:修改成功
- /*按键循环*/
- while(1)
- {
- if(KEY1==0)//确定按键
- {
- delay2(5000);
- if(KEY1==0)
- {
- _nop_();
- }
- while(!KEY1);
- OLED_Clear();
- goto TIMESETOUT;
- }
-
- if(KEY2==0)//取消按键
- {
- delay2(5000);
- if(KEY2==0)
- {
- _nop_();
- }
- while(!KEY2);
- OLED_Clear();
- goto TIMESETOUT;
- }
- }
- }
- else
- {
- /*提示失败信息*/
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle13,1);//显示标题:时间修改
- for(i=0;i<16;i++)
- {
- OLED_Show_sChar(i*8,2,sChar4,1);//显示横线
- }
- OLED_Show_CHinese(4,CCInfo16,1);//显示说明文字:输入不合规则
- /*按键循环*/
- while(1)
- {
- if(KEY1==0)//确定按键
- {
- delay2(5000);
- if(KEY1==0)
- {
- _nop_();
- }
- while(!KEY1);
- OLED_Clear();
- goto TIMESETOUT;
- }
-
- if(KEY2==0)//取消按键
- {
- delay2(5000);
- if(KEY2==0)
- {
- _nop_();
- }
- while(!KEY2);
- OLED_Clear();
- goto TIMESETOUT;
- }
- }
- }
- TIMESETOUT: _nop_();
- }
复制代码
对于下载限制的说明:
由于是我个人的设计,我认为在黑币上应该有一个价格,该作品也值得这个价格。
对于下载身份限制的说明:
当然要向着站内的人了~
密码锁第二版 凌净清河.zip
(247.84 KB, 下载次数: 216)
密码锁(第二版)说明文档.pdf
(286.06 KB, 下载次数: 171)
好希望你们能够回复我呀,回复这个帖子能给我带来不少鼓励呢!
|
评分
-
查看全部评分
|