概要
attachInterrupt()は、外部割り込みが発生したときに呼び出す関数を設定します。attachInterrupt()のリファレンスはこちらを参照してください。
ATmega328Pの外部割り込みは、INT0とINT1、PCINT0~PCINT23のどれかで起動されます。Arduinoでは、INT0(デジタルピン2番)とINT1(デジタルピン3番)の外部割り込みを利用できます。
割り込みの制御
INT0とINT1の外部割り込みは、外部割り込み関連のレジスタ(EICRAとEIMSK)を操作することで実現します。
EICRA
EICRA(External Interrupt Control Register A、外部割り込み制御レジスタA)は、割り込みの検出方法を制御します。
EICRA | ||||||||
---|---|---|---|---|---|---|---|---|
ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
名称 | - | - | - | - | ISC11 | ISC10 | ISC01 | ISC00 |
ISC11とISC10の組み合わせで、INT1(デジタルピン3)の割り込み条件を、ISC01とISC00の組み合わせでINT0(デジタルピン2)の割り込み条件を設定します。
ISC11/ISC01 | ISC10/ISC00 | 割り込み発生条件 |
---|---|---|
0 | 0 | LOWのとき |
0 | 1 | 値が変化したとき |
1 | 0 | HIGHからLOWになるとき |
1 | 1 | LOWからHIGHになるとき |
EIMSK
EIMSK(External Interrupt Mask Register)は、外部割り込みの許可・禁止を制御します。
EIMSK | ||||||||
---|---|---|---|---|---|---|---|---|
ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
名称 | - | - | - | - | - | - | INT1 | INT0 |
それぞれ1のときに、INT1/INT0の割り込みを許可します(かつ状態レジスタのIビットが1になっている必要があります)。
ソースコード
attachInterrupt()は、hardware/arduino/avr/cores/arduino/WInterrupts.c に定義されています。以下に全ソースコードを示します。Arduino Unoの場合に適用される部分だけを抜粋しています。実際には#if によりさまざまなチップに対応しています。
|
|
intFunc[]は、外部割り込みが発生したときに起動する関数を代入しておく配列です。intFuc[]の型のvoidFuncPtrとEXTERNAL_NUM_INTERRUPTSは、hardware/arduino/cores/arduino/wiring_private.hに以下のように定義されています。
|
|
voidFuncPtrは、voidを返す、引数のない関数へのポインタ型です。EXTERNAL_NUM_INTERRUPTSが2なので、関数を2個定義することができます。初期値として、何もしないnothing()という関数が代入されています。
入力は、interruptNumとuserFuc、modeで、それぞれ、uint8_t、void(*)(void)、int型です。出力はありません。
|
|
割り込み番号(interruptNum)が、EXTERNAL_NUM_INTERRUPTS未満のとき、それ以降を実行します。
引数で指定した関数をintFunc[]に格納します。割り込みハンドラの中から指定した関数が呼び出されます。
|
|
割り込み番号に対応したレジスタの値を設定します。
|
|
論理演算が見づらいので、少しずつ解剖していきます。
|
|
ISC00とISC01は、それぞれ、0と1です。よって、1 « ISC00は1(0b00000001)、1«ISC01は2(0b00000010)です。
両者の論理和をとると、0b00000011(=3)です。
|
|
次に、EICRAと~((1 « ISC00) | (1 « ISC01)))の論理積をとっています。((1 « ISC00) | (1 « ISC01)))は、0b00000011なので、その否定である、~((1 « ISC00) | (1 « ISC01)))は、0b11111100となります。
EICRAとこの0b11111100の論理積をとっているので、EICRAの下位2ビットをクリアするということになります。
mode « ISC00との論理和をとります。ISC00は0なので、modeとの論理和と同値です。
|
|
modeとして指定するのは、LOWあるいはCHANGE、RISING、FALLINGのどれかで、それぞれ、0、1、2、3です。
これにより、EICRAを設定します。
modeの値は検査していないので、変な値を指定すると、INT1の設定を変えてしまう可能性があります。
INT0_vect、INT1_vectは、それぞれ、INT0、INT1が発生したときに起動される割り込みハンドラです。
|
|
ISR()は、割り込みハンドラを定義するためのマクロです。割り込みハンドラでは、intFunc[]に登録した関数を呼び出します。
バージョン
Arduino AVR Boards 1.8.6
最終更新日
March 21, 2023