如圖4.14.2所示,用AT89S51的并行口P1接4×4矩陣鍵盤,以P1.0-P1.3作輸入線,以P1.4-P1.7作輸出線;在數(shù)碼管上顯示每個按鍵的“0-F”序號。對應(yīng)的按鍵的序號排列如圖4.14.1所示
500)this.width=500'>300)this.width=300" border=0>
圖4.14.1
2.硬件電路原理圖
500)this.width=500'>300)this.width=300" border=0>
圖4.14.2
3.系統(tǒng)板上硬件連線
(1. 把“單片機系統(tǒng)“區(qū)域中的P3.0-P3.7端口用8芯排線連接到“4X4行列式鍵盤”區(qū)域中的C1-C4 R1-R4端口上;
(2. 把“單片機系統(tǒng)”區(qū)域中的P0.0/AD0-P0.7/AD7端口用8芯排線連接到“四路靜態(tài)數(shù)碼顯示模塊”區(qū)域中的任一個a-h(huán)端口上;要求:P0.0/AD0對應(yīng)著a,P0.1/AD1對應(yīng)著b,……,P0.7/AD7對應(yīng)著h。
4.程序設(shè)計內(nèi)容
(1. 4×4矩陣鍵盤識別處理
(2. 每個按鍵有它的行值和列值 ,行值和列值的組合就是識別這個按鍵的編碼。矩陣的行線和列線分別通過兩并行接口和CPU通信。每個按鍵的狀態(tài)同樣需變成數(shù)字量“0”和“1”,開關(guān)的一端(列線)通過電阻接VCC,而接地是通過程序輸出數(shù)字“0”實現(xiàn)的。鍵盤處理程序的任務(wù)是:確定有無鍵按下,判斷哪一個鍵按下,鍵的功能是什么;還要消除按鍵在閉合或斷開時的抖動。兩個并行口中,一個輸出掃描碼,使按鍵逐行動態(tài)接地,另一個并行口輸入按鍵狀態(tài),由行掃描值和回饋信號共同形成鍵編碼而識別按鍵,通過軟件查表,查出該鍵的功能。
5.程序框圖
500)this.width=500'>300)this.width=300" border=0>
2樓 Juliet發(fā)表于2006-5-10 11:22:00 設(shè)計中你是否遇到過這樣的問題:你的產(chǎn)品上要求有幾十個按鍵,處理器IO口很少,PCB的面積又有嚴(yán)格限制,或者你要嚴(yán)格控制成本,無法使用象7219那樣的擴展芯片,怎么解決這個問題?
下面有個方法,大家都見過遙控器吧,上面不但有幾十個按鍵,而且功能還挺多什么去抖動,同時按鍵處理都有了,最最重要的是控制芯片體積小,價格便宜(也就1,2塊錢),外圍器件少。。不過具體實現(xiàn)起來有點小麻煩,這類芯片的信號一般是PPM輸出的,通常為了有更遠(yuǎn)的遙控距離,按鍵編碼調(diào)制在一個38k左右的載波上。所以我們不得不再為這個方案多花上1塊錢,加一個有爛運放做的低通濾波器,將載波濾除后在接到單片機的IO腳上,由于兩個頻率相差較多,這個濾波器并不難做。我使用LM324做的。其中有兩級低通,一個比較器。
當(dāng)你的示波器上出現(xiàn)一串可愛的幾百赫茲的方波時,你的硬件就成功啦。既然只用一條IO就擴展了幾十個按鍵,軟件上自然會多費些事,此類芯片發(fā)碼都是有引導(dǎo)頭,同步部分,用戶碼,鍵碼等部分組成,有三十多個位,具體可參照sc6121資料。下面時一個完整的接收程序,針對的芯片是sc6121,處理器89c51
///////////////////////////////////////////////////////////////////////////////
/*定時器1中斷服務(wù)程序*/
/*
每100us中斷一次,定時檢測HangSignal線上的電平狀態(tài),根據(jù)6121的砝碼格式譯出用戶碼鍵碼.\
ib_KeyCode[0] 用戶碼低位
,ib_KeyCode[1]用戶碼高位
,ib_KeyCode[2]鍵碼
,ib_KeyCode[3]鍵碼的反碼
*/
/////////////////////////////////////////////////////////////////////////////////////
void HandIn() interrupt 3 using 3 {
unsigned char tempbit=0;
bit Hbit;
Hbit=HandSignal; /*采樣信號線*/
if (NewKey==FALSE){ /*如果上一次按鍵事件已經(jīng)北處理*/
switch (ib_HandState){ /*根據(jù)接收狀態(tài)散轉(zhuǎn)*/
case LEAD: /*引導(dǎo)頭接收情況*/
if (Hbit){ /*如果信號線是高電平*/
if ((ib_LowTime>MIN_LeadTime)&&(ib_LowTime ib_HandState=START; /*正確進入同步頭接收狀態(tài)*/ else ib_HandState=RESTART; /*否則復(fù)位接收程序*/ ib_LowTime=0; /*清除低電平時間計數(shù)*/ } else{ /*如果信號是低電平*/ ib_LowTime++; /*增加低電平時間計數(shù)器*/ if (ib_LowTime>MAX_LeadTime) /*判斷低電平時間是否超時*/ ib_HandState=RESTART; /*是的話復(fù)位接收程序*/ } break; case START: /*同步頭接收情況*/ if(Hbit){ /*如果信號線是高電平*/ ib_HighTime++; /*高電平時間計數(shù)器加一*/ if (ib_HighTime>MAX_SynTime) /*如果高電平時間超長,復(fù)位接收程序*/ ib_HandState=RESTART; } else{