ATmega1284での割り込み処理

ATmega1284を使って割り込み処理をしてみた。最初、Arduinoのライブラリ「MsTimer2」を使って割り込み処理を試してみたけど、うまくできなかったので、avrのライブラリを使用した。
時間がたったら、いろいろ忘れそうなので備忘録を取っておく。

#タイマーの種類
タイマーは、クロックのタイミングを数えて（以下、タイマカウンタ）割り込み処理を実行する。タイマーには、標準モードとCTCモードの2種類より選択できる。今回は、CTCモードを使用した。

####**標準モード**

カウンタとして動作させたい時に使う。カウンタがMAX値のタイミングで、カウンタを0にリセットし、割り込み処理を発生させる。

| タイマ | カウンタ範囲 |
|:---------:|:------------:|
| Timer0、2（8bitタイマ） | 0 ～ 255     |
| Timer1（16bitタイマ）| 0 ～ 65535   |

####**CTCモード**

カウンタとして動作させたいときに使う。カウンタを0にリセットするタイミング（TOP値）を指定し、割り込み処理を発生させる。リセットするタイミングは、OCRnAで値を設定する。OCRnAの値を調整することで割り込み間隔を長くしたり短くしたりできる。

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/53064/42c50bd2-7878-941e-dfde-9f79e4f72e25.png)

#分周
「プリスケーラ」という一種のカウンタ回路を通すことで、CPUクロックの周波数より、1/8、1/64、1/256、1/1024のいずれかに速度を落として使うことができる。分周を使うことで、少ないビット幅のカウンタでも、長い間隔の割り込みができるようになる。


#カウンタの算出
カウンタ数（OCRn）は、以下の式より算出。分周率は、8、64、256、1024の4つから選択する。
今回は、0.005s（200Hz）で割り込み処理をしたいので、分周率64、カウンタ数1250を使うことにした。

**OCRn = システムクロック / 分周率 × タイマー時間**

|  分周率  |  カウンタ数 (OCRn)  |
|:--------:|:-----------:|
| 8        | 16000000/8*0.005=10000     |
| 64       | 16000000/64*0.005=1250     |
| 256      | 16000000/256*0.005=312.5   |
| 1024     | 16000000/1024*0.005=78.125 |


#コード
使用したタイマは、Timer1（16bitタイマ）。

```arduino_test.ino
#include <avr/io.h>
#include <avr/interrupt.h>

void setup() {
  noInterrupts();

  // レジスタをクリア
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  
  OCR1A = 1250; // カウンタ数
  TCCR1B = bit(WGM12) | bit(CS11) | bit(CS10); // CTCモードで分周率64
  TIMSK1 = bit(OCIE1A); // 割り込みをタイマー１に設定

  interrupts();
}

ISR (TIMER1_COMPA_vect) {
  // 割り込み処理
}

void loop() {
  // put your main code here, to run repeatedly:
}
```

- タイマ/カウンタの割り込み許可レジスタ
 
|        | 7bit | 6bit | 5bit | 4bit | 3bit |  2bit  |  1bit  | 0bit  |
|:------:|:----:|:----:|:----:|:----:|:----:|:------:|:------:|:-----:|
| TIMSK1 |   -  |   -  |   -  |   -  |   -  | OCIE1B | <font color="OrangeRed">OCIE1A | TOIE1 |

下表のタイマモード設定で、TOP=OCR1Aのため、比較Aレジスタが使用できるようOCIE1A=1にする。

- タイマ/カウンタの制御レジスタ

|        |  7bit  |  6bit  | 5bit | 4bit  | 3bit  | 2bit | 1bit | 0bit  |
|:------:|:------:|:------:|:----:|:-----:|:-----:|:----:|:----:|:-----:|
| TCCR1A | COM1A1 | COM1A0 |COM1B1|COM1B0 |   -   |   -  | WGM11| WGM10 |
| TCCR1B | ICNC1  | ICES1  |   -  | <font color="DeepPink">WGM13 | <font color="DeepPink">WGM12 | <font color="DeepSkyBlue">CS12 | <font color="DeepSkyBlue">CS11 | <font color="DeepSkyBlue">CS10  |

- タイマモード設定

| <font color="DeepPink">WGM13 | <font color="DeepPink">WGM12 | WGM11 | WGM10 |  MODE  |   TOP  |
|:-----:|:-----:|:-----:|:-----:|:------:|:------:|
|   0   |   0   |   0   |   0   | Normal | 0xFFFF |
|   <font color="DeepPink">0   |   <font color="DeepPink">1   |   0   |   0   |  CTC   | OCR1A  |
|   1   |   1   |   0   |   0   |  CTC   | ICR1   |

- クロック分周の設定

| <font color="DeepSkyBlue">CS12 | <font color="DeepSkyBlue">CS11 | <font color="DeepSkyBlue">CS10 | 意味      |
|:----:|:----:|:----:|:---------:|
|   0  |   0  |   0  | タイマ停止 |
|   0  |   0  |   1  | 分周なし   |
|   0  |   1  |   0  | 8分周     |
|   <font color="DeepSkyBlue">0  |   <font color="DeepSkyBlue">1  |   <font color="DeepSkyBlue">1  | <font color="DeepSkyBlue">64分周    |
|   1  |   0  |   0  | 256分周   |
|   1  |   0  |   1  | 1024分周  |