51單片機 第六節 矩陣鍵盤


本筆記默認學習者已擁有:
1.Keil5和stc燒寫工具 等各種軟件、驅動、環境;
2.有一個屬於自己的 51單片機開發板及相關零件 ;
3.認識C語言的語法;
本人使用的51開發板為 郭天祥C51 TX-1C增強版開發板 ;
本筆記根據B站up主:江科大自化協的教學視頻 整理得到ヾ(•ω•)




6-1 矩陣鍵盤

數碼管顯示的弊端:需要不斷地掃描,而且顯示的內容也非常少;
通過串口將數據傳輸到電腦上顯示:太依賴電腦了,顯得單片機系統很不獨立;

矩陣鍵盤I/O口由 16個 減少到 8個,矩陣連接地越多,減少I/O口越明顯;
視頻的1080P 的 像素比例為 1920 * 1080,有2,073,600個像素點,要顯示彩色還需要3色LED,
若每個單獨判斷,則需6,220,800個I/O口,但如果連接成矩陣形式的話,只需 (1920 +1080) * 3=9000 個I/O口即可;
減少 I/O口 效率是十分明顯的;




原理分析

上圖為TX-1C的原理圖部分,注意接口與視頻中不同

1.觀察 獨立按鍵 與 矩陣按鍵 的區別與相同之處;
發現 獨立按鍵 公共端都連接在 GND 上,另一端都分別連接在 I/O口 上;
如果將 矩陣鍵盤 一行四個 單獨拿出來看,
如果這一行的公共端連接在 GND 上,就會發現 矩陣鍵盤 與 獨立按鍵 基本相似;

先理解簡單的,再將復雜的轉化為簡單的,這樣復雜的就變成簡單的了;

2.這就是 按行掃描,第一個接到 GND 上,使用四個 if 進行判斷

\[\begin{cases} if(P13==0) \to s1按下了 \\if(P12==0) \to s2按下了 \\if(P11==0) \to s3按下了 \\if(P10==0) \to s4按下了 \end{cases} \]

3.對於接下來每行的判斷,若想判斷第二行,
給第一行 1,給第二行 0,給第三、四行 1,判斷四個I/O口;
4.這樣 逐行掃描,就可以實現 矩陣鍵盤的掃描了;

但是視頻中的 P15口 還連接到了 其他模塊(連接到了BZ口),會不時給 0或1;

這個模塊 相當於 一個驅動器,增大輸出電流能力,而 BZ口連接到了蜂鳴器;
視頻開發板中的蜂鳴器是一種無源蜂鳴器,如BZ口以一定頻率高低變化,蜂鳴器就會響;

5.這樣逐行掃描的話,蜂鳴器就會不自主地響,這是由於引腳沖突造成的;
6.為避免這種問題,即采用 逐列掃描

而引腳沖突在TX-1C中尤為嚴重,P3.4、P3.5口 都被 LCD1602占用,且P3.4口為使能端,故本筆記使用3*4矩陣鍵盤,代碼采用逐列掃描
本人能力有限,無法找到有效的解決端口占用的方法,只能廢掉s6,s10,s14,s18這一列按鍵了;




關於單片機的I/O口

1.單片機的I/O口的模式為一種 弱上拉 模式,又叫 准雙向口
2.即I/O口 既可以輸入(Input),又可以輸出(Output);

一個I/O口給高電平 1,另一個I/O口給低電平 0,將兩者連接在一起,雖然這確實相當於短路,但實際上並不會短路;

3.弱上拉,輸出 1 的驅動能力是有限的,輸出 0 的驅動能力是相對較強的,就是說 弱上拉,強下拉

4.如上圖為單片機的內部結構簡化示意圖;
若輸出高電平,就通過一個電阻接到VCC,若輸出低電平,就直接接到GND;
讀入會通過 斯密特觸發器 進行讀入;
若讀入時外界 什么都沒接(或接入高電平),那么讀入的是高電平;
若外界直接接到GND(輸入0),雖然輸出的是 1 ,但它讀入的 仍然是 0;

P1、P2、P3引腳配置 均采用 弱上拉 的工作模式,P0使用的是 開漏輸出 的工作模式,
但開發板上 P0 已經接到 上拉電阻 了,所以說 開發板上 P0、P1、P2、P3 都是這種工作模式,而且不可更改;
而現在 STC公司推出的 高系列 單片機 的I/O模式 都是可以配置的,比如 推挽輸出
推挽輸出 才是 沒有上拉電阻,高電平直接接到VCC,低電平直接接到GND,其只能輸出不能輸入;
還有一種 高阻輸入,高阻輸入既沒有上拉也沒有下拉,僅作輸入,以減少上拉電阻對輸入的影響;
還有一種 開漏輸出
有關模式的詳細介紹,可以參考STC89C52.pdf(提取碼:ncst)的 第4章STC89C52系列單片機的I/O口結構 ;

准雙向口輸出類型可用作輸出和輸入功能而不需重新配置口線輸出狀態。這是因為當口線
輸出為1時驅動能力很弱,允許外部裝置將其拉低。當引腳輸出為低時,它的驅動能力很強,
可吸收相當大的電流。

Q:驅動LED為什么低電平點亮,高電平熄滅?
A:因為其輸出 1 時驅動能力很弱;

Q:按鍵為什么也采用 低電平視為按下,高電平視為未按,為什么不將公共端接VCC,讀取高電平呢?
A:因為輸出低電平,再把它拉高,就會產生很大的電流,所以一般按鍵檢測0,接到低電平上;




MatrixKey.c

#include<reg51.h>
#include<Delayms.h>
/**
  * @brief  3*4矩陣鍵盤讀取按鍵鍵碼
  * @param  無
  * @retval KeyNumber 按下按鍵的鍵碼值
	          如果按鍵按下不放,程序會停留在此函數,松手的一瞬間,返回按鍵鍵碼,沒有按鍵按下時,返回0
*/
unsigned char MatrixKey(){
	unsigned char KeyNumber=0;
	
	P3=0xFF;
	T1=0; 
	if(RXD==0){ Delayms(20); while(RXD==0); Delayms(20); KeyNumber=1; }
	if(TXD==0){ Delayms(20); while(TXD==0); Delayms(20); KeyNumber=4; }
	if(INT0==0){ Delayms(20); while(INT0==0); Delayms(20); KeyNumber=7; }
	if(INT1==0){ Delayms(20); while(INT1==0); Delayms(20); KeyNumber=10; }
	
	P3=0xFF;
	WR=0; 
	if(RXD==0){ Delayms(20); while(RXD==0); Delayms(20); KeyNumber=2; }
	if(TXD==0){ Delayms(20); while(TXD==0); Delayms(20); KeyNumber=5; }
	if(INT0==0){ Delayms(20); while(INT0==0); Delayms(20); KeyNumber=8; }
	if(INT1==0){ Delayms(20); while(INT1==0); Delayms(20); KeyNumber=11; }
	
	
	P3=0xFF;
	RD=0; 
	if(RXD==0){ Delayms(20); while(RXD==0); Delayms(20); KeyNumber=3; }
	if(TXD==0){ Delayms(20); while(TXD==0); Delayms(20); KeyNumber=6; }
	if(INT0==0){ Delayms(20); while(INT0==0); Delayms(20); KeyNumber=9; }
	if(INT1==0){ Delayms(20); while(INT1==0); Delayms(20); KeyNumber=12; }
	
	return KeyNumber;
}



MatrixKey.h

#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__

unsigned char MatrixKey();

#endif



矩陣鍵盤.c

#include<reg51.h>
#include<Delayms.h>
#include<LCD1602.h>
#include<MatrixKey.h>
unsigned char KeyNum;
void main(){
	LCD_Init();
	LCD_ShowString(1,1,"Hello World!");
	while(1){
		KeyNum=MatrixKey();
		if(KeyNum) LCD_ShowNum(2,1,KeyNum,2);
	}
}

運行結果如下




6-2 矩陣鍵盤密碼鎖.c

#include<reg51.h>
#include<Delayms.h>
#include<LCD1602.h>
#include<MatrixKey.h>
unsigned char KeyNum;
unsigned int Password=0;
void main(){
	
	LCD_Init();
	LCD_ShowString(1,1,"Password:");
	LCD_ShowNum(2,1,Password,4);
	while(1){
		KeyNum=MatrixKey();
		if(KeyNum){
			if((KeyNum<=9 || KeyNum==11) && Password<999){ //按下數字鍵 且 Password不到四位
					if(KeyNum<=9) Password=Password*10+KeyNum;
					else Password=Password*10+0; 
					LCD_ShowNum(2,1,Password,4);
				}
				if(KeyNum==12){ //按下確認鍵
					if(Password==2345) LCD_ShowString(1,14,"OK "); //正確顯示OK
					else LCD_ShowString(1,14,"ERR"); //錯誤顯示ERR
					Password=0; //密碼清零
					LCD_ShowNum(2,1,Password,4);
				}
				if(KeyNum==10){ //按下退格鍵
					Password/=10; //清除最后一位
					LCD_ShowNum(2,1,Password,4);
				}
		}
	}
}
/*
 s7   s8  s9
 1    2   3

 s11  s12 s13
 4    5   6

 s15  s16 s17
 7    8   9

 s19  s20 s21
 退格  0   確認

*/

部分運行結果演示

運行結果請使用TX-1C開發板進行嘗試(ง •_•)ง




軟件相關

1.在 Keil5 編譯程序時,會發現軟件提醒 函數為使用的警告;
2.右鍵Target 1 ——>點擊 Options for Target 'Target 1'——>點擊 BL51 Misc

3.Disable Warning Numbers 欄 填寫 警告編號 16,該類型的警告便不再提醒;


1.在 Keil5 界面的左側,有四個快捷欄
2. Project即我們的工程樹;

3.Books中有全英文的用戶手冊等 指導書;

4.Functions可以列出當前文件里所有的函數,雙擊可以跳轉到函數代碼位置;

5.Templates能快速編寫代碼,其中有一些代碼模板,雙擊能直接寫出代碼;

右鍵——>點擊Configure Templates...可以配置模板;

|的意思為,插入此模板后,光標會移到|的位置;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM