Arduioのtimer割込み

2023.04.22


概要

Arduino UnoのCPUはATmega328またはATmega328Pで、タイマーはTimer0,Timer1,Timer2の3つある。
Timer0はすでにdelay()関数などで使われている。
CPUのクロックは16MHzでこれをプリスケーラやカウンタなどを使って丁度良い時間周期を作って
割込をさせる。知らんけど

Timer1割込の設定(500ms毎の割込み設定)

(1)CTCモードの設定

CTCモードとは、カウンタが特定の値になったところで割込が入理、カウンタがクリアされる。

 TCCR1AレジスタとTCCR1Bレジスタを設定する

TCCR1Aレジスタ

b7
b6
b5
b4
b3
b2
b1
b0
COM1A1 COM1A0
COM1B1
COM1B0 -
-
WGM11
WGM10

TCCR1Bレジスタ

b7
b6
b5
b4
b3
b2
b1
b0
ICNC1 ICES1
-
WGM13
WGM12
CS12 CS11
CS10

COM1A1からCOM1B0はすべて0にする  Normal Port Operation
他のモードはデータシート参照
WGM13,WGM12,WGM11,WGM10は0,1,0,0とセットしてCTCモード(Clear Time on Compare match mode)にする

(2)プリスケーラの設定

プリスケーラとは分周、例えば8だったらクロックが8倍になる。
ArduinoUnoは16MHzのクロックで動いているので,プリスケーラが8なら1/16MHz * 8 秒 = 0.5μ秒となる。

CS12
CS11
CS10
クロックの選択
0
0
0
No Clock(Timer/Counter stopped)
0
0
1
内部クロック プリスケーラなし   1/16MHz=0.0625μ秒
0
1
0
内部クロック プリスケーラ 8      1/16MHz*8=0.5μ秒
0
1
1
内部クロック プリスケーラ 64     1/16MHz*64=4μ秒
1
0
0
内部クロック プリスケーラ 256  1/16MHz*256=16μ秒
1
0
1
内部クロック プリスケーラ 1024   1/16MHz*256=64μ秒
1
1
0
外部クロック(端子T1,ネガティブエッジ)
1
1
1
外部クロック(端子T1,ポジティブエッジ)

(3)コンペアレジスタOCR1Aの設定

 OCR1Aには周期をセットする。このレジスタは16bit 0から65535まで設定可能
 0.5 秒ごとに割込を入れる場合、0.5秒=500000μ秒 なので
  プリスケーラを256、周期16μにするとちょうど割り切れる。
 500000/16=31250
  をセットする(もしかして0から始まるから31249にするのかもしれないが、
 誤差ということで)

(4)TIMER割込処理の関数

 これは最初からISR関数という名前で用意されている
  ISR(TIMER1_COMPA_vect){
   //処理を記述 ;

  } 

(5)割込み許可(Enable)

 TIMSK1 (Timer/Counter Interrupt Mask Register)の OCIE1AをONにする

TIMSK1レジスタ

b7
b6
b5
b4
b3
b2
b1
b0
-
-
ICIE1
-
-
OCIE1B OCIE1A
TOIE1

 ICIE1: Timer/Counter1, Input Capture Interrupt Enable
 OCIE1A: Timer1, Output Compare A Match Interrupt Enable
 OCIE1B: Timer/Counter1, Output Compare B Match Interrupt Enable
 TOIE1: Timer/Counter1, Overflow Interrupt Enable


プログラム例

void setup() {
  TCCR1A=0;
  TCCR1B=0;
  TCCR1B |= (1<<WGM12) |(1<<CS12) ; //CTCmode, Prescaler 256
  OCR1A=31250-1;
  TIMSK1 |= (1<<OCIE1A);
}

ISR(TIMER1_COMPA_vect){ // タイマー割込処理の関数
   //ここでタイマー割込のときの処理をする
}

void loop{
  //通常の処理
}




Timer2の割込設定

 詳しくはデータシート参照
 概要配下の通り

 TCCR2AのWG21に1を入れてCTC moddeにして
 TCCR2BのCS??にプリスケーラ(分周)を設定
  コンペアレジスタはOCR2A  だが8bit  なので  最大255までしか設定できない
 TIMSK2のOCIE2AをON(1)にして割込許可、始動
  
  割込関数は

  ISR (TIMER2_COMPA_vect) {
    //処理を記述;
   }