Arduino 中斷的使用

中斷的定義

程序運(yùn)行過程中時常需要監(jiān)控一些事件的發(fā)生,如對某一傳感器的檢測結(jié)果做出反應(yīng)。使用輪詢的方式進(jìn)行檢測時效率較低,等待時間較長,而使用中斷方式進(jìn)行檢測時則可以達(dá)到實(shí)時檢測的效果。

當(dāng)中斷被觸發(fā)時,控制器會暫停當(dāng)前正在運(yùn)行的主程序,而跳去運(yùn)行中斷程序,當(dāng)中斷程序運(yùn)行完后,會再回到之前主程序暫停的位置,繼續(xù)運(yùn)行主程序。如此便可以達(dá)到實(shí)時響應(yīng)處理事件的效果。

外部中斷是由外部設(shè)備發(fā)起請求的中斷。要想使用外部中斷,就需要了解中斷引腳的位置,根據(jù)外部設(shè)備選擇中斷模式,以及編寫一個中斷被觸發(fā)后需要執(zhí)行的中斷函數(shù)。

中斷引腳

ARDUINO中的外部中斷通常是由Pin口電平改變觸發(fā)的。每種型號的ARDUINO板都有數(shù)個PIn口可以用來注冊中斷

常見開發(fā)板外部引腳圖:常見開發(fā)板引腳圖

中斷模式

為了設(shè)置中斷模式,還需要了解設(shè)備觸發(fā)外部中斷的輸入 信號類型。中斷模式也就是中斷觸發(fā)的方式。在大多數(shù)ARDUINO上支持以下幾個中斷觸發(fā)方式

LOW 低電平觸發(fā)

CHANGE 電平變化觸發(fā)

RISING 上升沿觸發(fā),即高電平變低電平

FALLING 下降沿觸發(fā),即低電平變高電平

中斷函數(shù)

除了設(shè)置中斷模式外,還需要編寫一個響應(yīng)中斷的處理程序——中斷函數(shù),當(dāng)中斷被觸發(fā)后,便可以讓Arduino運(yùn)行該中斷函數(shù)。中斷函數(shù)就是當(dāng)中斷被觸發(fā)后要去執(zhí)行的函數(shù),該函數(shù)不能帶有任何參數(shù),且返回類型為空

這些準(zhǔn)備工作完成后,還需要在setup()中使用attachInterrrupt()函數(shù)對中斷引腳進(jìn)行初始化配置,以開啟arduino的外部中斷功能,其用法如下:

attachInterrupt(interrupt, function,mode)

功能:對中斷引腳進(jìn)行初始化配置

參數(shù):

interrupt,中斷編號,注意,這里的中斷編號并不是引腳編號

function,中斷函數(shù)名,當(dāng)中斷被觸發(fā)后即會運(yùn)行此函數(shù)所代表的中斷函數(shù)。

mode,中斷模式

detachInterrupt(interrupt)

功能:禁用外部中斷

參數(shù):

interrrupt,需要禁用的中斷編號

實(shí)驗(yàn)代碼


#define LED  A2
#define KEY 2

volatile byte  state;
volatile unsigned long last_time;
void setup() {

  Serial.begin(115200);

  // put your setup code here, to run once:
  pinMode(LED, OUTPUT);
  pinMode(KEY, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(KEY), keyInterrupt, RISING);
  state = LOW;
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(LED, state);
}

void keyInterrupt() {
  if ((millis() - last_time) > 500) {
    Serial.println("檢測到中斷");
    if (state == LOW) {
      state = HIGH;
    } else {
      state = LOW;
    }
    last_time = millis();

  }

}

嘗試自己模擬運(yùn)行下吧:https://wokwi.com/projects/347197223040189011

可能會遇到的問題

當(dāng)實(shí)際操作的時候你會發(fā)現(xiàn)你的中斷函數(shù)被觸發(fā)很多次,這個當(dāng)然不是我們想要看到的。這是由于我們按鍵是機(jī)械結(jié)構(gòu)所造成的抖動,而需求就是消除這個抖動。

if ((millis() - last_time) > 500) {
    Serial.println("檢測到中斷");
    if (state == LOW) {
      state = HIGH;
    } else {
      state = LOW;
    }
    last_time = millis();

  }

此方法是加入時間函數(shù)利用時間差進(jìn)行處理抖動效果。

當(dāng)然還有另外的一種方案筆者沒有嘗試過,利用在按鈕兩端并聯(lián)一顆電容利用它的特性過濾按鈕的抖動,感興趣的可以自己測試。

定時器庫的使用

引入庫: TimerOne
代碼中使用:#include "TimerOne.h"

#include "TimerOne.h"

#define LED 7

volatile byte state = LOW;

void setup() {
  Serial.begin(115200);
  // put your setup code here, to run once:
  pinMode(LED, OUTPUT);

  digitalWrite(LED, state);

  Timer1.initialize( 500000  ); // 初始化,   interval 以 micro sec 為單位
  Timer1.attachInterrupt( timer_task ); // attach the service routine here
}

void loop() {
  digitalWrite(LED, state);
}

void timer_task() {
  Serial.println("timer_task 執(zhí)行了");
  state = ~state;
}

運(yùn)行范例:https://wokwi.com/projects/347208147574719058

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容