1. 程式人生 > 實用技巧 >51微控制器 第六節 矩陣鍵盤

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)的第四章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...可以配置模板;

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