|
本版本是第一版功能的延伸和擴展。配合B站上傳的視頻更佳。
B站搜索你從未見過的密碼鎖(第二版)(UP凌凈清河)即可查到相關(guān)視頻()。
視頻有演示過程,有助于理解程序,強烈建議觀看。
另外我建立了一個STC 51單片機初學者提升qq群,如果你想在單片機的道路上從菜鳥走到入門,歡迎加群和大家共同成長。群剛開始建立,人數(shù)尚少,內(nèi)有資料不斷完善中。群聊號碼:873434536
特注:群不盈利、無廣告、沒有強制活動、沒有潛規(guī)則,僅為個人興趣和專業(yè)方向使然。
請先參閱第一版的說明:http://www.torrancerestoration.com/bbs/dpj-144690-1.html
聲明:
0.第二版代碼仍冗余,但仍然請大家在轉(zhuǎn)載、分享時提及原作者,非常感謝
1.設(shè)計使用STC15W4K48S4制作,由于管理員密碼存儲在內(nèi)部EEPROM中,故請勿使用IAP、IRC版本的單片機,否則會導(dǎo)致無法修改管理員密碼
2.本版本已經(jīng)可以作為課程設(shè)計使用了,但是仍然有斟酌的空間,下文將展示出功能上欠妥的部分,供使用者注意
3.設(shè)計目的是給密碼鎖課題的課設(shè)、畢設(shè)者提供一個完善的思路,可以看到在淘寶上目前還沒有這樣功能齊全,界面明了的密碼鎖。本設(shè)計若放在淘寶,有沒有買的不敢說,但是按照功能的定價超過300是可以的,此處提供給大家免費使用,唯一要求是不要用于盈利(寫給淘寶抄設(shè)計用來賣的家伙們,當然,我反正也管不了)。
4.注意兩點:其一,首次下載先在初始化函數(shù)中清除掉管理員密碼寫入的語句注釋符,編譯寫入后,將此語句注釋后再次編譯下載方可正常使用。僅首次,以后就再也不用如此操作了。其二,初次使用AT24C02是不能通過合法性檢測的,鎖會自動鎖死,進入管理員菜單后先修改用戶密碼,再執(zhí)行一次“立即解除鎖定”,即可正常使用。
器件/功能清單:
1.本作品使用了如下模塊(各模塊的位定義見源代碼):
2.OLED12864(SPI)
3.火焰探測模塊(三線制)
4.BMP180溫度氣壓傳感模塊(5線)
5.RC522射頻卡識別模塊
6.ADC鍵盤典型連接方式(STC手冊上的典型電路)
7.DS1302,不帶涓流充電(使用1N4148使電池單向供電)
8.AT24C02,硬件地址0xA0
9.繼電器(JQC-3FF)
10.單片機采用STC15W4K48S4,使用到的片內(nèi)資源有定時器0、定時器1、AD轉(zhuǎn)換器、EEPROM等。
設(shè)計亮點:
1.使用OLED12864屏幕顯示,具有用戶菜單和管理員菜單,直觀明了的設(shè)置使用流程(菜單未使用結(jié)構(gòu)體或鏈表)
2.用戶密碼存儲加密,使用BKDR哈希值計算并存儲,防止從24C02中竊取密碼
3.放棄傳統(tǒng)的矩陣鍵盤,使用ADC鍵盤,連接上更加方便
4.如3項所示,密碼為16進制,最大輸入16位
5.對于添加了管理員密碼的版本,使用內(nèi)部EEPROM存儲管理員密碼(在本版本中,管理員密碼明文存儲)
6.添加新器件BMP180,用于顯示溫度和氣壓
7.添加新器件RC522,并且配有完整的設(shè)置菜單,其權(quán)限小于密碼方式,開鎖時間為5秒
8.添加新功能火焰探測,僅是提供一個接口或思路,用于特殊情況的開鎖模式
9.修正了第一版中繼電器的錯誤驅(qū)動方式,改成PNP驅(qū)動
版本缺陷:
1.關(guān)于設(shè)計針對的鎖類型。因為射頻卡的開鎖有時長限制,所以可以看出該鎖管理系統(tǒng)是針對可以自動開關(guān)的滑動門設(shè)計的,只是簡化了門鎖的模型和樣式,換成繼電器供直觀顯示
2.本版本中設(shè)定密碼開鎖后5秒自動關(guān)鎖,這個在程序中可以修改,但是沒有提供手動修改的接口,可以自行添加
3.對按鍵的消抖和判斷部分仍然延續(xù)了第一版,因為好久之前的設(shè)計了,懶得改。按鍵按下會導(dǎo)致程序死循環(huán),原因是僅僅使用了最簡單的按鍵判斷:即假設(shè)每個獨立按鍵按下之后都會立即松開
4.采用的時間芯片為DS1302,有誤差,可以自行改為DS3231
5.BMP180部分,即狀態(tài)信息部分對數(shù)據(jù)的處理似乎有BUG,但是因為是第二版,也懶得改了
局限性:
1.RC522射頻卡只判斷了卡號,存儲也是基于卡號的信息。所以,雖然原則上,某些銀行卡、校園卡、公交卡都可以作為本設(shè)計射頻卡部分的“鑰匙”,但是也對安全造成了一定的威脅
2.采用的時間芯片支持時間不是到永遠
3.AT24C02最大可以存儲30張卡的信息,宏定義里面最大設(shè)置為30,要是換器件的話,驅(qū)動部分的器件地址和頁寫方式也要跟著換,記得注意
4.承上,AT24C02中數(shù)據(jù)搜索是按頁枚舉,效率很低,數(shù)量小倒也無所謂了,但是數(shù)量很多的話,勢必影響效率
5.設(shè)計完全沒有考慮到成本和功耗喲
IMG_20190107_150000.jpg (3.44 MB, 下載次數(shù): 151)
下載附件
2019-1-7 15:01 上傳
IMG_20190107_150022.jpg (3.31 MB, 下載次數(shù): 164)
下載附件
2019-1-7 15:01 上傳
IMG_20190107_150036.jpg (3.9 MB, 下載次數(shù): 139)
下載附件
2019-1-7 15:01 上傳
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;//復(fù)位
- sbit OLED_DC=P1^4;//數(shù)據(jù)/命令控制
- sbit OLED_SCL=P1^7;//時鐘 D0(SCLK)
- sbit OLED_SDIN=P1^6;//D1(MOSI) 數(shù)據(jù)
- sbit Hardware_Switch=P4^5;//管理員/用戶硬件開關(guān) 用戶:1 管理員:0
- sbit Fire_Sensor=P0^6;//火焰?zhèn)鞲衅魑�,有火焰�?,無火焰為0
- #include"DS1302_Driver.c"
- #include"BKDR_HASH_Fuction.c"
- #include"AT24C02_Driver.c"
- #include"OLED_Display.c"
- #include"Internal_EEPROM_Fuction.c"
- //運行數(shù)組
- 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};//管理員密碼存放數(shù)組,作為預(yù)設(shè)值保留此項
- unsigned char User_Password_Putin[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//用戶密碼輸入臨時存放數(shù)組
- unsigned char Admin_Password_Putin[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//管理員密碼輸入臨時存放數(shù)組
- //運行變量
- unsigned int ADC_DATA;//讀取到的ADC轉(zhuǎn)換值
- unsigned char ADC_value=0;//設(shè)置一個讀取到的按鍵位置值。位置值由電路連接確定,各個按鍵位置值由所連電阻分壓大小依次順序排列
- unsigned char ADC_keyvalue=0;//讀取到的ADC按鍵設(shè)定值。按鍵位置由電路而定可能并不規(guī)整,設(shè)定值為自定的各按鍵數(shù)值
- unsigned char first_num=1;//管理模式第一項菜單標號
- //運行計數(shù)
- unsigned char choose=1;//用戶菜單選擇號,用于記錄當前選中的菜單項目序號,默認在第一項位置
- unsigned char cnt_user_putin_wrong=0;//用戶輸入錯誤計數(shù)
- unsigned char t1_cnt=0;//定時器1運行計數(shù)
- //運行標志位
- bit flag_Identity=1;//身份標志位,表明當前所處身份狀態(tài) 用戶:1 管理員:0
- bit En_Standby=1;//待機狀態(tài)有效標志位(使能) 有效:1 無效:0
- bit En_Admin=0;//管理員模式下管理有效標志位(使能) 有效:1 無效:0
- bit User_Locker=0;//用戶輸入錯誤導(dǎo)致的鎖定有效 有效:1 無效:0
- bit Admin_Info=0;//管理員提示開關(guān),在用戶待機狀態(tài)下顯示某些信息 有效:1 無效:0
- bit _ReLock=0;//自動鎖定標志位,顯示定時器是否已經(jīng)到達計時時間 是:1 否:0
- bit En_Fire_Sensor=1;//火焰?zhèn)鞲衅髟试S位 有效:1 無效:0
- bit En_RFID=1;//射頻卡讀取允許位 有效:1 無效:0
- /*########################################################################################
- 設(shè)計名稱:密碼鎖設(shè)計 第二版
- 設(shè)計者:清河
- 版本:A1.0
- 最后封裝日期:2018-08-20
- 設(shè)備內(nèi)置ID:0x925AA0CA
- 管理員初始密碼010F(00000000)
- 平臺:STC15W4K48S4
- 硬件部分
- 獨立按鍵:共4個,用于進行各項調(diào)整
- ADC鍵盤:用于輸入密碼,本作品中可以輸入16進制的密碼,較平常10進制密碼更加安全,只要程序和電路做相應(yīng)的修改,也可以實現(xiàn)在AD可分辨的情況下上百的按鍵鍵位
- DS1302:配電池,實現(xiàn)斷電走時,用于待機顯示,如果在關(guān)機時取下電池或者替換DS1302則上電自動初始化
- LED指示燈:指示所處狀態(tài),本作品中進入用戶模式則LED1亮,進入管理員模式則LED2亮
- AT24C02:實現(xiàn)斷電密碼記憶功能,用于記錄用戶密碼的HASH值和注冊的卡信息
- RC522:用于實現(xiàn)刷卡開鎖
- 軟件部分
- 使用定時器0實現(xiàn)對DS1302數(shù)據(jù)的定時讀取,間隔50ms,以便更新當前的顯示值
- 使用定時器1在用戶解鎖成功時定時上鎖,設(shè)置的超時時間為5秒
- ########################################################################################*/
- void delay(unsigned int cnt)//調(diào)用該函數(shù)進行一段時間的延時
- {
- while(cnt--);
- }
- unsigned char KeyScan()
- {
- unsigned char ADC_keyvalue=0;//讀取到的ADC按鍵設(shè)定值
- ADC_CONTR=0xea;//開始轉(zhuǎn)換
- delay(1000);//這段暫停的時間用于等待AD轉(zhuǎn)換完成
- 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()//用戶密碼更改函數(shù),用于獲取新值賦給用戶密碼數(shù)組
- {
- 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;)//進入輸密碼的環(huán)節(jié)
- {
- 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數(shù)組中
- Save_User_Password();//保存新數(shù)據(jù)
- for(k=0;k<16;k++)
- {
- User_Password_Putin[k]=0;//清空用戶輸入
- }
- }
- while(!KEY1);
- OLED_Clear();//清屏,清屏放在此處可以使密碼正確的提示信息在按鍵松開前一直顯示
- break;//立即退出輸入密碼的環(huán)節(jié)
- }
-
- 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;//立即退出輸入密碼的環(huán)節(jié)
- }
- }
- return 0;
- }
- unsigned char Modify_Admin_Password()//管理員密碼修改,包括2個步驟:身份認證、密碼修改,其中任何一步都可以由取消鍵退出
- {
- unsigned char i;
- OLED_Clear();
- OLED_Display_Administrator_Onload();
-
- for(i=0;i<16;)//進入輸密碼的環(huán)節(jié)
- {
- 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)//如果確定鍵按下或輸入位數(shù)滿
- {
- 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;//清空管理員輸入,為后續(xù)輸入做準備
- }
-
- 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;)//進入輸密碼的環(huán)節(jié)
- {
- 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();//保存新數(shù)據(jù)
- for(k=0;k<16;k++)
- {
- Admin_Password_Putin[k]=0;//清空管理員輸入
- }
- }
- while(!KEY1);
- OLED_Clear();//清屏,清屏放在此處可以使密碼正確的提示信息在按鍵松開前一直顯示
- break;//立即退出輸入密碼的環(huán)節(jié)
- }
-
- if(KEY2==0)//如果取消鍵按下
- {
- delay(5000);
- if(KEY2==0)
- {
- for(k=0;k<16;k++)
- {
- Admin_Password_Putin[k]=0;//清空管理員輸入
- }
- OLED_Clear();//清屏
- }
- while(!KEY2);
- break;//立即退出輸入密碼的環(huán)節(jié)
- }
- }
- }
- else//密碼錯誤
- {
- OLED_Clear();
- }
- }
- while(!KEY1);
- goto END;//結(jié)束輸入
- }
-
- 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;//結(jié)束輸入
- }
- }
- END:return 0;
- }
- //################################################################################################################以下為主函數(shù)部分#############
- void sys_init()//系統(tǒng)初始化
- {
- 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;//設(shè)置定時器模式
- EA=1;//開啟總中斷
- TL0=0x00;//設(shè)置定時初值
- TH0=0x28;//設(shè)置定時初值
- ET0=1;//允許定時器0中斷
- TR0=1;//定時器0開始計時
-
- TL1=0x00;//設(shè)置定時初值
- TH1=0x28;//設(shè)置定時初值
- ET1=1;//允許定時器1中斷
- TR1=0;//定時器1停止計時
-
- P1ASF=0x04;//將P1^2設(shè)置為模擬輸入
- ADC_CONTR=0xe7;//開啟ADC電源,設(shè)置為最快轉(zhuǎn)換速度,停止轉(zhuǎn)換,選取P1^2作為ADC輸入
- ADC_RES=0;//清除結(jié)果寄存器
- /*ADRJ=0;//ADC_RES[7:0]存放高8位ADC結(jié)果,ADC_RES[1:0]存放低2位ADC結(jié)果 EADC=1;//A/D轉(zhuǎn)換中斷允許 PADC=1;//設(shè)置A/D轉(zhuǎn)換中斷優(yōu)先級為最高*/
- //CLK_DIV=0X20;
- EADC=1;
- PADC=1;
- }
- void sys_Pretreat()//系統(tǒng)預(yù)處理
- {
- Init_Determine();//DS1302上電自動初始化判斷
- //IAP_Clear_Sector(IAP_ADDRESS);//首次下載對EEPROM擦除
- //Admin_Password_Init();//首次下載存入管理員預(yù)置密碼
- 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中讀出的設(shè)備ID和程序中設(shè)定值不同說明器件被更替,用戶鎖定,需要重新設(shè)置密碼
- {
- User_Locker=1;
- }
- }
- t1_cnt=0;//使用后重置t1_cnt
- }
- void main()
- {
- sys_init();
- sys_Pretreat();
- while(1)
- {
- if(flag_Identity)//身份狀態(tài)
- {//用戶模式
- if(En_Standby)
- {//上鎖的待機狀態(tài)
- 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鍵盤有了輸入并且用戶沒有鎖定則繼續(xù)探測
- {
- 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;)//進入輸密碼的環(huán)節(jié)
- {
- 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數(shù)組中
-
- if(HASH_Compare())//密碼正確
- {
- En_Standby=0;//不再是待機狀態(tài)
- JDQ=0;//開啟繼電器
- OLED_Clear();
- OLED_Display_Right_Password();
- }
- else//密碼錯誤
- {
- En_Standby=1;//仍在待機狀態(tài)
- cnt_user_putin_wrong++;//錯誤計數(shù)增加一次
- if(cnt_user_putin_wrong==5)
- {
- User_Locker=1;//用戶鎖定有效
- cnt_user_putin_wrong=0;//但錯誤計數(shù)置0,這樣一來在管理員模式下只需要關(guān)心用戶鎖定標志位即可
- }
- }
-
- for(k=0;k<16;k++)
- {
- User_Password_Putin[k]=0;//清空用戶輸入
- }
-
- HASH_Result_Clear();//清空哈希計算結(jié)果
- }
- while(!KEY1);
- OLED_Clear();//清屏,清屏放在此處可以使密碼正確的提示信息在按鍵松開前一直顯示
- goto A;//立即退出輸入密碼的環(huán)節(jié)
- }
-
- 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();//清空哈希計算結(jié)果
- }
- while(!KEY2);
- goto A;//立即退出輸入密碼的環(huán)節(jié)
- }
- }
- A: _nop_();
- }
- }
-
- if(KEY1==0)//待機狀態(tài)下KEY1是管理員入口開關(guān)
- {
- 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;//關(guān)閉定時器1
- TL1=0x00;//設(shè)置定時初值
- TH1=0x28;//設(shè)置定時初值
- t1_cnt=0;//重置定時器1運行計數(shù)
- }
- }
-
- 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)
- {
- /*此處添加警報檢查和解除函數(shù)*/
- if(KEY1==0||KEY2==0||KEY3==0||KEY4==0)//若有按鍵按下
- {
- delay(5000);
- if(KEY1==0||KEY2==0||KEY3==0||KEY4==0)
- {
- JDQ=1;//關(guān)閉繼電器
- while(KEY1==0||KEY2==0||KEY3==0||KEY4==0);
- goto FIREQUTE;
- }
- }
- }
- FIREQUTE: OLED_Clear();//清屏
- }
- }
- }
- else
- {//解鎖的待機狀態(tài)
- OLED_User_Mode();//用戶模式菜單動態(tài)顯示
- LED1=0;LED2=1;
- if(KEY1==0)//確定按鍵
- {
- delay(5000);
- if(KEY1==0)
- {
- switch(choose)
- {
- case 1:
- JDQ=1;//關(guān)閉繼電器
- TR1=0;//定時器1停止計時
- TL1=0x00;//設(shè)置定時初值
- TH1=0x28;//設(shè)置定時初值
- t1_cnt=0;
- En_Standby=1;//重新回到上鎖狀態(tài)
- break;
- case 2:
- while(!KEY1);//等待按鍵松開,若不加此句可能導(dǎo)致Modify_User_Password()瞬間運行完,用戶密碼變?yōu)?
- choose=1;//重置菜單選擇位
- TR1=0;//定時器1停止計時
- TL1=0x00;//設(shè)置定時初值
- TH1=0x28;//設(shè)置定時初值
- 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;//關(guān)閉繼電器
- TR1=0;//定時器1停止計時
- TL1=0x00;//設(shè)置定時初值
- TH1=0x28;//設(shè)置定時初值
- t1_cnt=0;
- En_Standby=1;//重新回到上鎖狀態(tài)
- }
- while(!KEY2);
- OLED_Clear();
- }
-
- if(_ReLock)//自動上鎖判斷
- {
- En_Standby=1;//重新回到上鎖狀態(tài)
- _ReLock=0;//重置標志位
- TR1=0;//關(guān)閉定時器1
- TL1=0x00;//設(shè)置定時初值
- TH1=0x28;//設(shè)置定時初值
- t1_cnt=0;//重置定時器1運行計數(shù)
- OLED_Clear();//此處的清屏使用戶菜單在待機界面沒有殘留
- }
- }
- }
- else
- {//管理員狀態(tài)確認
- if(Hardware_Switch==0)
- {//管理員模式
- if(En_Admin)//管理有效
- {
- OLED_Admin_Mode();//管理模式菜單動態(tài)顯示
- LED1=1;LED2=0;
- if(KEY1==0)//確定按鍵
- {
- delay(5000);
- if(KEY1==0)
- {
- switch(choose)
- {
- case 1:
- User_Locker=0;//解除用戶鎖定
- break;
- case 2:
- while(!KEY1);//等待按鍵松開,若不加此句可能導(dǎo)致Modify_User_Password()瞬間運行完,用戶密碼變?yōu)?
- Modify_User_Password();
- break;
- case 3:
- while(!KEY1);//等待按鍵松開,若不加此句可能導(dǎo)致Modify_Admin_Password()瞬間運行完,管理密碼變?yōu)?
- Modify_Admin_Password();
- break;
- case 4:
- OLED_Admin_onoff_Mode();//常開常關(guān)選項
- break;
- case 5:
- OLED_Admin_RFID_Mode();//射頻卡開關(guān)選項
- break;
- case 6:
- Time_Set();//時間修改
- break;
- case 7:
- OLED_Display_System_Information();//顯示狀態(tài)信息
- break;
- case 8:
- OLED_Admin_firesensor_Mode();//火焰探測開關(guān)選項
- break;
- case 9://重置用戶數(shù)據(jù)
- 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();//管理員登入靜態(tài)顯示
- 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;)//進入輸密碼的環(huán)節(jié),如果前面有對第一位密碼的捕獲操作,則此處的循環(huán)從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)//如果確定鍵按下或輸入位數(shù)滿
- {
- 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;//立即退出輸入密碼的環(huán)節(jié)
- }
-
- 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;//立即退出輸入密碼的環(huán)節(jié)
- }
- }
- }
- }
- B: if(KEY2==0)//取消按鍵,和置硬件標志位是一樣的程序,簡單復(fù)制過來的,成品可以刪除
- {
- delay(5000);
- if(KEY2==0)
- {
- OLED_Clear();
- En_Admin=0;//管理無效
- choose=1;//由于管理模式菜單和用戶模式共用一個選擇項,并且菜單顯示和choose有關(guān),所以如果不重置菜單選中位,菜單長度的不同會導(dǎo)致用戶顯示的失敗
- first_num=1;/*如果第一項菜單標號first_num改為全局變量,那么在此處將它置1可以保證每一次進入管理菜單是默認選中第一項*/
- flag_Identity=1;//返回用戶狀態(tài)
- }
- while(!KEY2);
- OLED_Clear();
- }
- }
- }
- else//如果硬件標志位被置1
- {
- OLED_Clear();
- En_Admin=0;//管理無效
- choose=1;//由于管理模式菜單和用戶模式共用一個選擇項,并且菜單顯示和choose有關(guān),所以如果不重置菜單選中位,菜單長度的不同會導(dǎo)致用戶顯示的失敗
- first_num=1;/*如果第一項菜單標號first_num改為全局變量,那么在此處將它置1可以保證每一次進入管理菜單是默認選中第一項*/
- flag_Identity=1;//返回用戶狀態(tài)
- }
- }
- }
- }
- void GetTime() interrupt 1//使用定時器0每隔約50ms獲取一次時間信息
- {
- TL0=(65536-50000)/256;//設(shè)置定時初值
- TH0=(65536-50000)%256;//設(shè)置定時初值
- Ds1302ReadTime();//讀取DS1302時間信息
- time_procressing();//將讀取到的時間轉(zhuǎn)換為十進制數(shù)據(jù),存放在time_trans數(shù)組中
- time_assign();//將得到的值放置在顯示數(shù)組中
- }
- void ReLock() interrupt 3
- {
- TL1=0x00;//設(shè)置定時初值
- TH1=0x28;//設(shè)置定時初值
- t1_cnt++;
- if(t1_cnt==100)
- {
- _ReLock=1;//置標志位
- JDQ=1;//關(guān)閉繼電器
- t1_cnt=0;
- }
- }
- void ADC_Routine() interrupt 5//中斷發(fā)生證明AD轉(zhuǎn)換的結(jié)束
- {
- 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;
- }
復(fù)制代碼 OLED_DISPLAY.C(和顯示有關(guān)的功能函數(shù))
- /*
- 此文件中將來自O(shè)LED_Fuction.c中的顯示函數(shù)按程序狀態(tài)封裝,調(diào)用時更新特定顯示
- */
- #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)//調(diào)用該函數(shù)進行一段時間的延時
- {
- while(cnt--);
- }
- /*####################################################用戶狀態(tài)函數(shù)##############################################*/
- void OLED_Display_Standby()//待機狀態(tài),顯示定時器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()//用戶模式下輸入密碼的靜態(tài)顯示
- {
- 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()//用戶模式下輸入密碼正確的靜態(tài)提示信息
- {
- 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()//用戶模式菜單動態(tài)顯示,因為容量小于等于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)//上調(diào)按鍵
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//選項最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下調(diào)按鍵
- {
- delay2(5000);
- if(KEY4==0)
- {
- choose++;
- if(choose==3)choose=2;//選項最大不能大于2
- }
- while(!KEY4);
- }
- }
- /*######################################################管理員狀態(tài)函數(shù)############################################*/
- void OLED_Display_Administrator_Onload()//管理員登入靜態(tài)顯示
- {
- 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)
- {//定制的菜單顯示接口函數(shù),用于將菜單變量名和調(diào)用它的變量值連接起來,需要知道顯示的起始菜單號和當前選中的菜單
- 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()//管理模式菜單動態(tài)顯示
- {
- //static unsigned char first_num=1;//第一項菜單標號
- OLED_Show_CHinese(0,CCTitle5,0);//顯示標題:管理模式
-
- OLED_Display_Menu(first_num,choose);//根據(jù)first_num和choose的動態(tài)刷新顯示函數(shù)
-
- if(KEY3==0)//上調(diào)按鍵
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//選項最少不能小于1
- if(choose<first_num)first_num--;
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下調(diào)按鍵
- {
- 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()//常開常關(guān)選項,因為容量小于等于3個,一屏可以放得下,所以不加滾屏功能,僅在兩個選項中跳動
- {
- unsigned char choose_possition;//用于存放進入此級菜單時上一級choose的值
- choose_possition=choose;
- OLED_Clear();
- OLED_Show_CHinese(0,CCTitle9,0);//顯示標題:開關(guān)選項
- 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;//管理員開鎖通知關(guān),該提示信息在用戶代碼處修改
- 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)//上調(diào)按鍵
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//選項最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下調(diào)按鍵
- {
- delay2(5000);
- if(KEY4==0)
- {
- choose++;
- if(choose==3)choose=2;//選項最大不能大于2
- }
- while(!KEY4);
- }
- }
- OUT2:choose=choose_possition;//將之前存儲的值還給choose以保證上級菜單不出現(xiàn)錯亂
- }
- void OLED_Admin_firesensor_Mode()//火焰探測器開關(guān)選項,因為容量小于等于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;//關(guān)閉火焰探測器使能位
- 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)//上調(diào)按鍵
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//選項最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下調(diào)按鍵
- {
- delay2(5000);
- if(KEY4==0)
- {
- choose++;
- if(choose==3)choose=2;//選項最大不能大于2
- }
- while(!KEY4);
- }
- }
- FSMENUQUIT:choose=choose_possition;//將之前存儲的值還給choose以保證上級菜單不出現(xiàn)錯亂
- }
- 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;//關(guān)閉射頻卡模塊使能位
- 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)//上調(diào)按鍵
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//選項最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下調(diào)按鍵
- {
- delay2(5000);
- if(KEY4==0)
- {
- choose++;
- if(choose==4)choose=3;//選項最大不能大于3
- }
- while(!KEY4);
- }
- }
- RFIDQUIT:choose=choose_possition;//將之前存儲的值還給choose以保證上級菜單不出現(xiàn)錯亂
- }
- void OLED_Admin_RFID_Manage()//射頻管理選項,因為容量小于等于3個,一屏可以放得下,所以不加滾屏功能,僅在3個選項中跳動
- {
- unsigned char choose_manage;//新建一個臨時選項變量,與上兩層目錄無關(guān)
- 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:
- /*添加卡函數(shù)*/
- Card_Add();
- break;
- case 2:
- /*刪除卡函數(shù)*/
- Card_Delete();
- break;
- case 3:
- /*對比卡函數(shù)*/
- 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)//上調(diào)按鍵
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose_manage--;
- if(choose_manage==0)choose_manage=1;//選項最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下調(diào)按鍵
- {
- 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);//顯示標題:狀態(tài)信息
- 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)
- {
- /*在此添加溫度氣壓掃描顯示函數(shù)*/
- 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判斷,但為了整體規(guī)范性,就不在意那幾個時鐘了
- OLED_Clear();
- goto OUT3;
- }
-
- if(KEY2==0)//取消按鍵
- {
- delay2(5000);
- if(KEY2==0)
- {
- _nop_();
- }
- while(!KEY2);//由于按鍵只起到返回的作用,此處也可以將第二次if判斷去掉,僅使用while判斷,但為了整體規(guī)范性,就不在意那幾個時鐘了
- OLED_Clear();
- goto OUT3;
- }
- }
- OUT3:_nop_();
- }
- void Time_Set()//時間修改函數(shù)
- {
- bit en_data=1;//數(shù)據(jù)合法標志位,表示數(shù)據(jù)檢查時的合法:1/不合法:0判斷結(jié)果
- 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];//復(fù)制運行數(shù)組,取待顯示每一位
-
-
- /*第一部分,日期設(shè)置*/
- 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);//確認進入該函數(shù)時的按鍵已經(jīng)松開
- while(1)
- {
- OLED_DateSet_Display(set_date,choose);//刷新顯示時間設(shè)置數(shù)組,該數(shù)組保存設(shè)置的時間(按位)
-
- 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;//跳出當前循環(huán),進入下一循環(huán)時間設(shè)置
- }
-
- if(KEY2==0)//取消按鍵,直接退出時間設(shè)置函數(shù)
- {
- delay2(5000);
- if(KEY2==0)
- {
- _nop_();
- }
- while(!KEY2);
- OLED_Clear();
- goto TIMESETOUT;
- }
-
- if(KEY3==0)//上調(diào)按鍵
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//選項最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下調(diào)按鍵
- {
- delay2(5000);
- if(KEY4==0)
- {
- choose++;
- if(choose==9)choose=8;//選項最大不能大于8
- }
- while(!KEY4);
- }
- }
-
- /*第二部分,時間設(shè)置*/
- 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);//刷新顯示時間設(shè)置數(shù)組,該數(shù)組保存設(shè)置的時間(按位)
-
- 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;//跳出當前循環(huán),進入第三部分
- }
-
- if(KEY2==0)//取消按鍵,直接退出時間設(shè)置函數(shù)
- {
- delay2(5000);
- if(KEY2==0)
- {
- _nop_();
- }
- while(!KEY2);
- OLED_Clear();
- goto TIMESETOUT;
- }
-
- if(KEY3==0)//上調(diào)按鍵
- {
- delay2(5000);
- if(KEY3==0)
- {
- choose--;
- if(choose==0)choose=1;//選項最少不能小于1
- }
- while(!KEY3);
- }
-
- if(KEY4==0)//下調(diào)按鍵
- {
- 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)//對日子的判斷。注意,由于閏年的存在,若出現(xiàn)閏年輸入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)
- {
- /*拼接寫入數(shù)組*/
- 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);//顯示說明文字:修改成功
- /*按鍵循環(huán)*/
- 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);//顯示說明文字:輸入不合規(guī)則
- /*按鍵循環(huán)*/
- 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_();
- }
復(fù)制代碼
對于下載限制的說明:
由于是我個人的設(shè)計,我認為在黑幣上應(yīng)該有一個價格,該作品也值得這個價格。
對于下載身份限制的說明:
當然要向著站內(nèi)的人了~
密碼鎖第二版 凌凈清河.zip
(247.84 KB, 下載次數(shù): 216)
2019-1-7 15:11 上傳
點擊文件名下載附件
閱讀權(quán)限: 10 下載積分: 黑幣 -5
密碼鎖(第二版)說明文檔.pdf
(286.06 KB, 下載次數(shù): 171)
2019-1-7 15:12 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
好希望你們能夠回復(fù)我呀,回復(fù)這個帖子能給我?guī)聿簧俟膭钅兀?br />
|
評分
-
查看全部評分
|