Make: AVR Programming pt.03

http://squeuei.hatenablog.com/entry/2016/08/16/201654squeuei.hatenablog.com

Chapter 8

 割り込みを扱うときはISR()を使う。厳密に言うところは関数じゃなくてマクロ。 引数として割り込みベクタを与える。割り込みベクタの定義はio.hに書いてある。

外部割り込み

 外部割り込みを有効化するときは、2段階ある事を忘れないようにする。

  1. 使いたい割り込みベクタを有効化する
  2. 割り込みシステム全体をsei()で有効化する。

 普通は割り込みに入るときにglobal interrupt enableがオフになるので、割り込み中に更なる割り込みが発生することは無い。それを許可したい場合は、ISRのなかでsei()を呼ぶか、ISR_NOBLOCKでISRを定義するかのどっちかにする。

 割り込みを生じさせたくない場合はcli()を使ってglobal interrupt enableをオフにする。再開したいときはsei()を。

ピン変化割り込み

 Pin-Change InterruptではPxyPCINTxが対応する。ただしxはアルファベットと数字で対応してるのでややこしい。PByはPCINT0,PCyはPCINT1、PDyはPCINT2みたいに。 割り込みベクタは全部のピンで共通なので、ISRの中でどのピンからの割り込みなのかを判定して処理しないといけない。

  1. 制御レジスタ(PCICR)で使いたい割り込みを有効化する。
  2. 使いたいピンをピンマスクレジスタで設定する。
  3. global interrupt enableをsei()で有効化する。

 割り込みを受けるときは

  1. 同じバンクの複数のピンからトリガを受ける場合にはbit_is_clear(BUTTON_IN, BUTTON)のようにどのピンからの割り込みなのかを調べる。
  2. 同じバンクに一つしかトリガを受けない場合には、立ち上がりと立ち下がりの両方に反応することに注意。どちらなのかを確認する必要がある。

ISRで変数を操作したいとき

 ISRは引数を取れないので、mainからもISRからもアクセスできるグローバル変数を宣言する。 ただし、その変数はvolataileを付けること。つけないと、一度もmain内で変更されない変数とみなされて、コンパイラが定数に変更してしまうことがある。 空のforループを回すときにも同じ事をする。

Chapter 9

タイマ

 タイマにはノーマルモードとCTCモードがある。 ノーマルモードではカウンタがオーバフローするまで動作する。タイマの種類にもよるが255あるいは65535。 CTCモードではOCRnAレジスタで指定した値までカウントする。 ATMega168の場合はTimer1が16bit、そのほかは8bit。現在のタイマーの値はTCNTxに格納されている。

 CTCモードの場合はTCCRxAレジスタWGM01を設定する。また、outputモードにする場合はTCCRxAレジスタCOMxA0を設定する。また、outputモードにする場合は Output Compare Resister OCRxAビットに

 どのモードにせよ、プリスケーラを設定しなければ、タイマは動作しない。CSx2CSx1CSx0の値を、データシートの表にしたがって設定する。

CPUスピード

 CPUスピードを変える方法には“ヒューズ”を書き換える方法と、ソースコードの中で設定する方法の2つがある。

 この本のサンプルコードに付属するMakefileではmake set_fast_fuseすることで8MHz動作に変更される。戻すときはmake set_default_fuses

 そのほかにもAVRDUDEで設定変更ができるけど、例えばSPIEN-enable fuse bitを変更してしまうとSPIでのプログラミングができなくなったり(設定を戻すこともSPIではできない!)、CPUクロックソースを外部クロックに設定してしまったり(こっちはクロックや他のマイコンから1MHzの信号を印可してやればよいので、まだ対処しやすい)するので、注意が必要。

 ソースコードで設定する場合には、Clock Prescalar Change Enableビットをセットしてから4クロック以内にプレスケーラの値を変更しないと行けない。これはけっこうやっかいなので、avr/power.hにクロック変更用のマクロがすでに用意されている。

#include <avr/power.h>
clock_prescale_set(clock_div_1);

などとすればよい。

 power.hにはAVRに内蔵されている特定のモジュールの電源を落とすマクロなども用意されているので、省電力化したい場合には活用すると良い。