概要
Raspberry Pi Picoで割り込み処理(外部割り込み)を行う方法をArduinoIDE、C/C++SDK、両方の記述方法で試してみました。割り込み処理は個人的にはあまり好きではなく普段はあまり使わないようにしているのですがどうしても必要になったので使い方を調べました。
開発環境はArduinoIDEを使用。earlephilhower版のボードで検証してますが、恐らくMbed版でも同じ動きはすると思います。従来のattachinterrupt()関数も使えましたが、C/C++SDKでの記述でもテストしてみました。
attachinterrupt()関数で外部割り込み
まずは、従来のattachinterrupt()関数を使用する方法です。基本的にはArduinoと使い方は同じ。Picoでもそのまま使えます。ただUnoとは違い外部割り込みに使用できるピンが多いです。
関数の使い方
void attachInterrupt(interrupt, function, mode)
interrupt
:割り込み番号。UNOの場合、int0/1(2番、3番ピン)と少し紛らわしい引数となってますが、Picoの場合はそのままGPIOのピン番号。しかも割り当てピンに制限は無さそう。GP2/3/4/5/6/14/15試しましたが正常に割り込みできていた感じです。
function
:割り込み発生時に呼び出す関数
mode
:UNOと同じ。LOW/CHANGE/RISING/FALLIGの中から選択
スケッチ例
外部割り込みピンをGP15ピンに設定。ロジック変化で割り込みが発生し、GP15ピンの状態に応じてオンボードLEDをON/OFFさせてます。
// 2024/01/28 // imo Lab. https://Garchiving.com #define PIN_LED (25u) #define INT_PIN (15u) void setup() { pinMode(PIN_LED, OUTPUT); pinMode(INT_PIN, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(INT_PIN), blink, CHANGE); } void loop() { } void blink(void) { digitalWrite(PIN_LED, digitalRead(INT_PIN)); }
GP15ピンはプルアップ設定。スイッチなどを接続して「ON/OFF」(GP15ピンをGNDに接続)すと、オンボードLEDが点滅します。
C/C++SDKで外部割り込み
内容はattachinterrupt()関数と同様。設定の手順としてはattachinterrupt()関数と似ています。
関数の使い方
◆まずはArduinoのattachinterrupt()関数と同様の関数。
void gpio_set_irq_enabled_with_callback(uint8_t gpio, uint32_t event_mask, bool enabled, gpio_irq_callback_t callback)
gpio
:外部割り込みに設定するピン。
event_mask
:割り込み発生のタイミング。
bit | constant | タイミング |
---|---|---|
0 | GPIO_IRQ_LEVEL_LOW | ピン状態がLOWの間 |
1 | GPIO_IRQ_LEVEL_HIGH | ピン状態がHIGHの間 |
2 | GPIO_IRQ_EDGE_FALL | ピン状態がHIGH⇒LOWに変わったとき |
3 | GPIO_IRQ_EDGE_RISE | ピン状態がLOW⇒HIGHに変わったとき |
ピン状態に何か変化があった場合はGPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL
と記述。
enable
:true/falseで切替
callback
:呼び出される関数名
◆複数ピンに外部割り込みを設定する場合
void gpio_set_irq_enabled(uint8_t gpio, uint32_t event_mask, bool enabled)
引数の内容は前述の関数と同様です。外部割り当て行うピン毎に設定。ただPicoの仕様なのかピン毎に呼び出されるコールバック関数が設定できないようで、どのピンでも前述設定した関数が呼び出される仕様となってます。そのためなのか?呼び出されるコールバック関数には引数があります。
◆呼び出される関数
void gpio_callback(uint gpio, uint32_t events)
引数にピン番号、イベントがあります。これでどのピン割り込みが発生したかを判断するということでしょうか。
void gpio_callback(uint gpio, uint32_t events){ if(gpio == 14 && events == GPIO_IRQ_EDGE_FALL){ } if(gpio == 15 && events == GPIO_IRQ_EDGE_FALL){ } }
このようにどのピンに変化があったかを判定して処理するような感じになるのでしょうか。他に方法があるような気もしますが調べても良くわかりませんでした。
スケッチ(ソース)
// 24/01/28 // imo Lab. http://garchiving.com #define PIN_LED (25u) #define PIN_INT1 (14u) #define PIN_INT2 (15u) #define PIN_INT3 (16u) void setup() { pinMode(PIN_LED, OUTPUT); pinMode(PIN_INT1, INPUT_PULLUP); pinMode(PIN_INT2, INPUT_PULLUP); pinMode(PIN_INT3, INPUT_PULLUP); gpio_set_irq_enabled_with_callback(PIN_INT1, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback); gpio_set_irq_enabled(PIN_INT2, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true); gpio_set_irq_enabled(PIN_INT3, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true); } void loop() { } void gpio_callback(uint gpio, uint32_t events) { digitalWrite(PIN_LED, digitalRead(gpio)); digitalWrite(PIN_LED, digitalRead(gpio)); }
GPIO14/15/16ピンのいずれかに変化があった場合、変化があったピン状態に合わせてオンボードLEDが点滅するスケッチです。
ArduinoIDEを使用するならattachinterrupt()関数を使用すればいいのかなという気はします。
▼参考▼
コメント