在按鍵的上方有4個撥動開關。開關與按鍵,在原理和使用方法上都是很相似的,但有不一樣的用途——按鍵按下後鬆開就會彈起,而開關能夠保存其狀態。html
<switch.h> 定義了與開關相關的函數。switch_status 對應 button_down ,switch_changed 對應 button_pressed ,使用與按鍵是基本相同的。函數
這裏經過一個異常簡單的例子來演示開關函數的使用,並說明開關操做與按鍵的細微差異:使LED與開關狀態保持同步。spa
仿照上一篇教程,咱們能夠簡單地把 button_pressed 替換爲 switch_changed :code
1 #include <ee1/led.h> 2 #include <ee1/switch.h> 3 #include <ee1/delay.h> 4 5 int main() 6 { 7 led_init(); 8 switch_init(PIN_NULL, PIN_NULL); 9 while (1) 10 { 11 if (switch_changed(SWITCH_0)) 12 led_flip(LED_GREEN); 13 delay(40); 14 } 15 }
若是把按鍵撥到關(即下)再復位單片機,一切安好,可是若是一開始是開的狀態,LED的狀態會老是與開關相反。爲何呢?由於開關能夠保存狀態,這是第一個差異。htm
因此,咱們能夠每次得知開關狀態改變後讀取開關狀態,並傳給LED:blog
1 #include <ee1/led.h> 2 #include <ee1/switch.h> 3 #include <ee1/delay.h> 4 5 int main() 6 { 7 led_init(); 8 switch_init(PIN_NULL, PIN_NULL); 9 while (1) 10 { 11 if (switch_changed(SWITCH_0)) 12 led_set(LED_GREEN, switch_status(SWITCH_0)); 13 delay(40); 14 } 15 }
這也引出了第二個差異——當 switch_changed 返回 true 時,咱們不能直接知曉開關的狀態,須要手動調用 switch_status ;而對於相應的按鍵操做,咱們知道此時按鍵必定處於按下的狀態。教程
若是復位時開關狀態爲開,除了第一次撥動按鍵之前,LED老是與按鍵同步的。然而咱們的要求是保持同步,固然包括一開始的時候。爲了得到正確的初始狀態,咱們能夠在進入主循環前添加如下代碼:ip
1 if (switch_status(SWITCH_0)) 2 led_set(LED_GREEN, true);
但事實上,這個問題根本沒有那麼麻煩,甚至不須要 switch_changed 函數——每次循環讀取開關狀態,再把LED設置成相應狀態便可:get
1 #include <ee1/led.h> 2 #include <ee1/switch.h> 3 #include <ee1/delay.h> 4 5 int main() 6 { 7 led_init(); 8 switch_init(PIN_NULL, PIN_NULL); 9 while (1) 10 { 11 led_set(LED_GREEN, switch_status(SWITCH_0)); 12 delay(40); 13 } 14 }
你一開始有沒有想到這個簡單的方案?若是有,而且第一反應就是這個,那你得開始逐漸改變思路了。這種方案在這個例子中可用,是由於對 led_set 和 switch_status 的調用的成本是很低的,每次循環都調用也沒有問題。然而這並非放之四海而皆準的,有些函數經不起這樣頻繁的調用。在那樣的狀況下,檢測狀態改變,再讀取狀態,是一種更好的方案。同步
思考:在斷定按鍵動做的函數中,前一次狀態經過靜態變量存儲,其初值爲真,保證第一次調用時函數不會返回真;對於開關動做,相應靜態變量的初值應該是什麼?
做業:每一個開關控制一個LED,一個按鍵控制開關是否啓用;啓用時要讓LED與當前開關狀態對應,禁用時要關閉全部LED。