割り込み(Interrupt)¶
割り込みとは¶
割り込み(Interrupt) は、外部からの信号を検出したとき(例:GPIOピンの状態変化)、実行中のプログラムを一時停止して、あらかじめ登録した関数を実行する仕組みです。
リアルタイム性が必要な場合に最適です。
割り込みの登録¶
ESP32では
attachInterrupt()
関数を使って、割り込みを登録できます。
// 基本的な使い方
attachInterrupt(GPIO_PIN, handlerFunction, triggerMode);
// 基本的に起動時に登録
void setup(void) {
// GPIO4の立ち上がりエッジで onPPSPulse() を実行
attachInterrupt(GPIO_NUM_4, onPPSPulse, RISING);
}
パラメーター¶
| パラメーター | 説明 | 例 |
|---|---|---|
GPIO_PIN |
監視するGPIOピン番号 | GPIO_NUM_4 |
handlerFunction |
イベント時に実行する関数 | onPPSPulse |
triggerMode |
トリガーする条件 | RISING(立ち上がり) |
トリガーモード¶
| モード | 説明 | 例 |
|---|---|---|
RISING |
信号がLOW→HIGHに変わった時 | 1PPSパルス(立ち上がり) |
FALLING |
信号がHIGH→LOWに変わった時 | ボタン押下(立ち下がり) |
CHANGE |
信号が変わった時(両方) | 変化を全て捕捉したい場合 |
HIGH |
信号がHIGHの間ずっと | レベルトリガー |
LOW |
信号がLOWの間ずっと | レベルトリガー |
割り込みハンドラー¶
割り込みハンドラーは、 割り込みが発生したときに自動実行される関数です。
// 基本的な形
void IRAM_ATTR handlerFunctionName() {
// 割り込み発生時に実行されるコード
}
IRAM_ATTRは、この関数をESP32の高速RAM(IRAM)に配置するマクロです。
割り込みハンドラーが高速に実行されるというメリットがあります。
ただし、IRAM容量には限界があるため、複雑な処理は避け、短い処理に限定すべきです。
ハンドラー定義のポイント¶
| 項目 | 説明 |
|---|---|
| 短い | 複雑な処理は避ける。グローバル変数に値を記録して終わりが基本 |
| 高速 | ハンドラーが長く実行されると、メインプログラムが停止してしまう |
| グローバル変数を使う | ハンドラー内で値を記録し、メインループで処理する設計が標準 |
| volatile修飾 | 複数の場所から参照する場合は volatile を使って最新値取得を保証 |
割り込みハンドラーのサンプル¶
// main.cpp の先頭
/// Timestamp captured from interrupt.
static uint64_t g_interrupt_value = 0;
/// Flag set by interrupt handler.
volatile bool g_interrupt_flag = false;
// 割り込みハンドラー(IRAM内で高速実行)
void IRAM_ATTR onInterruptEvent() {
g_interrupt_value = micros();
g_interrupt_flag = true;
}
// setup()で割り込みを登録
void setup(void) {
attachInterrupt(GPIO_NUM_4, onInterruptEvent, RISING);
}
// メインループで処理
void loop() {
if (g_interrupt_flag) {
uint64_t value = g_interrupt_value;
g_interrupt_flag = false; // Clear flag first
// 複雑な処理をここで実行
Serial.printf("Interrupt at: %llu us\n", value);
}
}
kurikintonsではGNSSモジュールから取得した時刻を1PPSパルスで補正するために、
割り込みを使用しています。
まとめ¶
| 項目 | 説明 |
|---|---|
| 割り込み | GPIOピン変化時に即座にハンドラーを実行する仕組み |
| 登録 | attachInterrupt(GPIO_PIN, handler, RISING/FALLING/CHANGE) |
| ハンドラー | void IRAM_ATTR handler() {...} の形式 |
| 設計 | ハンドラーは最小限にして、メインループで処理 |