ATmega328の割り込みの使用方法

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

ATmega328の割り込みの使用方法を記載する。
割り込みには、シリアル割り込みやピン入力が変化した時の割り込み等がある。
ここでは、タイマ割り込みについて記載する。


割り込みの種類

ATmega328の割り込みの種類には、以下のようなものがある。

ATmega328の割り込みの種類
シンボル 名前 説明
INT0_vect 外部割り込みピン INT0 外部ピンの変化で割り込み
INT1_vect 外部割り込みピン INT1 外部ピンの変化で割り込み
PCINT0_vect 外部割り込みピン INT0 ピンの論理変化割り込みのみサポート
PCINT0〜23まである
TIMER0_COMPA_vect タイマ0
コンペアマッチA
タイマ0でコンペアマッチAのとき割り込み
TIMER0_COMPB_vect タイマ0
コンペアマッチB
タイマ0でコンペアマッチBのとき割り込み
TIMER0_OVF_vect タイマ0
オーバーフロー
タイマ0でカウンタ最大値を超えたとき割り込み
TIMER1_COMPA_vect タイマ1
コンペアマッチA
タイマ1でコンペアマッチAのとき割り込み
TIMER1_COMPB_vect タイマ1
コンペアマッチB
タイマ1でコンペアマッチBのとき割り込み
TIMER1_CAPT_vect タイマ1
捕獲イベント
タイマ1でICR1に達したときに割り込み
TIMER1_OVF_vect タイマ1
オーバーフロー
タイマ1でカウンタ最大値を超えたとき割り込み
TIMER2_COMPA_vect タイマ2
コンペアマッチA
タイマ2でコンペアマッチAのとき割り込み
TIMER2_COMPB_vect タイマ2
コンペアマッチB
タイマ2でコンペアマッチBのとき割り込み
TIMER2_OVF_vect タイマ2
オーバーフロー
タイマ2でカウンタ最大値を超えたとき割り込み
SPI_STC_vect SPIシリアル転送完了 SPIシリアル転送完了のとき割り込み
USART_RX_vect USART受信完了 USART(シリアル通信)受信完了のとき割り込み
USART_UDRE_vect USART送信可能 USART(シリアル通信)送信可能のとき割り込み
USART_TX_vect USART送信完了 USART(シリアル通信)送信完了のとき割り込み


割り込みのタイミングは、ピン入力の変化やタイマで指定した時間の経過、シリアル通信イベント等がある。
(上表に記載のない割り込みもある)
使用したい割り込みのシンボルは、ISR()関数の引数に指定して使用する。


割り込み処理の基本

割り込みを許可する命令は、sei命令である。
割り込み関数(ISR)からmain関数へ戻る命令は、ret命令である。

main関数から、割り込み関数(ISR)に処理が移る時、一旦、割り込みが禁止される。
割り込み処理が終わると、割り込みをまた許可しないといけないため、ret命令とsei命令を組み合わせた、reti命令がある。
reti命令で割り込み処理が終わる。

また、割り込みを禁止にするには、cil命令を使用する。

以下に割り込み処理のサンプルコードを記述する。

 #include <avr/io.h>
 #include <avr/interrupt.h>  // 割り込み処理
 
 // ISR関数とmain関数で使用する変数(コンパイラはこの変数を最適化しない)
 volatile unsigned char count;
 
 // 割り込み関数
 ISR(TIMER0_OVF_vect)  // タイマ0でオーバーフローが起きた時
 {
    count++;
 }
 
 int main()
 {
    // 割り込み処理を行うためレジスタの設定を行う 
    //cil();  // 割り込み禁止
    sei();    //割り込み許可
 
    while(1)
    {
       // メイン処理
    }
  
    return 0;
 }



タイマ割り込みの使用方法

タイマの割り込みを使用するためのレジスタ設定およびプログラムを記述する。
タイマに関しての記事は、ATmega328でのタイマとPWMの使用方法を参照すること。

タイマ0の割り込み
タイマ0割り込みレジスタ TIMSK0
ビット 7 6 5 4 3 2 1 0
レジスタ名 - - - - - OCIE0B OCIE0A TOIE0


  • OCIE0B : タイマ0のコンペアマッチBの割り込み(比較一致Bの割り込み)
  • OCIE0A : タイマ0のコンペアマッチAの割り込み(比較一致Aの割り込み)
  • TOIE0  : タイマ0のオーバーフロー割り込み


以下に、タイマ0でコンペアマッチAで割り込み処理を行うサンプルコードを記述する。

 #include <avr/io.h>
 #include <avr/interrupt.h>  // 割り込み処理を行うため
 
 ISR(TIMER0_COMPA_vect)  // タイマ0 コンペアマッチAの割り込み関数
 {
    // ..略
 }
 
 int main()
 {
    // タイマ0 制御レジスタA
    TCCR0A = 0b10000010;  // 10 : コンペアマッチAでLOW、10 : CTCモード
    // タイマ0 制御レジスタB
    TCCR0B = 0b00000001;  // 分周なし
    // タイマ0 割り込み設定
    TIMSK0 = 0b00000010;  // コンペアマッチAの割り込みを設定
  
    // コンペアマッチするタイミング
    OCR0A = 32499;  // 32.5[ms]でコンペアマッチ@1[MHz]
 
    // ポートの設定
    // ..略
  
    sei();  // 割り込み許可
 
    while(1)
    {
       // メイン処理
    }
 
    return 0;
 }


タイマ1の割り込み
タイマ1割り込みレジスタ TIMSK1
ビット 7 6 5 4 3 2 1 0
レジスタ名 - - ICIE1 - - OCIE1B OCIE1A TOIE1
  • ICIE1  : タイマ1の捕獲割り込み(タイマ(カウンタ)の値がICR1に達した時の割り込み)
  • OCIE1B : タイマ1のコンペアマッチBの割り込み(比較一致Bの割り込み)
  • OCIE1A : タイマ1のコンペアマッチAの割り込み(比較一致Aの割り込み)
  • TOIE1  : タイマ1のオーバーフロー割り込み


以下に、タイマ1で捕獲割り込みをするサンプルコードを記述する。

 #include <avr/io.h>
 #include <avr/interrupt.h>  // 割り込み処理を行うため
 
 // タイマ1での捕獲割り込み関数(ICR1に達すると割り込み)
 ISR(TIMER1_CAPT_vect) 
 {
    // 処理
 }
 
 int main()
 {
    // タイマ1 制御レジスタA
    TCCR1A = 0b00000010;  // 高速PWMモード(TOP値 : ICR1)
    // タイマ0 制御レジスタB
    TCCR1B = 0b00011001;  // 高速PWMモードで分周なし
    // タイマ0 割り込み設定
    TIMSK1 = 0b00100000;  // 捕獲割り込みを設定
 
    // 割り込み発生する時間の設定
    ICR1 = 64999;  // 65.0[ms]@1[MHz]
 
    // ポートの設定
    // 略
 
    sei();  // 割り込み許可
 
    while(1)
    {
       // メイン処理
    }
 
    return 0;   //プログラム終了
 }


タイマ2の割り込み
タイマ2割り込みレジスタ TIMSK2
ビット 7 6 5 4 3 2 1 0
レジスタ名 - - - - - OCIE2B OCIE2A TOIE2


  • OCIE2B : タイマ2のコンペアマッチBの割り込み(比較一致Bの割り込み)
  • OCIE2A : タイマ2のコンペアマッチAの割り込み(比較一致Aの割り込み)
  • TOIE2  : タイマ2のオーバーフロー割り込み


タイマ2は、タイマ0と同じ使い方なのでサンプルコードは省略する。