獨立按鍵實驗

2022-01-13 22:00:08

按鍵簡介

        按鍵是一種電子開關,使用時,按下按鈕,則開關接通,鬆開手時, 開關斷開。開發板上使用的按鍵及內部簡易圖如下圖所示:

         按鍵管腳兩端距離長的表示預設是導通狀態(1、2),距離短的預設是斷開狀態(1、3), 如果按鍵按下,初始導通狀態變為斷開,初始斷開狀態變為導通。 通常的按鍵所用開關為機械彈性開關,當機械觸點斷開、閉合時,電壓訊號如下圖所示:

         由於機械點的彈性作用,按鍵開關在閉合時不會馬上穩定的接通,在斷開時也不會一下子斷開,因而在閉合和斷開的瞬間均伴隨著一連串的抖動。抖動時間的長短由按鍵的機械特性決定的,一般為 5ms 到 10ms。按鍵穩定閉合時間的長短則由操作人員的按鍵動作決定的,一般為零點幾秒至數秒。按鍵抖動會引起按鍵被誤讀多次。為了確保 CPU 對按鍵的一次閉合僅作一次處理,必須進行消抖。

         按鍵消抖有兩種方式,一種是硬體消抖,另一種是軟體消抖。為了使電路更加簡單,通常採用軟體消抖。本文使用的開發板也是採用軟體消抖。通常而言,一個簡單的按鍵消抖就是先讀取按鍵的狀態,如果讀取到按鍵按下之後,延時 10ms,再次讀取按鍵的狀態,如果按鍵還是按下狀態,那麼說明按鍵已經按下。其中延時 10ms 就是軟體消抖處理。至於硬體消抖,此處不多做贅述。微控制器常用的軟體去抖動方法:

  1. 先設定 IO 口為高電平(由於開發板 IO 都有上拉電阻,所以預設 IO 為高電平)
  2. 讀取 IO 口電平確認是否有按鍵按下。
  3. 如有 IO 電平為低電平後,延時幾個毫秒。
  4. 再讀取該 IO 電平,如果仍然為低電平,說明按鍵按下。
  5. 執行按鍵控制程式。

         獨立按鍵電路構成是由各個按鍵的一個管腳連線在一起接地,按鍵其他引腳分別接到微控制器 IO 口。

         微控制器的 IO 口既可作為輸出也可作為輸入使用,當檢測按鍵時用的是它的輸入功能,獨立按鍵的一端接地, 另一端與微控制器的 I/O 口相連,開始時先給該 IO 口賦一高電平,然後讓微控制器不斷地檢測該 I/O 口是否變為低電平,當按鍵閉合時,即相當於該 I/O 口通過按鍵與地相連,變成低電平,程 序一旦檢測到 I/O 口變為低電平則說明按鍵被按下,然後執行相應的指令。

硬體部分

         使用到硬體資源如下:

  1. LED 模組中 D1 指示燈
  2. K1 按鍵

         獨立按鍵模組電路如下圖所示:

          由上圖可知,該模組電路是獨立的,8 個獨立按鍵的控制管腳並未直接連線到 51 微控制器的 IO 上,而是連線到 JP1 端子上,所以使用任意微控制器管腳都可以,這裡使用 P3.0 口來檢測 K1 按鍵,使用 P2.0 管腳控制 D1 指示燈。

原始碼

           KEY_SCAN 函數帶一個形參 mode,該引數用來設定是否連續掃描按鍵,如果 mode 為 0,只能操作一次按鍵,只有當按鍵鬆開後才能觸發下次的掃描,這樣做的好處是可以防止按下一次出現多次觸發的情況。如果 mode 為 1,函數是支援連續掃描的,即使按鍵未鬆開,在函數內部有 if(mode==1)這條判斷語句,因 此 key 始終是等於 1 的,所以可以連續掃描按鍵,當按下某個按鍵,會一直返回這個按鍵的鍵值,這樣做的好處是可以很方便實現連按操作。

#include "reg52.h"

typedef unsigned int u16;//使用關鍵字 typedef 對系統預設資料型別 unsigned int 重新命名
typedef unsigned char u8;
 
/*定義獨立按鍵的控制腳*/
sbit KEY1=P3^1;
sbit KEY2=P3^2;
sbit KEY3=P3^3;
sbit KEY4=P3^4;

/*定義LED控制腳*/
sbit LED1=P2^1;
sbit LED2=P2^2;
sbit LED3=P2^3;
sbit LED4=P2^4;

/*使用宏定義獨立按鍵按下的鍵值*/
#define KEY1_PRESS 1   //K1按下
#define KEY2_PRESS 2   //K2按下
#define KEY3_PRESS 3   //K3按下
#define KEY4_PRESS 4   //K4按下
#define KEY_UNPRESS 0  //未有按鍵按下

void delay_10us(u16 ten_us)//延時函數,ten_us=1 時,大約延時 10us
{
 	while(ten_us--);
}

u8 KEY_SCAN(u8 mode)//檢測獨立按鍵是否按下,按下則返回對應鍵值給主函數
{
 	static u8 key=1;

	if(mode) //連續掃描按鍵,防止按鍵按下無效
		key=1;
	if(key==1&&(KEY1==0||KEY2==0||KEY2==0||KEY3==0||KEY4==0)) //從此處開始做消抖處理,先第一次確認是否有按鍵按下
	{
	 	delay_10us(1000);//消抖
		key=0;
		if(KEY1==0)	 //再次確認是哪個按鍵按下,消抖處理結束
			return KEY1_PRESS;
		else if(KEY2==0)
			return KEY2_PRESS;
		else if(KEY3==0)
			return KEY3_PRESS;
		else if(KEY4==0)
			return KEY4_PRESS;
	}
	else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)
	{
	 	key=1;
	}
	 return KEY_UNPRESS;
}

void main(void)	   //主函數
{
	u8 DL_LED=0;	
	while(1)
	{
	 	 DL_LED=KEY_SCAN(0); //接收函數返回的獨立按鍵按下的鍵值,用這個值來確定點亮那個LED燈
		 if(DL_LED==1)	 //檢測按鍵K1是否按下
		 	LED1=!LED1;		//LED1狀態翻轉,剛開始第一次按下按鍵,LED1埠輸出高電平,LED點亮 ,第二次按下時,狀態翻轉,輸出低電平
		 if(DL_LED==2)	 //檢測按鍵K2是否按下
		 	LED2=!LED2;		//LED2狀態翻轉
		 if(DL_LED==3)	 //檢測按鍵K3是否按下
		 	LED3=!LED3;		//LED3狀態翻轉
		 if(DL_LED==4)	 //檢測按鍵K4是否按下
		 	LED4=!LED4;		//LED4狀態翻轉
	}
}

現象

          按下「獨立按鍵」模組中相應按鍵,控制對應的LED指示燈亮滅。