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