1. 程式人生 > >普中微控制器 獨立按鍵word文件20180923

普中微控制器 獨立按鍵word文件20180923

第六講 獨立按鍵

按鍵是什麼東西,我想這個就不必由我向各位闡述了。嗯,如你所見,按鍵種類繁多,功能有簡有繁,極大的充斥著我們的生活。但是無論如何,所有的按鍵其實都有一個原型,來源於同一種原理,所有的按鍵無論多複雜,多華麗,都是從這樣一個原型發展而成的。好比你就算長的再帥,你也是隻猩猩變來的,呵呵。我們平日所見到的絕大部分的按鍵,其實都可以歸類為一種,叫“接觸式按鍵”。下圖為一個典型的接觸式按鍵(又稱輕觸開關)。

需要特別說明的是,這裡說的“接觸”,是指機械層面上的接觸,而不是感光或者某些特殊塗層(比如觸控式螢幕)一類的接觸。所以,按鍵的工作特性其實是一種機械特性,下文會詳細說明。

如上圖,請對照圖一想象,1、2、3、4 分別對應按鍵的四個引腳,其中藍色的線表示按鍵未被按下之時的狀態,我成為初始狀態,它是不導通的;而綠色的線是卻永久導通的。各位明白了麼,其實是兩個相同的結構連在一起了。我們只要將需要按鍵開關作用的線路分別接在1、3 和2、4 的任意取一組合,概括起來就是(1,2)、(1,4)、(3,2)、(3,4)四種組合,都可以起到我們預期的開關作用。

相信以上說明使大家對按鍵的工作原理有了個比較清晰的認識了,現在來說說一個小知識。先看下圖(圖4):

首先說明的是,上圖的連法是不允許的,因為當按鍵按下之後,電源和地短接,會將導線直接燒燬。但是此處用作特例,假設導線不會燒燬。現在來提出一個問題,當按鍵按下以後,請問如果這時用萬用表測量導線上任何一處的電壓,得到的結果是VCC 還是GND 的電壓?

答案是:GND,即表示測出的電壓為0V。為什麼呢,因為導線上,對於兩端的電平是一種類似於程式語言邏輯運算裡面的“與”,即對於導線兩端:有零即為零,只有全為一是才為一。理解了這點,按鍵的工作前提就有了。

鍵盤分為編碼鍵盤和非編碼鍵盤。鍵盤上閉合鍵的識別由專用的硬體編碼器實現,併產生鍵編碼號或鍵值的稱為編碼鍵盤,如計算機鍵盤。而靠軟體程式設計來識別的鍵盤稱為非編碼鍵盤,在微控制器組成的各種系統中,用的較多的是非編碼鍵盤。非編碼鍵盤又分為獨立鍵盤和行列式鍵盤(常說的矩陣鍵盤)。在這一講中我們介紹一下微控制器中鍵盤使用。

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

我們先來說一下,按鍵常常遇到的問題—抖動問題。

還以圖四為例,按鍵未按下之前,圖四按鍵左端的導線因為連在VCC 上而顯示高電平,右端顯示低電平,按鍵按下後,按鍵閉合,整個導線都顯示低電平,然後按鍵鬆開,又回到按鍵按下之前的點評狀態。如果只考察按鍵左端的電平變化,應該是上圖中所顯示的一個負脈衝波形。但是,實際上,正確的波形應該是下圖。相比於上圖,大家都看到了在高低電平直接有一段鋸齒一樣的波形,這就是所謂的按鍵抖動。

為什麼會有按鍵抖動呢,原因很簡單,接觸式按鍵是靠機械的接觸來實現開關作用的。這種接觸方式就註定了它要經歷一個“接觸不穩定——正在穩定中——徹底穩定”的一種過程。就好比你用手抓緊一顆石頭,即使你一開始就很用力的握緊,也不可能馬上就達到最緊的狀態,也要經歷一個從握住到最緊握的過程。那麼在這個過程裡,接觸式按鍵就處於一種徘徊在“閉合”與“斷開”兩者之間的狀態。體現在電路中,就是在一小段時間內有非常多的“按下——擡起”動作。而這段抖動的時間,大概是10~20 毫秒,依不同的環境條件而定。

解決這個問題常見的方法有軟體去抖動和硬體去抖動。

我們解釋一下抖動:關於按鍵去抖動的解釋,我們在手動按鍵的時候,由於機械抖動或是其它一些非人為的因素很有可能會造成誤識別,一般手動按下一次鍵然後接著釋放,按鍵兩片金屬膜接觸的時間大約為50ms 左右,在按下瞬間到穩定的時間為5-10ms,在鬆開的瞬間到穩定的時間也為5-10ms,如果我們再首次檢測到鍵被按下後延時10ms 左右再去檢測,這時如果是干擾訊號將不會被檢測到,如果確實是有鍵被按下,則可確認,以上為按鍵識別去抖動的原理。

獨立按鍵:

我們先將一下獨立按鍵的使用方法,開發板獨立按鍵電路圖如下:

獨立按鍵一共5個,分別連線在微控制器的P3.0到P3.4口。去抖動的方式,我們採用軟體延時的方法。過程如下:

  1. 先設定IO口為高電平(一般上電預設就為高)
  2. 讀取IO口電平確認是否有按鍵按下
  3. 如有IO電平為低電平後,延時幾個ms
  4. 再讀取該IO電平,如果任然為低電平,說明對應按鍵按下
  5. 執行相應按鍵的程式

/**************************************************************************

* 實驗名              : 獨立按鍵實驗

* 使用的IO       : LED使用P2,鍵盤使用P3.0、P3.1、P3.2、P3.3

* 實驗效果       : 按下K1鍵,滅掉LED,按下K2鍵,開啟所有的LED,按下K3鍵,LED左移一位,按下K4鍵,LED右移一位。

*   注意                   :由於P3.2口跟紅外線共用,所以做按鍵實驗時為了不讓紅外線影響實驗

*效果,最好把紅外線先取下來。

**************************************************************************/

#include<reg51.h>

#include<intrins.h>

#define GPIO_LED P2

sbit K1=P3^0;

sbit K2=P3^1;

sbit K3=P3^2;

sbit K4=P3^3;

void Delay10ms( );   //延時10ms

/**************************************************************************

* 函式名         : main

* 函式功能         : 主函式

* 輸入           : 無

* 輸出          : 無

**************************************************************************/

void main(void)

{

    unsigned int i,j;

    while(1)

    {

        if(K1==0)       //檢測按鍵K1是否按下

        {

            Delay10ms();    //消除抖動

            if(K1==0) //再次檢測按鍵是否按下

                j=0;

            while((i<50)&&(K1==0)) //檢測按鍵鬆手檢測,如果不鬆手超過延時也會自動結束等待

            {

                Delay10ms();

                i++;

            }

            i=0;

        }      

        if(K2==0)          //檢測按鍵K2是否按下

        {

            Delay10ms();

            if(K2==0)

                j=0xff;

            while((i<50)&&(K2==0))

            {

                Delay10ms();

                i++;

            }

            i=0;

        }          

        if(K3==0)              //檢測按鍵K3是否按下

        {

            Delay10ms();

            if(K3==0)

            {

                if((j==0)||(j==0xff))      //如果當前狀態是全亮的或者全滅的,就點亮他的第一盞燈

                {

                   j=0xfe;

                }

                else

                   j=_crol_(j,1);         //左移一位

            }

            while((i<50)&&(K3==0))

            {

                Delay10ms();

                i++;

            }

            i=0;

        }

        if(K4==0)                  //檢測按鍵K4是否按下

        {

            Delay10ms();

            if(K4==0)

            {

                if((j==0)||(j==0xff))

                {

                   j=0xfe;

                }

                else

                   j=_cror_(j,1);     //右移一位

            }

            while((i<50)&&(K4==0))

            {

                Delay10ms();

                i++;

            }

            i=0;

        }

        GPIO_LED=j;

    }              

}

/*************************************************************************

* 函式名         : Delay10ms

* 函式功能         : 延時函式,延時10ms

* 輸入           : 無

* 輸出          : 無

**************************************************************************/

void Delay10ms(void)   //誤差 0us

{

    unsigned char a,b,c;

    for(c=1;c>0;c--)

        for(b=38;b>0;b--)

            for(a=130;a>0;a--);

}

下載獨立按鍵控制led燈.hex,觀察實驗結果。

實驗效果是:按下K1鍵,滅掉LED,按下K2鍵,開啟所有的LED,按下K3鍵,LED左移一位,按下K4鍵,LED右移一