一般常用的輸入元件不外開關(switch)與按鍵(button),中的開關算是最簡單也最容易使用了,而按鍵由於機械結構的關係,就比較麻煩一點;【圖4、8】是一個按鍵被按下與放開時在輸出接點所產生的信號波形,由於按鍵使用的機械彈片有慣性,因此會產生所謂的彈跳(bounce)現象,使得按鍵每次按下或放開時會出現次數不定的脈波輸出,如果不處理的話,就會測量到錯誤的按鍵次數。
圖4、8 按鍵按下與放開時接點信號彈跳狀態圖
要解決按鍵彈跳的問題有很多種方法,大致上可分硬體與軟體兩種,除非特別的原因,不然為了節省成本,當然是以軟體的方式為之最多。一般來說按鍵按下或者放開後,會出現彈跳的時間約在幾個毫秒(ms)的區間,很少超過10ms的,因此只要在測到按鍵動作之後,延遲一段過這個長度的時間後,就可以避開按鍵彈跳的問題了。
◎功能與動作說明:
1、程式啟動時先讓七段LED顯示器每隔一秒依序顯示數字0~9及A~F共16個數字,顯示完後會停在數字’0’上。
2、每當按鍵測試到被按下時,段LED顯示器上的數字會立即加1,這時即使按鍵被長按著也不會再動作,直到按鍵放開為止;當數字增加到最後的數字’9’時,再按下按鍵的話會重新由’0’開始顯示,並且一直循環下去。
◎ 電路圖:
圖4、9 七段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
沒有留言:
張貼留言