電子密碼鎖畢業(yè)設(shè)計:矩陣鍵盤與LED狀態(tài)機(jī)實現(xiàn))
簡介這是一套基于51單片機(jī)的4位電子密碼鎖畢業(yè)設(shè)計資料主要面向電子信息類畢業(yè)生、單片機(jī)初學(xué)者以及需要快速完成課程設(shè)計的讀者。方案以AT24C02作為密碼存儲芯片實現(xiàn)掉電后密碼不丟失密碼輸入采用矩陣鍵盤搭配1602液晶實時顯示狀態(tài)并通過紅綠LED直觀模擬開鎖與關(guān)鎖。功能上還包含錯誤次數(shù)累計、超過三次觸發(fā)報警、30秒無操作自動關(guān)閉背光以及提供密碼還原鍵可恢復(fù)至初始密碼1111整體邏輯完整、貼近實際應(yīng)用場景。資源包共71個文件壓縮包約14.73MB涵蓋原理圖、Proteus仿真、Keil C源程序、PDF參考論文、開題報告、使用說明及實物圖等類型目錄結(jié)構(gòu)清晰便于對照硬件設(shè)計理解程序流程也可以直接運行仿真查看效果。目前已有6900余人學(xué)習(xí)下載適合需要從零搭建完整方案、深入理解密碼存儲與矩陣鍵盤掃描邏輯的讀者可在現(xiàn)有框架上擴(kuò)展指紋識別、遙控開鎖等進(jìn)階功能。1. 基于51單片機(jī)電子密碼鎖畢業(yè)設(shè)計4位密碼加一顆LED燈就能把鎖做明白很多人在答辯時會被問住的一個問題是你的電子密碼鎖和直接買一個四位按鍵開關(guān)有什么區(qū)別答案是密碼鎖的實質(zhì)既不是密碼本身也不是那顆LED燈而是「狀態(tài)機(jī)」。51單片機(jī)電子密碼鎖把按鍵輸入、4位密碼比對、鎖狀態(tài)輸出這三件事用一段可以反復(fù)解釋的代碼串起來LED燈就是狀態(tài)機(jī)的可視化出口。燈亮代表開鎖燈滅代表上鎖這種表達(dá)在Proteus仿真和實物演示里都直觀。選51單片機(jī)而不是STM32理由很簡單課程設(shè)計、畢業(yè)設(shè)計里對“原理看得透”的要求往往比性能更重要。51的IO口直接可控矩陣鍵盤掃描和延時消抖都能一步步講清楚適合在有限時間里完成從原理圖到實物演示的全流程。這篇內(nèi)容就把硬件接線、掃描邏輯、密碼比對和LED狀態(tài)顯示按可復(fù)現(xiàn)的路徑講完。2. 51單片機(jī)電子密碼鎖硬件搭建矩陣鍵盤接線與LED驅(qū)動電路參數(shù)2.1 核心器件選型為什么STC89C52比AT89S52更適合課設(shè)常見的做法是用STC89C52作為主控這款芯片在51單片機(jī)課程設(shè)計里出現(xiàn)頻率最高。相比AT89S52STC89C52通過串口就能下載程序不需要額外買編程器對只有一塊開發(fā)板或面包板的場景非常友好。內(nèi)部自帶Flash程序存儲器和EEPROM做密碼存儲擴(kuò)展時也不用加外部存儲芯片。晶振選12MHz一個機(jī)器周期是1μs延時函數(shù)計算方便正好滿足按鍵消抖和LED閃爍演示的需求。物料清單按功能劃分如下器件規(guī)格數(shù)量用途單片機(jī)STC89C52RCDIP40封裝1主控晶振12MHz1系統(tǒng)時鐘瓷片電容30pF2晶振負(fù)載電解電容10μF1復(fù)位電路電阻10kΩ2復(fù)位、上拉電阻330Ω1LED限流按鍵4×4矩陣鍵盤1密碼輸入發(fā)光二極管紅色φ5mm1鎖狀態(tài)指示蜂鳴器有源5V1按鍵提示音選矩陣鍵盤而不是獨立按鍵是因為4位密碼需要數(shù)字0~9再加確認(rèn)和清除鍵至少12個鍵位。如果用獨立按鍵直接接IO口要占用12個引腳而4×4矩陣鍵盤只占8個引腳這對IO資源緊張的51單片機(jī)來說非常關(guān)鍵。矩陣鍵盤省下的引腳可以留給LED、蜂鳴器或擴(kuò)展繼電器。限流電阻選330Ω而不是隨意選是因為紅色LED的正向壓降約1.8~2.0V51單片機(jī)IO口高電平約4.5V灌電流驅(qū)動時飽和壓降約0.2V目標(biāo)電流定在8mA左右算出來是 (5-2-0.2)/0.008 ≈ 350Ω因此標(biāo)準(zhǔn)規(guī)格330Ω既能讓亮度足夠又不會超出手冊允許的灌電流范圍。2.2 4×4矩陣鍵盤的引腳分配與P1口接線方法51單片機(jī)電子密碼鎖的矩陣鍵盤慣例是接在P1口。P1口是準(zhǔn)雙向IO口內(nèi)部有弱上拉按鍵不按時讀回高電平按下時對應(yīng)引腳被拉低。如果把行線接P1.0~P1.3列線接P1.4~P1.7掃描邏輯會非常順逐列輸出低電平再讀行線狀態(tài)就能定位到具體按鍵。#define KEY_PORT P1 sbit LED_LOCK P2^0; // LED指示燈低電平點亮 sbit BUZZER P2^1; // 蜂鳴器可選這段定義把P1整個端口交給矩陣鍵盤掃描P2.0作為LED控制引腳P2.1作為蜂鳴器引腳。這樣的分配是合理的P1口作為準(zhǔn)雙向口不需要外部上拉電阻P2口的其余引腳還可以接1602液晶或繼電器驅(qū)動給后續(xù)擴(kuò)展留出空間。接線時要注意一個問題行線和列線的定義必須與掃描函數(shù)一致。假如行線接P1.0~P1.3列線接P1.4~P1.7那么掃描代碼里列線輸出低電平的位操作就要落在P1.4到P1.7上。這里的接線順序在Proteus仿真里錯了還能快速改在實物上接反了就非常難查所以工程實踐上我習(xí)慣在原理圖上把網(wǎng)絡(luò)標(biāo)號直接寫成P1_ROW0~P1_ROW3、P1_COL0~P1_COL3而不是只標(biāo)數(shù)字。2.3 LED指示燈電路共陽極、共陰極與限流取值LED燈代表鎖開關(guān)這個功能看似簡單但電路接法直接影響代碼邏輯。51單片機(jī)P2口在輸出高電平時驅(qū)動能力弱實測電流往往只有幾百微安直接高電平點亮LED效果很差。因此這里選低電平點亮方案LED正極經(jīng)330Ω限流電阻接VCC負(fù)極接P2.0P2.0輸出低電平時LED亮起。這種灌電流連接方式能提供更穩(wěn)定的驅(qū)動電流。#define LOCK_OPEN 0 // P2.0輸出低電平LED亮 #define LOCK_CLOSED 1 // P2.0輸出高電平LED滅為什么是“LED亮代表開鎖”而不是“亮代表通電”這在畢設(shè)答辯時經(jīng)常被追問。項目標(biāo)題寫得很明確LED燈代表鎖的開關(guān)所以亮滅要跟鎖狀態(tài)綁定而不是跟電源綁定。沒有按鍵操作時LED滅輸入正確密碼比對成功后LED亮再按清除鍵或超時自動上鎖后LED滅這樣整個狀態(tài)遷移在實物上看得非常清楚。如果后續(xù)要驅(qū)動真正的電磁鎖LED就不夠用了。電磁鎖工作電流通常在幾百毫安級別不能直接接在P2.0上需要加三極管放大。常見做法是用S8550作為低端驅(qū)動P2.0接基極發(fā)射極接GND集電極接電磁鎖負(fù)極電磁鎖正極接VCC基極串1kΩ電阻限流。LED可以并聯(lián)在電磁鎖兩端做狀態(tài)指示或者單獨保留這顆LED作為邏輯狀態(tài)燈。2.4 復(fù)位電路、晶振布局與實物抗干擾處理復(fù)位電路和晶振電路是51單片機(jī)電子密碼鎖最容易忽略的部分。復(fù)位電路用10μF電解電容加10kΩ電阻組成上電復(fù)位復(fù)位引腳接10μF電容到VCC、接10kΩ電阻到GND這是STC89C52數(shù)據(jù)手冊里的標(biāo)準(zhǔn)接法。晶振的兩個引腳各接一個30pF瓷片電容到GND電容要盡量貼近晶振引腳否則在面包板上可能出現(xiàn)起振不穩(wěn)定或頻率漂移的問題。矩陣鍵盤在實物上還有個容易被忽略的問題P1口雖然有內(nèi)部弱上拉但上拉阻值較大如果按鍵和單片機(jī)之間用了長排線導(dǎo)線容易拾取工頻干擾。常見的處理是在行線上并聯(lián)4個10kΩ外部上拉電阻提高抗干擾能力。在Proteus仿真里有沒有這些上拉電阻都無所謂但實物的穩(wěn)定性會差一截。另一個措施是給單片機(jī)電源引腳并聯(lián)一個0.1μF去耦電容放在供電入口附近避免上電瞬間的電壓跌落導(dǎo)致單片機(jī)反復(fù)復(fù)位。蜂鳴器如果是無源的需要P2.1輸出一定頻率的方波才能發(fā)聲有源蜂鳴器只要給高電平或低電平就能響簡單得多。我在密碼鎖里建議選有源蜂鳴器代碼里只要置高再延時再置低就能產(chǎn)生按鍵提示音不必額外寫定時器PWM波形。3. 4位密碼識別與按鍵掃描矩陣鍵盤消抖和密碼比較邏輯3.1 行列掃描時序列線拉低與行線回讀的原理4×4矩陣鍵盤的掃描思想是把8根線分成行和列兩組先讓所有列線輸出高電平然后逐列拉低同時讀取行線狀態(tài)。如果某一行和當(dāng)前被拉低的列相交的按鍵被按下這一行線的電平就會從高被拉低。行列交叉點一旦確定鍵值也就確定了。uchar Key_Scan(void) { uchar col, row_value, key_value 0xFF; KEY_PORT 0x0F; // 高4位列線先拉高低4位行線靠內(nèi)部上拉 row_value KEY_PORT 0x0F; // 讀行線狀態(tài) if (row_value 0x0F) { return 0xFF; // 沒有按鍵按下 } Delay10ms(); // 消抖跳過機(jī)械抖動 row_value KEY_PORT 0x0F; if (row_value 0x0F) { return 0xFF; // 抖動導(dǎo)致的誤觸發(fā) } for (col_value 0; col_value 4; col_value) { KEY_PORT 0xFF; // 先把所有IO口置高 KEY_PORT ~(0x10 col_value); // 將當(dāng)前列線拉低 row_value KEY_PORT 0x0F; if (row_value ! 0x0F) { if ((row_value 0x01) 0x00) key_value col_value * 4 0; if ((row_value 0x02) 0x00) key_value col_value * 4 1; if ((row_value 0x04) 0x00) key_value col_value * 4 2; if ((row_value 0x08) 0x00) key_value col_value * 4 3; break; } } while ((KEY_PORT 0x0F) ! 0x0F); // 等待按鍵釋放 return key_value; }這段掃描函數(shù)的關(guān)鍵在于兩次讀取。第一次讀一次判斷有沒有鍵按下如果檢測到低電平延時10ms后再讀一次兩次都讀到低電平才認(rèn)為是有效按鍵這就完成了機(jī)械消抖。機(jī)械按鍵的抖動時間一般在5~10ms兩次讀取的間隔取10ms是經(jīng)驗值取值太短消抖不徹底取值太長會讓人感覺按鍵反應(yīng)遲鈍。掃描得到key_value的范圍是0~15不同的矩陣布局對應(yīng)的鍵值映射不同。下面的映射表按常見4×4鍵盤布局定義uchar code KeyTable[16] { 1, 2, 3, A, 4, 5, 6, B, 7, 8, 9, C, *, 0, #, D };3.2 密碼存儲與比較數(shù)組比對和移位寄存器兩種思路4位密碼的存儲常見有兩種方案。第一種是定義兩個長度為4的數(shù)組一個存放預(yù)設(shè)密碼一個存放輸入緩沖然后逐位比較。第二種是用一個unsigned int變量把按鍵碼按位移位累加最后整體比較。數(shù)組方案更直觀適合畢業(yè)設(shè)計講解也方便以后擴(kuò)展成6位或8位密碼移位方案省RAM但可讀性差答辯時不容易說清楚。uchar code Password[4] {1, 2, 3, 4}; uchar InputBuf[4]; uchar InputLen 0; bit LockFlag 1; // 1表示上鎖0表示開鎖void Compare_Password(void) { uchar i; if (InputLen ! 4) { Buzzer_Once(); return; // 密碼位數(shù)不足直接返回 } for (i 0; i 4; i) { if (InputBuf[i] ! Password[i]) { break; // 有一位不同就退出循環(huán) } } if (i 4) { LockFlag 0; LED_LOCK LOCK_OPEN; // LED亮表示開鎖 } else { LockFlag 1; LED_LOCK LOCK_CLOSED; } InputLen 0; // 清空輸入緩沖等待下一次 }比較邏輯里有一個很容易出錯的地方循環(huán)結(jié)束后用i 4判斷是否全部相等。因為只有四位數(shù)全部比對通過循環(huán)才會正常走完一旦某一位不等break會直接跳出。這個寫法比用strcmp要直觀也避免了引入字符串庫函數(shù)。uchar code關(guān)鍵字表示密碼數(shù)組存放在程序存儲區(qū)不占RAM這是51單片機(jī)資源有限時常有的優(yōu)化。3.3 數(shù)字鍵輸入、*清除和#確認(rèn)的完整按鍵處理流程密碼鎖的操作流程要處理三類按鍵數(shù)字鍵、清除鍵、確認(rèn)鍵。輸入過程中允許用戶發(fā)現(xiàn)自己按錯了按*鍵清空重來輸完4位按#鍵觸發(fā)比對。如果用戶輸入到第4位后不按確認(rèn)鍵繼續(xù)按數(shù)字鍵合理的處理是忽略多余輸入而不是讓緩沖區(qū)溢出。void Key_Process(uchar key) { if (key *) { InputLen 0; // 清除已輸入的密碼 LED_LOCK LOCK_CLOSED; return; } if (key #) { Compare_Password(); // 執(zhí)行密碼比對 return; } if (key 0 key 9) { if (InputLen 4) { InputBuf[InputLen] key; InputLen; } // 輸入滿4位后多余數(shù)字直接被忽略 } }這個處理函數(shù)在按鍵按下時被調(diào)用一次數(shù)字鍵只負(fù)責(zé)把字符填進(jìn)InputBuf不立即執(zhí)行比較。這樣做的好處是用戶輸入錯誤密碼時不會在輸入過程中被立刻打斷給了修改的機(jī)會。InputLen 4這個條件既保護(hù)數(shù)組不越界又規(guī)定了4位密碼的位數(shù)上限。如果設(shè)計者希望輸入滿4位后自動比對也可以在主函數(shù)中加一個判斷但手動按#確認(rèn)的方式更符合真實電子門鎖的操作習(xí)慣。3.4 錯誤次數(shù)限制與系統(tǒng)鎖定防暴力破解的兩種實現(xiàn)電子密碼鎖如果沒有錯誤次數(shù)限制任何人都可以逐個組合試探4位密碼總共10000種組合理論上最多試10000次就能打開。畢業(yè)設(shè)計里至少要有一個簡單的防暴力破解機(jī)制。常見方案是連續(xù)錯誤3次后鎖定30秒鎖定期間無論按什么鍵都不響應(yīng)。uchar ErrorCount 0; bit SystemLocked 0; void Compare_Password(void) { uchar i; if (InputLen ! 4) return; for (i 0; i 4; i) { if (InputBuf[i] ! Password[i]) break; } if (i 4) { LockFlag 0; LED_LOCK LOCK_OPEN; ErrorCount 0; } else { ErrorCount; LED_LOCK LOCK_CLOSED; if (ErrorCount 3) { SystemLocked 1; Delay_Long(); // 延時30秒最簡單的鎖定方式 SystemLocked 0; ErrorCount 0; } } InputLen 0; }用Delay_Long()實現(xiàn)30秒鎖定寫法最直接缺點是延時時單片機(jī)不能響應(yīng)任何操作。進(jìn)階的做法是用定時器記錄當(dāng)前時間鎖定期間主循環(huán)只更新計時器不響應(yīng)按鍵這樣鎖定位和計時互不干擾答辯時可以展開講一講比單純延時更出彩。4. 用LED燈指示鎖開關(guān)狀態(tài)機(jī)設(shè)計、鎖驅(qū)動與邊界處理4.1 把鎖做成狀態(tài)機(jī)而不是單純置位LED很多新手寫密碼鎖喜歡在比對成功后直接LED 0失敗直接LED 1看起來能用但邏輯是散的。更穩(wěn)健的做法是把“鎖狀態(tài)”抽象成一個變量LED只是這個狀態(tài)的一種顯示方式。LockFlag置0代表開鎖LED亮LockFlag置1代表上鎖LED滅。以后如果要求開鎖5秒后自動上鎖只需要在狀態(tài)機(jī)里加一個定時條件不需要改動LED控制代碼。當(dāng)前狀態(tài)觸發(fā)條件下一個狀態(tài)LED狀態(tài)上鎖輸入密碼且比對通過開鎖亮開鎖按鍵*清除或超時上鎖滅上鎖輸入密碼且比對失敗上鎖滅鎖定連續(xù)錯誤3次上鎖滅這張狀態(tài)表描述的就是電子密碼鎖核心的狀態(tài)遷移關(guān)系。代碼里用LockFlag和SystemLocked兩個位變量就能表達(dá)完整邏輯不需要復(fù)雜的switch-case。把狀態(tài)變量、LED控制、密碼比對分層來實現(xiàn)后續(xù)加繼電器驅(qū)動或語音播報模塊時主流程不會亂。4.2 LED驅(qū)動代碼與真實鎖執(zhí)行部件的銜接前文已確定LED采用灌電流驅(qū)動P2.0低電平點亮。在真實系統(tǒng)中LED只是狀態(tài)指示真正的鎖體需要電磁鐵或步進(jìn)電機(jī)驅(qū)動。51單片機(jī)電子密碼鎖畢業(yè)設(shè)計如果只控制一顆LED評委可能會問“鎖在哪里”。這時可以增加一個繼電器模塊用P2.2控制。sbit RELAY P2^2; // 繼電器控制引腳 void Set_Lock_State(bit open) { if (open) { LockFlag 0; LED_LOCK LOCK_OPEN; RELAY 1; // 繼電器吸合鎖舌收回 } else { LockFlag 1; LED_LOCK LOCK_CLOSED; RELAY 0; // 繼電器釋放鎖舌彈出 } }繼電器本身感性負(fù)載線圈斷電時會產(chǎn)生反向電動勢必須在線圈兩端并聯(lián)一個續(xù)流二極管陰極接正極陽極接負(fù)極否則可能擊穿三極管。這一點在Proteus仿真里看不出來實物電路則必須加上。驅(qū)動繼電器用NPN三極管還是PNP取決于繼電器模塊是高電平觸發(fā)還是低電平觸發(fā)買模塊前先看廠家資料。4.3 開鎖延時自動關(guān)閉和按鍵提示音的實現(xiàn)真實門鎖開鎖后通常會在幾秒后自動上鎖防止用戶忘記關(guān)門。用51單片機(jī)做這個功能有兩種方案。一種是Delay延時簡單但延時時無法處理按鍵另一種是用定時器中斷計數(shù)開鎖標(biāo)志置位后主循環(huán)每次檢測定時器的溢出次數(shù)到達(dá)設(shè)定值就自動上鎖。bit AutoLockEnable 0; uint TimerCount 0; void Timer0_Init(void) { TMOD 0x01; // 定時器0方式116位定時 TH0 0xFC; // 1ms定時初值 TL0 0x18; ET0 1; EA 1; TR0 1; } void Timer0_ISR(void) __interrupt 1 { TH0 0xFC; TL0 0x18; if (AutoLockEnable) { TimerCount; if (TimerCount 5000) { // 5秒后自動上鎖 TimerCount 0; AutoLockEnable 0; Set_Lock_State(0); // 關(guān)閉鎖 } } }這里的定時初值0xFC18對應(yīng)1ms因為12MHz晶振下定時器每1μs計數(shù)一次1ms需要計數(shù)1000次65536減1000等于64536十六進(jìn)制就是0xFC18。5000次溢出就是5秒這個參數(shù)按需修改。用定時器方案的好處是自動上鎖期間按鍵仍然可用不會出現(xiàn)鎖在延時時段里完全無響應(yīng)的情況。5. 畢業(yè)設(shè)計驗證與答辯Proteus仿真、實物排查與演示技巧5.1 Proteus仿真51單片機(jī)的最小檢查清單Proteus仿真是驗收51單片機(jī)電子密碼鎖最容易出錯也最容易通過的環(huán)節(jié)。在Proteus里分別放置AT89C51、4×4矩陣鍵盤、LED、電阻和電源端子把編譯生成的HEX文件加載到單片機(jī)中。檢查清單按順序執(zhí)行檢查晶振電路是否連接Proteus中的單片機(jī)默認(rèn)使用內(nèi)部時鐘模型但加載HEX后需要確認(rèn)電源引腳已經(jīng)接VCC和GND運行仿真點擊矩陣鍵盤的按鍵時注意觀察鍵盤引腳是否有電平變化依次按下1、2、3、4、#LED應(yīng)點亮再按*LED應(yīng)熄滅故意輸入錯誤密碼連續(xù)3次后再按正確密碼觀察是否處于鎖定狀態(tài)不響應(yīng)。如果LED始終不亮優(yōu)先檢查HEX文件是否生成成功。Keil中需要通過Options for Target設(shè)置勾選Create HEX File默認(rèn)情況下Keil不會自動生成HEX。Proteus加載的是HEX不是編譯的工程文件這一步是新手最容易卡住的地方。5.2 實物調(diào)試中的常見故障快速定位實物和仿真之間最大的差別在于電氣噪聲和接觸不良。以下表格列出密碼鎖實物最常見的問題和排查方向故障現(xiàn)象可能原因處理方法按任意鍵無反應(yīng)單片機(jī)未運行或晶振不起振用示波器測晶振引腳波形檢查復(fù)位電路單獨某個鍵沒反應(yīng)矩陣鍵盤該行或該列斷線萬用表測行線和列線通斷按一次鍵被識別多次消抖延時不足或按鍵釋放未檢測將消抖延時加大到15ms以上輸入正確密碼不開鎖密碼數(shù)組內(nèi)容與按下鍵值不匹配串口打印或仿真觀察InputBuf內(nèi)容LED亮度不足限流電阻過大把電阻從1kΩ改為330Ω矩陣鍵盤的“行或列斷線”在面包板上最常見。面包板內(nèi)部金屬彈片老化后接觸電阻增大按鍵按下去時電阻不歸零單片機(jī)讀到的是不確定電平。處理方式是換一個面包板區(qū)域或者直接換成焊接的鍵盤模塊。5.3 答辯現(xiàn)場演示方法與關(guān)鍵問答應(yīng)對答辯演示時不要只演示“輸入1234燈亮”這一個動作。更完整的演示流程是先演示錯誤密碼LED不亮蜂鳴器響再演示正確密碼LED亮接著按*鍵LED熄滅最后演示連續(xù)輸錯3次進(jìn)入鎖定狀態(tài)在鎖定期間按正確密碼無效等待鎖定結(jié)束后再操作。這套流程把密碼鎖的核心功能全部覆蓋正好對應(yīng)畢業(yè)論文里硬件設(shè)計、軟件流程和狀態(tài)分析的章節(jié)。被問到“如何修改密碼”時如果作品沒有實現(xiàn)改密功能可以直接說明當(dāng)前設(shè)計采用固定密碼并說出擴(kuò)展方向STC89C52內(nèi)置EEPROM可以設(shè)計一個長按鍵進(jìn)入密碼修改模式新密碼寫入EEPROM掉電不丟失。這類回答既誠實又體現(xiàn)對芯片資源的理解。被問到“LED燈的驅(qū)動電流為什么夠”時把灌電流驅(qū)動和限流電阻計算過程講清楚說明曾經(jīng)測過實際電流值比籠統(tǒng)回答“能亮就行”有說服力得多。本文還有配套的精品資源點擊獲取