1. 程式人生 > >《博哥Arduino學習筆記系列》- 第四課 經典按鍵實驗

《博哥Arduino學習筆記系列》- 第四課 經典按鍵實驗

一、前言

     回顧一下第三課

     《博哥Arduino學習筆記系列》- 第三課 經典LED

      我們講了數字IO口介紹以及做了流水燈演示(主要用到IO口的輸出功能),這節課我們講解一下IO口的輸入功能,說到輸入功能,最經典的例子莫過於按鍵實驗。廢話少說,趕緊上車。


二、實驗介紹

       注意:這課實驗是基於第三課實驗材料進行的。

       使用了大按鍵模組:
        
       這個模組,高電平有效。


        

       1)實驗1  當按住按鍵時點亮LED,當放開按鍵後熄滅LED
       2)實驗2  當點選一次按鍵時點亮LED,當再次點選一次按鍵時熄滅LED(就跟家裡燈一樣)
三、實驗過程

        我的實驗儘量都在程式碼中解釋,畢竟程式碼才是最直觀的展示

        1)實驗1 當按住按鍵時點亮LED,當放開按鍵後熄滅LED
            程式碼如下:

[C] 純文字檢視 複製程式碼

?

程式碼

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

028

029

030

031

032

033

/**

* @Desc 按鍵燈(當按住按鍵時點亮LED,當放開按鍵後熄滅LED)

* @author 微控制器菜鳥

* @Date  2016/12/3

* 注意:LED的一端接到5V,另外一端接到輸出引腳,低電平亮

*       按鍵是高電平有效

*/

#define LED  2

#define KEY  10

int buttonState = HIGH;//記錄當前按鍵狀態

void setup() {

//配置2號引腳作為輸出引腳

pinMode(LED,OUTPUT);

digitalWrite(LED,HIGH);//滅掉LED

//配置10號引腳為輸入引腳 如果是自己連線普通按鍵 pinMode(KEY,INPUT_PULLUP),弱上拉

pinMode(KEY,INPUT);

}

void loop() {

buttonState = digitalRead(KEY);//讀取當前按鍵狀態

if(buttonState == HIGH){

//按鍵按下

digitalWrite(LED,LOW);//點亮LED

}else{

//按鍵放開

digitalWrite(LED,HIGH);//熄滅LED

}

}



2)實驗2  當點選一次按鍵時點亮LED,當再次點選一次按鍵時熄滅LED(就跟家裡燈一樣)
           程式碼如下:

[C] 純文字檢視 複製程式碼

?

程式碼

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

028

029

030

031

032

033

034

035

/**

* @Desc 按鍵燈(當點選一次按鍵時點亮LED,當再次點選一次按鍵時熄滅LED)

* @author 微控制器菜鳥

* @Date  2016/12/3

* 注意:LED的一端接到5V,另外一端接到輸出引腳,低電平亮

*       按鍵是高電平有效

*/

#define LED  2

#define KEY  10

int buttonState = HIGH;//記錄當前按鍵狀態

int flag = HIGH;//預設當前滅燈

void setup() {

//配置2號引腳作為輸出引腳

pinMode(LED,OUTPUT);

digitalWrite(LED,flag);//滅掉LED

//配置10號引腳為輸入引腳 如果是自己連線普通按鍵 pinMode(KEY,INPUT_PULLUP),弱上拉

pinMode(KEY,INPUT);

}

void loop() {

buttonState = digitalRead(KEY);//讀取當前按鍵狀態

if(buttonState == HIGH){

//按鍵按下

delay(40);//做一個防抖動延時(確保真是按下了按鍵而不是錯誤)

buttonState = digitalRead(KEY);//再一次讀取按鍵狀態

if(buttonState==HIGH){

//再次確認是否真的按下了按鍵,是的話就置反當前燈的狀態

flag = !flag;

digitalWrite(LED,flag);

}

}

}



我的按鍵模組的實驗結果是:偶爾可以,偶爾又不可以,證明只是簡單防抖動肯定是不行的。後面經過查資料用以下防抖動方法:

 

[C] 純文字檢視 複製程式碼

?

程式碼

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

028

029

030

031

032

033

034

035

036

037

038

039

040

041

042

043

044

045

046

047

048

049

050

051

052

053

054

055

056

/**

* @Desc 按鍵燈(當點選一次按鍵時點亮LED,當再次點選一次按鍵時熄滅LED)

* @author 微控制器菜鳥

* @Date  2016/12/3

* 注意:LED的一端接到5V,另外一端接到輸出引腳,低電平亮

*       按鍵是高電平有效

*/

#define LED  2

#define KEY  10

int flag = HIGH;//預設當前滅燈

// 定義記錄按鍵當前狀態的變數

int state_btn;

// 定義記錄按鍵最近一次狀態變化的變數,並初始化狀態為LOW。

int lastButtonState = LOW;

// 定義記錄最近一次抖動的時間變數,並初始化時間為0毫秒。

long lastDebounceTime = 0;

// 定義延遲抖動的時間變數

long debouncdDelay = 60;

void setup() {

//配置2號引腳作為輸出引腳

pinMode(LED,OUTPUT);

digitalWrite(LED,flag);//滅掉LED

//配置10號引腳為輸入引腳 如果是自己連線普通按鍵 pinMode(KEY,INPUT_PULLUP),弱上拉

pinMode(KEY,INPUT);

}

void loop() {

int buttonState = digitalRead(KEY);//讀取當前按鍵狀態

if(buttonState != lastButtonState){

//如果按鍵發生了變化  則重新設定最近一次抖動的時間

//方法millis()可以獲取當前時間,單位統一為毫秒。

lastDebounceTime = millis(); 

}

// 判斷按鍵按下狀態時間間隔是否大於延遲抖動的時間長度。

if(millis()-lastDebounceTime>debouncdDelay){

// 判斷當前的按鍵狀態是否和之前有所變化

if(buttonState != state_btn){

// 如果發生了變化,

// 則更新按鍵狀態變數。

state_btn = buttonState;

if(state_btn == HIGH){

//再次確認是否真的按下了按鍵,是的話就置反當前燈的狀態

flag = !flag;

digitalWrite(LED,flag);

}

}

}

// 更新按鍵最近一次狀態變化的變數

lastButtonState = buttonState;

}



這裡的防抖演算法的思路是:需要記錄一個最近狀態 lastButtonState (每讀一次引腳狀態就記錄一次),然後在抖動間隔內(60ms)判斷最新狀態,只要間隔內狀態改變,就不斷更新抖動時間的起始點(也就是 lastDebounceTime = millis(); ),直到防抖動滿足 millis()-lastDebounceTime>debouncdDelay。之後再判斷一下當前狀態和之前狀態是否改變 buttonState != state_btn (以防使用者按太久了)

四、總結
       這節課我們主要學習數字IO口的輸入功能,整體上還算簡單,主要是注意按鍵防抖動。下一節我們計劃將模擬IO