2020年5月23日 星期六

四.3 七段LED顯示器按鍵按下次數顯示實習


一般常用的輸入元件不外開關(switch)與按鍵(button)中的開關算是最簡單也最容易使用了而按鍵由於機械結構的關係就比較麻煩一點;【圖4】是一個按鍵被按下與放開時在輸出接點所產生的信號波形由於按鍵使用的機械彈片有慣性因此會產生所謂的彈跳(bounce)現象使得按鍵每次按下或放開時會出現次數不定的脈波輸出如果不處理的話就會測量到錯誤的按鍵次數。


圖48 按鍵按下與放開時接點信號彈跳狀態圖


要解決按鍵彈跳的問題有很多種方法大致上可分硬體與軟體兩種除非特別的原因不然為了節省成本當然是以軟體的方式為之最多一般來說按鍵按下或者放開後會出現彈跳的時間約在幾個毫秒(ms)的區間很少超過10ms的因此只要在測到按鍵動作之後延遲一段過這個長度的時間後就可以避開按鍵彈跳的問題了


功能與動作說明

1程式啟動時先讓七段LED顯示器每隔一秒依序顯示數字0~9及A~F共16個數字顯示完後會停在數字’0’上

2每當按鍵測試到被按下時段LED顯示器上的數字會立即加1這時即使按鍵被長按著也不會再動作直到按鍵放開為止當數字增加到最後的數字’9’時再按下按鍵的話會重新由’0’開始顯示並且一直循環下去


電路圖

圖49 七段LED顯示器麵包板接線與電路圖


程式說明與列表

2~5行的程式定義了控制七段LED顯示器輸出腳位陣列(segPin[]),和按鍵輸入的腳位”key”(第15腳),以及儲存按鍵輸入次數的變數”count”;在接著的初始化(setup())程式區中(7~20行),先將所使用到的8隻IO接腳設定為輸出(9、10行),然後以for()迴圈的方式將0~F共16個數字顯示在七段LED顯示器上(13~17行),剩下的程式會在顯示完後讓七段LED顯示器畫面停留在數字’0’上。

在主迴圈程式(22~36行)中會不斷的測試按鍵是否被按下若有則延遲20ms後再測試一次之所以會這樣做除了在等待按鍵的彈跳現象過去之外要判斷之前測到的信號是否為雜訊由於一般雜訊的寬度都小於ms所以如果按鍵輸入還在20ms之後是邏輯’1’狀態才是真正按鍵被按下而非突發的雜訊


23   if(digitalRead(key))         // 測試按鍵(Pin腳GPIO15)是否被按下(=1)?

24   {

25     delay(20);           // 若是則延遲20mS以等待按鍵的彈跳狀態結束

26     if(digitalRead(key))            // 再次測試按鍵狀態是否穩定


如果按鍵被按下則先將儲存按鍵次數的變數”count”加一然後測試次數是否已經超過上限值’9’假如超過的話便讓它歸零接著再呼叫「Seg7_Display()」這個副程式把按鍵的次數值顯示在七段LED顯示器上。最後的兩行程式會一直等待按鍵放開後才會讓程式繼續重新執行下去。


33    while(digitalRead(key))         // 等待按鍵放開(key=0)

34      delay(10);                    // 防止看門狗重置(Reset)

以下是完整的程式列表:

 

// 設定七段LED顯示器在ESP8266上使用的接腳編號

const byte  segPin[]={16,5,4,0,2,14,12,13};  

//   對應的段位   a, b, c, d, e, f, g, dp

const byte key=15; // 按鍵輸入腳位

byte  count=0;

 

void setup() {

  // 將 ESP8266 上所使用到的七段LED接腳以for()迴圈的方式都設定為輸出:

  for(byte i=0;i<8;i++)

    pinMode(segPin[i],OUTPUT);

    

  // 以for()迴圈的方式將0~F共16個數字顯示在七段LED顯示器上:

  for(byte i=0;i<16;i++)

  {

    Seg7_Display(i);

    delay(1000);                    // 等候1秒

  }

  Seg7_Display(count);              // 最後顯示'0'

  delay(1000);

}

 

void loop() {

  if(digitalRead(key))         // 測試按鍵(Pin腳GPIO15)是否被按下(=1)?

  {

    delay(20);              // 若是則延遲20mS以等待按鍵的彈跳狀態結束

    if(digitalRead(key))            // 再次測試按鍵狀態是否穩定

    {

      count++;                      // 將按鍵次數加1

      if(count==10)                 // 測試按鍵次數是否已到達上限10

        count=0;                    // 若是則歸0

      Seg7_Display(count);          // 按鍵次數值顯示在七段LED上

    }

    while(digitalRead(key))         // 等待按鍵放開(key=0)

      delay(10);                    // 防止看門狗重置(Reset)

  }

}

 

// 七段LED顯示器數字顯示副程式:

void  Seg7_Display(byte number)

{    

  // 共陽式七段LED顯示器的數字段位陣列值: 0/亮 1/滅

         // 數字 0~3

  const byte  segNum[]={ B11000000,B11111001,B10100100,B10110000,    

           // 數字 4~7

                       B10011001,B10010010,B10000010,B11111000,                                 // 數字 8~b

B10000000,B10010000,B10001000,B10000011,

                  // 數字 C~F

                B11000110,B10100001,B10000110,B10001110 };

                   // 將8個數字段位值取出後顯示在對應的輸出段位腳上:

    for(byte j=0;j<8;j++)     { 

      if(bitRead(segNum[number],j))   // 測試選擇到的數字段位值是否為'1'?

        digitalWrite(segPin[j],1);  // 若是則對應的段位腳設定輸出'1'

      else

        digitalWrite(segPin[j],0);  // 反之則對應的段位腳設定輸出'0'

    }

}   // Seg7_Display副程式結束    


程式名稱key1_seg1.ino


沒有留言:

張貼留言