このところAVRで遊んでいます。タイマー割り込みを使ってみました。
タイマー割り込みを使うときは以下のことをします。
- avr/interrupt.hのinclude
- 割り込みハンドラを作る
- 割り込み許可レジスタの設定
割り込みハンドラはISR(ベクトル名)というマクロの直後に関数の中身を書きます。
割り込み許可レジスタはTIMSK1というレジスタに値を設定します。
動作確認はLEDチカチカです。14pin(PB0)にLEDと電流制限抵抗をつないでいます。
AVR Libcのページの割り込みのページを参考にさせていただきました。
ソースです。
割り込み処理は特別なprologとepilogが必要になるので、なんらかの形でコンパイラに割り込みハンドラであることを教えてあげないといけません。指定方法はC言語の標準の範囲ではないので、CPU毎、コンパイラ毎に異なります。AVRのgccはマクロが用意されているので簡単です。
割り込みベクトルの名前は、ヘッダファイルiomx8.hから見つけました。TIMER1_COMPA_vectは_VECTOR(11)を#defineしたものです。
最初思っていたほど難しくなかったというのが感想です。
タイマー割り込みを使うときは以下のことをします。
- avr/interrupt.hのinclude
- 割り込みハンドラを作る
- 割り込み許可レジスタの設定
割り込みハンドラはISR(ベクトル名)というマクロの直後に関数の中身を書きます。
割り込み許可レジスタはTIMSK1というレジスタに値を設定します。
動作確認はLEDチカチカです。14pin(PB0)にLEDと電流制限抵抗をつないでいます。
AVR Libcのページの割り込みのページを参考にさせていただきました。
ソースです。
#include <avr/io.h> #include <avr/interrupt.h> // 割り込み処理ハンドラ ISR(TIMER1_COMPA_vect) { PORTB ^= 0x01; // PB0反転 } // タイマー初期化 void timer_init(unsigned t) { // 15.11.5 タイマ/カウンタ1比較レジスタA OCR1A = t; // 15.11.1 タイマ/カウンタ1制御レジスタA (初期値は0x00なので必要ない) // ++-------COM1A1:COM1A0 00 OC1A切断 // ||++---- COM1B1:COM1B0 00 OC1B切断 // |||| ++ WGM11:WGM10 00 波形生成種別(4bitの下位2bit) TCCR1A = 0b00000000; // 15.11.2 タイマ/カウンタ1制御レジスタB // +------- ICNC1 0 // |+------ ICES1 0 // || ++--- WGM13:WGM12 01 波形生成種別(4bitの上位2bit) CTC top=OCR1A // || ||+++ CS12:CS11:CS10 101 1024分周 TCCR1B = 0b00001101; // 15.11.8 タイマ/カウンタ1割り込みマスクレジスタ // +----- ICIE1 0 // | +-- OCIE1B 0 // | |+- OCIE1A 1 タイマ/カウンタ1比較A割り込み許可 // | ||+ TOIE1 0 TIMSK1 = 0b00000010; sei(); // 割り込み許可 } // int main() { DDRB = 0x01; // PB0(14pin) 出力 PORTB = 0x01; timer_init(100); // 100 * 1024us毎に割り込み (約4.88Hz) @ 1MHz while(1) ; // 無限ループ }
割り込み処理は特別なprologとepilogが必要になるので、なんらかの形でコンパイラに割り込みハンドラであることを教えてあげないといけません。指定方法はC言語の標準の範囲ではないので、CPU毎、コンパイラ毎に異なります。AVRのgccはマクロが用意されているので簡単です。
割り込みベクトルの名前は、ヘッダファイルiomx8.hから見つけました。TIMER1_COMPA_vectは_VECTOR(11)を#defineしたものです。
最初思っていたほど難しくなかったというのが感想です。