❶ 如何用單片機模擬鍵盤控制電腦
介面協議原理
PS/2鍵盤介面採用一種雙向同步串列協議。即每在時鍾線上發一個脈沖,就在數據線上發送一位數據。在相互傳輸中,主機擁有匯流排控制權,即它可以在任何時候抑制鍵盤的發送。方法是把時鍾線一直拉低,鍵盤就不能產生時鍾信號和發送數據。在兩個方向的傳輸中,時鍾信號都是由鍵盤產生,即主機不產生通信時鍾信號。
如果主機要發送數據,它必須控制鍵盤產生時鍾信號。方法如下:主機首先下拉時鍾線至少100μs抑制通信,然後再下拉數據線,最後釋放時鍾線。通過這一時序控制鍵盤產生時鍾信號。當鍵盤檢測到這個時序狀態,會在10ms內產生時鍾信號。如圖3中 A 時序段。主機和鍵盤之間,傳輸數據幀的時序如圖2、圖3所示。2.2 數據包結構在主機程序中,利用每個數據位的時鍾脈沖觸發中斷,在中斷常式中實現數據位的判斷和接收。在實驗過程中,通過合適的編程,能夠正確控制並接收鍵盤數據。但該方案有一點不足,由於每個CLOCK都要產生一次中斷,中斷頻繁,需要耗用大量的主機資源。
/*-----------------------------------------------
ps2滑鼠的基本原理應用
說明:此程序使用標准PS2鍵盤輸入。此樣例僅作測試使用
晶振使用12M或者11.0592M,本鍵盤使用部分字母和數字測試,其他按鍵不能使用,用
戶可以自行擴展。由於開發板和程序的各種參數,程序中沒有使用奇偶校驗,不保證沒有
誤碼,校驗程序請自行添加。
-------------------------------------------------*/
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
sbit Key_Data = P3^3 ; //定義Keyboard引腳
sbit Key_CLK = P3^2; //使用中斷
bit BF=0;
bit Shift; //定義上檔鍵標志
bit Key_UP; //定義通碼斷碼標志
unsigned char KeyV;
unsigned char IntNum;
unsigned char DisNum;
/*-----------------------------------------------
外部中斷讀入信息
-----------------------------------------------*/
void Keyboard_out(void) interrupt 0
{
if ((IntNum > 0) && (IntNum < 9))
{
KeyV = KeyV >> 1; //因鍵盤數據是低>>高,結合上一句所以右移一位
if (Key_Data)
KeyV = KeyV | 0x80; //當鍵盤數據線為1時到最高位
}
IntNum++;
while (!Key_CLK); //等待PS/2CLK拉高
if (IntNum > 10)
{
IntNum = 0; //當中斷11次後表示一幀數據收完,清變數准備下一次接收
BF = 1; //標識有字元輸入完了
EA = 0; //關中斷等顯示完後再開中斷
}
}
/*-----------------------------------------------
解碼信息
注意:如SHIFT+G為12H 34H F0H 34H F0H 12H
也就是說shift的通碼+G的通碼+shift的斷碼+G的斷碼
-----------------------------------------------*/
void Decode(unsigned char ScanCode) //
{
unsigned char TempCyc,Val;
if (!Key_UP) //當鍵盤按下時
{
switch (ScanCode)
{
case 0xF0 : // 當收到0xF0,Key_UP置1表示斷碼開始
Key_UP = 1;
break;
case 0x12 : // 左 SHIFT
Shift = 1;
break;
case 0x59 : // 右 SHIFT
Shift = 1;
break;
default:
if(!Shift) //如果SHIFT沒按下
{
for (TempCyc = 0;(UnShifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++); //查表顯示
if (UnShifted[TempCyc][0] == ScanCode)
{
Val= UnShifted[TempCyc][1];
LCD_Write_Char(DisNum%16,DisNum/16,Val);
DisNum++;
if(DisNum==33)
{
LCD_Clear(); //清屏
DisNum=0; //重頭寫數據
}
}
}
else //按下SHIFT
{
for(TempCyc = 0; (Shifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++); //查表顯示
if (Shifted[TempCyc][0] == ScanCode)
{
Val= Shifted[TempCyc][1];
LCD_Write_Char(DisNum%16,DisNum/16,Val);
DisNum++;
if(DisNum==33)
{
LCD_Clear(); //清屏
DisNum=0; //重頭寫數據
}
}
}
break;
}
}
else
{
Key_UP = 0;
switch (ScanCode) //當鍵松開時不處理判碼,如G 34H F0H 34H 那麼第二個34H不會被處理
{
case 0x12 : // 左 SHIFT
Shift = 0;
break;
case 0x59 : // 右 SHIFT
Shift = 0;
break;
}
}
BF = 0; //標識字元處理完了
}
/*-----------------------------------------------
ps2初始化(實際初始化外部中斷)
-----------------------------------------------*/
void PS2_Init(void)
{
IT1 = 0; //設外部中斷1為低電平觸發
EA = 1; //外部中斷開
EX0 = 1; //開中斷
}
/*-----------------------------------------------
讀取鍵盤值
-----------------------------------------------*/
void Read_KeyBoard(void)
{
if (BF)
Decode(KeyV);
else
EA = 1; //開中斷
}
❷ 鍒╃敤STC89S51鍗曠墖鏈哄仛閿鐩樸
#include
"KBCODE.H"
#define
LCM_RS
P2_0
#define
LCM_RW
P2_1
//瀹氫箟LCD寮曡剼
#define
LCM_E
P2_2
#define
LCM_Data
P0
#define
Busy
0x80
//鐢ㄤ簬媯嫻婰CM鐘舵佸瓧涓鐨凚usy鏍囪瘑
#define
Key_Data
P3_2
//瀹氫箟Keyboard寮曡剼
#define
Key_CLK
P3_3
void
LCMInit(void);
void
DisplayOneChar(unsigned
char
X,unsigned
char
Y,unsigned
char
DData);
void
DisplayListChar(unsigned
char
X,unsigned
char
Y,unsigned
char
code
*DData);
void
Delay5Ms(void);
void
Delay400Ms(void);
void
Decode(unsigned
char
ScanCode);
void
WriteDataLCM(unsigned
char
WDLCM);
void
WriteCommandLCM(unsigned
char
WCLCM,BuysC);
unsigned
char
ReadStatusLCM(void);
unsigned
char
code
cdle_net[]
=
{"RICHMCU
PS2
TEST"};
unsigned
char
code
email[]
=
{"www.RICHMCU.COM"};
unsigned
char
code
Cls[]
=
{"
"};
static
unsigned
char
IntNum
=
0;
//涓鏂嬈℃暟璁℃暟
static
unsigned
char
KeyV;
//閿鍊
static
unsigned
char
DisNum
=
0;
//鏄劇ず鐢ㄦ寚閽
static
unsigned
char
Key_UP=0,
Shift
=
0;//Key_UP鏄閿鏉懼紑鏍囪瘑錛孲hift鏄瘲hift閿鎸変笅鏍囪瘑
static
unsigned
char
BF
=
0;
//鏍囪瘑鏄鍚︽湁瀛楃﹁鏀跺埌
void
main(void)
{
unsigned
char
TempCyc;
Delay400Ms();
//鍚鍔ㄧ瓑寰咃紝絳塋CM璁插叆宸ヤ綔鐘舵
LCMInit();
//LCM鍒濆嬪寲
DisplayListChar(0,
0,
cdle_net);
DisplayListChar(0,
1,
email);
for(TempCyc=0;
TempCyc<10;
TempCyc++)
{
Delay400Ms();
//寤舵椂
}
DisplayListChar(0,
1,
Cls);
IT1
=
0;
//璁懼栭儴涓鏂1涓轟綆鐢靛鉤瑙﹀彂
EX1
=
1;
//寮涓鏂
EA
=
1;
while(1)
{
if(BF)
Decode(KeyV);
else
{
EA
=
1;
//寮涓鏂
}
}
}
//鍐欐暟鎹
void
WriteDataLCM(unsigned
char
WDLCM)
{
ReadStatusLCM();
//媯嫻嬪繖
LCM_Data
=
WDLCM;
LCM_RS
=
1;
LCM_RW
=
0;
LCM_E
=
0;
//鑻ユ櫠鎸閫熷害澶楂樺彲浠ュ湪榪欏悗鍔犲皬鐨勫歡鏃
LCM_E
=
0;
//寤舵椂
LCM_E
=
1;
}
//鍐欐寚浠
void
WriteCommandLCM(unsigned
char
WCLCM,BuysC)
//BuysC涓0鏃跺拷鐣ュ繖媯嫻
{
if(BuysC)
ReadStatusLCM();
//鏍規嵁闇瑕佹嫻嬪繖
LCM_Data
=
WCLCM;
LCM_RS
=
0;
LCM_RW
=
0;
LCM_E
=
0;
LCM_E
=
0;
LCM_E
=
1;
}
//璇葷姸鎬
unsigned
char
ReadStatusLCM(void)
{
LCM_Data
=
0xFF;
LCM_RS
=
0;
LCM_RW
=
1;
LCM_E
=
0;
LCM_E
=
1;
while(LCM_Data
&
Busy);
//媯嫻嬪繖淇″彿
return(LCM_Data);
}
void
LCMInit(void)
//LCM鍒濆嬪寲
{
LCM_Data
=
0;
WriteCommandLCM(0x38,0);
//涓夋℃樉紺烘ā寮忚劇疆錛屼笉媯嫻嬪繖淇″彿
Delay5Ms();
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
Delay5Ms();
WriteCommandLCM(0x38,1);
//鏄劇ず妯″紡璁劇疆,寮濮嬭佹眰姣忔℃嫻嬪繖淇″彿
WriteCommandLCM(0x08,1);
//鍏抽棴鏄劇ず
WriteCommandLCM(0x01,1);
//鏄劇ず娓呭睆
WriteCommandLCM(0x06,1);
//
鏄劇ず鍏夋爣縐誨姩璁劇疆
WriteCommandLCM(0x0F,1);
//
鏄劇ず寮鍙婂厜鏍囪劇疆
}
//鎸夋寚瀹氫綅緗鏄劇ず涓涓瀛楃
void
DisplayOneChar(unsigned
char
X,
unsigned
char
Y,
unsigned
char
DData)
{
Y
&=
0x1;
X
&=
0xF;
//闄愬埗X涓嶈兘澶т簬15錛孻涓嶈兘澶т簬1
if(Y)
X
|=
0x40;
//褰撹佹樉紺虹浜岃屾椂鍦板潃鐮+0x40;
X
|=
0x80;
//綆楀嚭鎸囦護鐮
WriteCommandLCM(X,
1);
//鍙戝懡浠ゅ瓧
WriteDataLCM(DData);
//鍙戞暟鎹
}
//鎸夋寚瀹氫綅緗鏄劇ず涓涓插瓧絎
void
DisplayListChar(unsigned
char
X,
unsigned
char
Y,
unsigned
char
code
*DData)
{
unsigned
char
ListLength;
ListLength
=
0;
Y
&=
0x1;
X
&=
0xF;
//闄愬埗X涓嶈兘澶т簬15錛孻涓嶈兘澶т簬1
while
(DData[ListLength]>0x19)
{//鑻ュ埌杈懼瓧涓插熬鍒欓鍑
if(X
<=
0xF)
{//X鍧愭爣搴斿皬浜0xF
DisplayOneChar(X,
Y,
DData[ListLength]);
//鏄劇ず鍗曚釜瀛楃
ListLength++;
X++;
}
}
}
//5ms寤舵椂
void
Delay5Ms(void)
{
unsigned
int
TempCyc
=
5552;
while(TempCyc--)
;
}
//400ms寤舵椂
void
Delay400Ms(void)
{
unsigned
char
TempCycA
=
5;
unsigned
int
TempCycB;
while(TempCycA--)
{
TempCycB=7269;
while(TempCycB--)
;
}
}
void
Keyboard_out(void)
interrupt
2
{
if((IntNum
>
0)
&&
(IntNum
<
9))
{
KeyV
>>=
1;
//鍥犻敭鐩樻暟鎹鏄浣>>楂橈紝緇撳悎涓婁竴鍙ユ墍浠ュ彸縐諱竴浣
if(Key_Data)
{
KeyV
|=
0x80;
//褰撻敭鐩樻暟鎹綰誇負1鏃朵負1鍒版渶楂樹綅
}
}
IntNum++;
while(!Key_CLK);
//絳夊緟PS/2CLK鎷夐珮
if(IntNum
>
10)
{
IntNum
=
0;
//褰撲腑鏂10嬈″悗琛ㄧず涓甯ф暟鎹鏀跺畬錛屾竻鍙橀噺鍑嗗囦笅涓嬈℃帴鏀
BF
=
1;
//鏍囪瘑鏈夊瓧絎﹁緭鍏ュ畬浜
EA
=
0;
//鍏充腑鏂絳夋樉紺哄畬鍚庡啀寮涓鏂
}
}
void
Decode(unsigned
char
ScanCode)
//娉ㄦ剰:濡係HIFT+G涓12H
34H
F0H
34H
F0H
12H錛屼篃灝辨槸璇磗hift鐨勯氱爜+G鐨勯氱爜+shift鐨勬柇鐮+G鐨勬柇鐮
{
unsigned
char
TempCyc;
if(!Key_UP)
{
//褰撻敭鐩樻澗寮鏃
switch(ScanCode)
{
case
0xF0
:
//褰撴敹鍒0xF0錛孠ey_UP緗1琛ㄧず鏂鐮佸紑濮
Key_UP
=
1;
break;
case
0x12:
//
宸
SHIFT
Shift
=
1;
break;
case
0x59:
//
鍙
SHIFT
Shift
=
1;
break;
default:
if(DisNum
>
15)
{
DisplayListChar(0,1,Cls);
//娓匧CD絎浜岃
DisNum
=
0;
}
if(Shift
==
1)
{
//濡傛灉鎸変笅SHIFT
for(TempCyc
=
0;(Shifted[TempCyc][0]!=ScanCode)&&(TempCyc<59);
TempCyc++);
//鏌ヨ〃鏄劇ず
if(Shifted[TempCyc][0]
==
ScanCode)
{
DisplayOneChar(DisNum,1,Shifted[TempCyc][1]);
}
DisNum++;
}
else
{
//娌℃湁鎸変笅SHIFT
for(TempCyc
=
0;
(UnShifted[TempCyc][0]!=ScanCode)&&(TempCyc<59);TempCyc++);
//鏌ヨ〃鏄劇ず
if(UnShifted[TempCyc][0]
==
ScanCode)
{
DisplayOneChar(DisNum,1,UnShifted[TempCyc][1]);
}
DisNum++;
}
break;
}
}
else
{
Key_UP
=
0;
switch(ScanCode)
{
//褰撻敭鏉懼紑鏃朵笉澶勭悊鍒ょ爜錛屽侴
34H
F0H
34H
閭d箞絎浜屼釜34H涓嶄細琚澶勭悊
case
0x12:
//
宸
SHIFT
Shift
=
0;
break;
case
0x59:
//
鍙
SHIFT
Shift
=
0;
break;
default:
break;
}
}
BF
=
0;
//鏍囪瘑瀛楃﹀勭悊瀹屼簡
}
❸ 51單片機普通i/o可以模擬USB鍵盤嗎
用2個普通的I/O口來模擬USB鍵盤當然是可以的。用USB控制晶元當然好了,寫程序更方便簡單。但增加了成本。
用I/O口來模擬,必須要知道USB的協議,更要知道USB鍵盤的協議,要把這些協議都寫進程序中去才行啊。
這樣,寫程序比較麻煩,但可以節省硬體成本了。
❹ 外設鍵盤的工作原理
有人知道外設鍵盤的工作原理嗎?沒有的話就跟我來看看咯!以下就是我做的整理,希望大家能喜!
外設鍵盤的簡介
鍵盤是一組按鍵的組合,它是最常用的單片機輸入設備,操作人員可以通過鍵盤輸入數據或命令,實現簡單的人機對話。單片機使用的鍵盤是一種常開型的開關,通常鍵的兩個觸點處於斷開狀態,按下鍵時它們才閉合。鍵盤分編碼和非編碼鍵盤,鍵盤的識別可用軟體識別也可用專用晶元識別。
MCS-51單片機擴展鍵盤介面的 方法 用很多,從硬體結構上,可通過單片機I/0介面擴展鍵盤,也可通過擴展I/O介面設計鍵盤,還有些用的是專用鍵盤晶元。
鍵盤的工作原理
鍵盤從結構上分為獨立式鍵盤與矩陣式鍵盤。一般按鍵較少時採用獨立式鍵盤,按鍵較多時採用矩陣式鍵盤。
(1) 獨立式鍵盤。
在由單片機組成的測控系統及智能化儀器中,用的最多的是獨立式鍵盤。這種鍵盤具有硬體與軟體相對簡單的特點,其缺點是按鍵數量較多時,要佔用大量口線。圖1是一個利用MCS-51單片機的P1口設計的非編碼鍵盤。
圖1 獨立式鍵盤
當按鍵沒按下時,CPU對應的I/O介面由於內部有上拉電阻,其輸入為高電平;當某鍵被按下後,對應的I/O介面變為低電平。只要在程序中判斷I/O介面的狀態,即可知道哪個鍵處於閉合狀態。以下是非編碼鍵盤鍵處理子程序。
JNB P1.0, KEY00 ;轉按鍵1處理程序
JNB P1.1, KEY01 ;轉按鍵1處理程序
JNB P1.2, KEY02 ;轉按鍵1處理程序
JNB P1.3, KEY03 ;轉按鍵1處理程序
JNB P1.4, KEY04 ;轉按鍵1處理程序
JNB P1.5, KEY05 ;轉按鍵1處理程序
JNB P1.6, KEY06 ;轉按鍵1處理程序
JNB P1.7, KEY07 ;轉按鍵1處理程序
RET ;無鍵按下,返回
KEY00: …
RET
KEY01: …
RET
…
(2) 矩陣式鍵盤。
矩陣式鍵盤使用於按鍵數量較多的場合,它由行線與列線組成,按鍵位於行、列的交叉點上。一個3*3的行列結構可以構成一個有9個按鍵的鍵盤。同理,一個4*4的行列可以構成一個16按鍵的鍵盤。很明顯,在按鍵數量較多的場合,與獨立式鍵盤相比,矩陣式鍵盤要節省很多I/0介面。
2.鍵盤按鍵識別方法
(1)掃描法。
下面以圖2的K2鍵按下為例,說明此鍵是如何識別出來的。
圖2 8031與鍵盤連接
掃描法有行掃描和列掃描兩種,無論採用哪種,無論採用哪種,其效果是一樣的,只是在程序中的處理方法有所區別。下面以列掃描法為例來介紹掃描法識別按鍵的方法。首先在鍵處理程序中將P1.4-P1.7依次按位變低,P1.4-P1.7在某一時刻只有一個為低。在某一位為低時讀行線,根據行線的狀態即可判斷出哪一個按鍵被按下。如2號鍵按下,當列線P1.5為低時,讀回的行線狀態中P1.0被拉低,由此可知K2鍵被按下。一般在掃描法中分兩步處理按鍵,首先是判斷有無鍵按下,如行線有一個為低,則有鍵按下。當判斷有鍵按下時,使列線依次變低,讀行線,進而判斷出具體哪個鍵被按下。
(2)線反轉法。
掃描法是逐行或逐列掃描查詢,當被按下的鍵處於最後一列時,要經過多次掃描才能最後獲得此按鍵所處的行列值。而線反轉法則顯的簡練,無論被按的鍵處於哪列,均可經過兩步即能獲得此按鍵所在的行列值,仍以圖4.38為例來介紹線反轉法。
首先將行線P1.0-P1.3作為輸入線,列線P1.4-P1.7作為輸出線,並且輸出線輸出全為低電平,讀行線狀態,則行線中電平為低的是按鍵所在的行。然後將列線作為輸入線,行線作為輸出線,並將輸出線輸出為低電平,讀列線狀態,則列線是電平為低的是按鍵所在的列。綜合上述兩步結果,確定按鍵所在的行和列,從而識別出所按下的鍵。
假設10號鍵被按下,在第一步P1.3-P1.0全為低電平時,讀P1.4-P1.7的值,則P1.5為低電平;在第二步P1.4-P1.7輸出全為低電平時,讀P1.3-P1.0時,P1.2為低電平。由此可判斷第3行第2列有鍵被按下,此鍵就是K10鍵。
3. 鍵盤的介面電路
設計MCS-51單片機鍵盤時可根據單片機系統的實際情況來靈活處理。在使用內部有程序存儲器的單片機時,如單片機的I/O介面夠用,可直接利用單片機的I/O介面連接鍵盤。如果I/O介面不夠用,可利用擴展I/O介面連接鍵盤,有時也可使用專用的鍵盤介面晶元。
(1) 利用單片機的I/O介面連接鍵盤。
利用MCS-51單片機的I/O介面連接鍵盤時分兩種情況,一是當P0、P1、P2、P3均為普通輸入/輸出時,可使用任意I/0介面連接鍵盤;二是當單片機系統擴展程序存儲器、數據存儲器、I/O時,由於P0、P2作為地址數據匯流排的使用,所以擴展鍵盤時只能使用P1口、P3口。如圖2所示為利用MCS-51單片機的P1口設計的4*4矩陣鍵盤。
注意如果用P0口設計鍵盤,要給P0口各口線提供上拉電阻,其大小一般為2-10kn。
(2) 利用擴展I/O介面設計鍵盤。
MCS-51單片機在匯流排擴展凡是時由於P0口、P2口分別作為數據匯流排及地址匯流排,而P1口、P3口又有其他用途時,擴展鍵盤可利用擴展的I/O介面。利用8255的PC口設計的4*4矩陣鍵盤如圖3所示,利用8255的PC口設計的編碼鍵盤,PC0-PC3為行輸入,PC4-PC7為列輸出。
圖3 8255與鍵盤連接圖
(3) 按鍵去抖。
由於通常的按鍵所用的開關是機械開關,當開關閉合、斷開時並不是馬上穩定地接通和斷開,而是在閉合與斷開瞬間均伴隨有一連串的抖動。
為了確保CPU對鍵的一次閉合僅做一次處理,必須要在程序或硬體上進行防抖處理。為節省硬體,通常在單片機系統中,一般不採用硬體方法消除鍵的抖動,而是用軟體消抖方法。即檢測鍵閉合後延時5-10ms,讓前延抖動消失後再一次檢測鍵的狀態,如果仍保持閉合狀態電平,則確認真正有鍵按下。當檢測到按鍵釋放後,也要給5-10ms的延時,待後延抖動消失後才轉入該鍵處理程序。以下是具有消抖功能的鍵程序,只有按鍵按下再放開後才做一次鍵處理。
KEY_00:
JB P1.0, KEY_01 ;無鍵按下,查下一個鍵
LCALL DELAY ;延時10ms
JNB P1.0, $ ;鍵一直按下,等待
LCALL DELAY ;鍵松開,延時10ms
JB P1.0, KEY_00 ;一次按鍵完成,轉鍵盤處理程序
KEY_01: …
RET
(4) 鍵盤的編碼。
對於獨立式按鍵鍵盤,由於按鍵數目較少,可根據實際情況靈活編碼。對於矩陣式鍵盤,按鍵的位置由行號和列號唯一確定,所以分別對行號與列號進行二進制編碼,然後將兩值合成一個位元組,高4位是行號,低4位是列號。如10號鍵被按下時,列號讀回的值為1011,行號讀回的值為1101,此兩值合成為11011011=0DBH,據此值可轉到10號鍵處理程序。這種方式雖然簡單,但其離散性很大,在讀程序時必須要結合硬體電路。也可將讀回的鍵值按一定的方式運算後,算出對應的鍵值進行散轉,但這樣會增加程序的工作量,因而大多數單片機系統在鍵盤處理程序中只根據讀回的鍵值進行散轉。
(5) 常用的專用鍵盤晶元。
無論是利用CPU的I/O介面擴展鍵盤,還是利用擴展I/O晶元擴展鍵盤,由於均是用普通I/O介面擴展,如果要在單片機的程序中設計專用的鍵盤程序,特別是矩陣式鍵盤,其程序相對復雜一些。因而在較復雜一些的單片機系統中可選用專用的鍵盤晶元設計鍵盤。現常用的鍵盤擴展晶元有Intel8279、CH451、ICM7218、PCF8574等。
(6) 單片機對鍵盤的控制方式。
在單片機應用系統設計中,為了節省硬體,無論是採用獨立式鍵盤還是採用矩陣式鍵盤,單片機對鍵盤的控制有以下3種方式。
i 程序控制掃描方式。
這種方式只有單片機空閑時,才可調用鍵盤掃描子程序,查詢鍵盤的輸 入狀態是否改變。
ii 定時掃描方式。
單片機對鍵盤的掃描也可採用定時掃描方式,即單片機每隔一定的時間對鍵盤掃描一次。在這種方式中,通常採用單片機內部的定時器,產生10ms的定時中斷,CPU響應定時中斷請求後對鍵盤進行掃描,以查詢鍵盤是否有鍵按下。
iii 中斷掃描方式。
雖然採用程序查詢與定時對鍵盤的掃描方式時的程序編制簡單,但一個單片機系統在運行時的大多數時間里鍵盤基本是不工作的。為了進一步提高CPU的工作效率,可採用中斷方式。當鍵盤有鍵動作時產生中斷,CPU響應鍵盤中斷後,執行鍵盤中斷程序,判別鍵盤按下鍵的鍵號,並做相應處理。
❺ 51單片機鍵盤電路的兩種方式,各自的優缺點
獨立按鍵優點:可以直接讀取,檢測佔用時間較少,不受其他因素影響
缺點:佔用IO口資源較多,每一個按鍵都獨佔一個IO口。
矩陣鍵盤優點:佔用IO口資源較少。
缺點:必須掃描檢測按鍵情況,程序復雜,佔用時間較多。