按鍵切換狀態的不同C寫法對比

2021-07-26 10:04:14 字數 1618 閱讀 3306

給定乙個按鍵,以及乙個狀態輸出(如乙個led),按下一次按鍵後led燈改變一次狀態,再按一次按鍵led再次切換狀態,這是嵌入式程式設計中乙個很簡單的任務,但要想達到很好的效果並不容易,一下對比幾種c寫法(以arduino為例):

bool buttonstate = 1;

bool x = 1;

void loop()

else

if (buttonstate == low && x==0)

delay(1);

}

這種寫法使用乙個x變數來希望使得每次按鍵後切換一次led狀態,但這個程式有乙個問題是當按鍵按下時間較長時,程式會不斷進入判斷並不斷切換led的狀態,導致每次按下按鍵後led都會閃爍多次,鬆開後的狀態也是隨機的,儘管可以通過增加兩次判斷的延時稍稍改善,但改善效果很低,過大的時延也使得其他程式和按鍵本身響應速度降低,基本是不可取的。

bool newbuttomstate = 1;

bool oldbuttonstate = 1;

bool ledstate = 1;

void loop()

} oldbuttonstate = newbuttonstate; //record the old key state

}

程式二通過檢測按鍵之前的狀態,每次切換led時都需要判斷按鍵之前的狀態(高電平)和按下的狀態(低電平)同時滿足。這樣效果比程式一要好了很多,即使按鍵一直被按下也不會反覆進入判斷語句切換led的狀態,同時考慮到按鍵消抖,每次判斷後延時一段時間,再判斷一次。這個程式本身應該考慮比較周全了,但實際試驗中發現,當按下按鍵時間較長時再鬆開,led常常出現連續開關兩次,且改變延時時間仍然不能有所改善,仔細考慮和查閱一些資料後,改進為第三種程式寫法,終於得到比較好的效果

bool newbuttomstate = 1;

bool oldbuttonstate = 1;

bool ledstate = 1;

void loop()

oldbuttonstate = newbuttonstate;

delay(1); //the delay'position is very very important

}

程式三和程式二似乎沒有什麼區別,而且反而還去掉了按下狀態延時消抖的語句,似乎應該反而效果不如程式二,但實際上我用乙個抖動很差的開關做了多次試驗的結果是,程式三基本達到了接近完美的效果。響應非常迅速而幾乎沒有出現過任何錯誤(程式二大約會出現一半的錯誤響應)。

這其中的奧秘到底在哪呢,仔細觀察程式三,除了去掉了按鍵按下的再次判斷的延時消抖,唯一的區別就是在末尾加了乙個時延語句,而正是這個延時語句的位置使得它有著遠遠優於程式二的效果

原因在於實際中使用的物理按鍵的抖動特點。實際上大多數常用按鍵在按下時(觸點閉合)的抖動並不顯著,而抖動主要出現在按下後鬆開的階段(觸點離開),這個大家可以自己用示波器做一些相關實驗(以後有時間我可以另外開帖用示波器做一系列試驗)。因此基於這個特點,我在程式末尾,即按鍵鬆開後的階段新增乙個延時就可以有效防止鬆開階段的抖動影響,這個延時值很小,對於我用的按鍵,我設定延時1ms就有很好的效果。而我又嘗試將按下階段的消抖語句去除,發現沒有任何影響。

Vim實戰手冊(2)常用的狀態切換按鍵

1 normal mode insert mode i 小寫字母i,在游標位置插入 a 小寫字母a,在游標的下乙個位置插入 i 大寫字母i,在游標所在行的第乙個非空格處插入 a 大寫字母a,在游標所在行的最後乙個字元處插入 o 小寫字母o,在游標所在行的下一行處插入新行 o 大寫字母o,在游標所在行...

整理 狀態機的兩種寫法對比

狀態機可以用兩種方法實現 豎著寫 在狀態中判斷事件 和橫著寫 在事件中判斷狀態 這兩種實現在本質上是完全等效的,但在實際操作中,效果卻截然不同。豎著寫 在狀態中判斷事件 c 片段 cur state nxt state switch cur state else if e1 event else i...

Linux下C語言檢測多個按鍵按下狀態的方法

在需要同時監聽多個按鍵按下狀態的情況下,可以通過監聽 dev input event事件的方法來判斷按鍵的狀態。比如對於通過鍵盤控制小車時,有可能多個方向鍵同時按下,需要同時監測到,通過前面文章的方法可以有效監控單個按鍵的訊息,但是不能同時監控多個按鍵同時按下的資訊。需要通過記錄鍵盤的按下和釋放事件...