|
○ 関連レジスタ
タイマ/カウンタ1関連のレジスタを以下に紹介します。マクロについては、avr-libc で使用できる定義名を掲載しています。また、日本語のレジスタ名とビット名は、英語の定義名称を適当に訳してます。
- タイマ/カウンタ1制御レジスタA(TCCR1A)
ビット番号 7 6 5 4 3 2 1 0 マクロ COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10 初期値 0 0 0 0 0 0 0 0 各ビットの説明を以下に書きます。
ビット名 内容 COM1A1/COM1A0
COM1B1/COM1B0(比較1出力モード)OC1A/OC1B ピン(PDIP パッケージでは 19/18 ピン)の出力方式を設定します。 - WGM11 = WGM10 = 0 の場合(標準動作、CTC動作)(?=A/B)
COM1?1 COM1?0 内容 0 0 OC1? には出力されない 0 1 比較一致において反転 1 0 比較一致において 0(Low) 1 1 比較一致において 1(High)
- WGM13-10=0101/0110/0111/1110/1111 の場合(高速PWM)(?=A/B)
COM1?1 COM1?0 内容 0 0 OC1? には出力されない 0 1 WGM13-10=1111 の場合は比較一致で OC1A 反転、OC1B は出力されない。 WGM13-10=それ以外の場合は OC1? には出力されない 1 0 比較一致で 0(Low)、TCNT1 = 0 で 1(High) 1 1 比較一致で 1(High)、TCNT1 = 0 で 0(Low)
- WGM13-10=0001/0010/0011/1000/1001/1010/1011 の場合(位相基準PWM)(?=A/B)
COM1?1 COM1?0 内容 0 0 OC1? には出力されない 0 1 WGM13-0=10x1 の場合は比較一致で OC1A 反転、OC1B は出力されない。 それ以外は OC1? には出力されない 1 0 TCNT1 上昇時の比較一致で 0(Low)、下降時の比較一致で 1(High) 1 1 TCNT1 上昇時の比較一致で 1(High)、下降時の比較一致で 0(Low)
FOC1A/FOC1B(OC1A/OC1B出力強制) 動作種別が標準動作および比較一致タイマ/カウンタクリアの場合に、1 を設定することで強制的に比較一致を発生させます。割り込みやタイマ/カウンタのクリアは行われず、OC1A/OC1B ピンの出力のみ変更になる様です。自分は使い所がよく分りませんが… WGM11/WGM10(波形生成モード) TCCR1B レジスタの WGM13-12ビットと併せて動作種別(LECTURE 6 タイマ/カウンタについてを参照)を設定します。 WGM13 WGM12 WGM11 WGM10 動作種別 0 0 0 0 標準動作 0 0 0 1 8ビット位相基準PWM動作 0 0 1 0 9ビット位相基準PWM動作 0 0 1 1 10ビット位相基準PWM動作 0 1 0 0 比較一致タイマ/カウンタクリア(CTC)動作(OCR1Aピンがカウンタ最大値) 0 1 0 1 8ビット高速PWM動作 0 1 1 0 9ビット高速PWM動作 0 1 1 1 10ビット高速PWM動作 1 0 0 0 位相/周波数基準PWM動作(ICR1ピンがカウンタ最大値) 1 0 0 1 位相/周波数基準PWM動作(OCR1Aピンがカウンタ最大値) 1 0 1 0 位相基準PWM動作(ICR1ピンがカウンタ最大値) 1 0 1 1 位相基準PWM動作(OCR1Aピンがカウンタ最大値) 1 1 0 0 比較一致タイマ/カウンタクリア(CTC)動作(ICR1ピンがカウンタ最大値) 1 1 0 1 予約 1 1 1 0 高速PWM動作(ICR1ピンがカウンタ最大値) 1 1 1 1 高速PWM動作(OCR1Aピンがカウンタ最大値)
- WGM11 = WGM10 = 0 の場合(標準動作、CTC動作)(?=A/B)
- タイマ/カウンタ1制御レジスタB(TCCR1B)
ビット番号 7 6 5 4 3 2 1 0 マクロ ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10 初期値 0 0 0 0 0 0 0 0 各ビットの説明を以下に書きます。
ビット名 内容 ICNC1(捕獲入力1ノイズ消去器) 1 に設定することで、捕獲入力ノイズ消去器が有効になります。 ICES1(捕獲入力1エッジ選択) 1を設定すると ICP1 ピンの立ち上がりエッジで捕獲を認識し、0 を設定すると立下りエッジで捕獲を認識します。 WGM13/WGM12(波形生成モード) TCCR1A レジスタの WGM11-10ビット説明を参照 CS12/CS11/CS10(クロック選択) タイマ/カウンタ1で使用するクロックのシステムクロックに対する分周比、あるいは外部クロックの使用を以下の組み合わせで設定します。 CS12 CS11 CS10 内容 0 0 0 タイマ/カウンタ0停止 0 0 1 分周比無し 0 1 0 CK/8 0 1 1 CK/64 1 0 0 CK/256 1 0 1 CK/1024 1 1 0 外部クロック。T1 ピン(PDIP パッケージでは 2 ピン)の立ち下がりエッジ 1 1 1 外部クロック。T1 ピン(PDIP パッケージでは 2 ピン)の立ち上がりエッジ
- タイマ/カウンタ1カウンタ(TCNT1H,TCNT1L)(TCNT1 として 2 バイトアクセス可能)
16 ビットのカウンタ値を格納するレジスタです。
TCNT1 として 2 バイトアクセスする場合は、 アクセス時に割り込みが起きない様にしてください。--- TCNT1H ---
ビット番号 7 6 5 4 3 2 1 0 マクロ - - - - - - - - 初期値 0 0 0 0 0 0 0 0 --- TCNT1L ---
ビット番号 7 6 5 4 3 2 1 0 マクロ - - - - - - - - 初期値 0 0 0 0 0 0 0 0
- タイマ/カウンタ1比較Aレジスタ(OCR1AH,OCR1AL)(OCR1A として 2 バイトアクセス可能)
TCNT1 との比較に使われる 16 ビットレジスタです。
OCR1A として 2 バイトアクセスする場合は、 アクセス時に割り込みが起きない様にしてください。--- OCR1AH ---
ビット番号 7 6 5 4 3 2 1 0 マクロ - - - - - - - - 初期値 0 0 0 0 0 0 0 0 --- OCR1AL ---
ビット番号 7 6 5 4 3 2 1 0 マクロ - - - - - - - - 初期値 0 0 0 0 0 0 0 0
- タイマ/カウンタ1比較Bレジスタ(OCR1BH,OCR1BL)(OCR1B として 2 バイトアクセス可能)
TCNT1 との比較に使われる 16 ビットレジスタです。
OCR1B として 2 バイトアクセスする場合は、 アクセス時に割り込みが起きない様にしてください。--- OCR1BH ---
ビット番号 7 6 5 4 3 2 1 0 マクロ - - - - - - - - 初期値 0 0 0 0 0 0 0 0 --- OCR1BL ---
ビット番号 7 6 5 4 3 2 1 0 マクロ - - - - - - - - 初期値 0 0 0 0 0 0 0 0
- タイマ/カウンタ1捕獲レジスタ(ICR1H,ICR1L)(ICR1 として 2 バイトアクセス可能)
ICP1 ピンで捕獲を認識した時点の TCNT1 の値を格納する 16 ビットレジスタです。
ICR1 として 2 バイトアクセスする場合は、 アクセス時に割り込みが起きない様にしてください。--- ICR1H ---
ビット番号 7 6 5 4 3 2 1 0 マクロ - - - - - - - - 初期値 0 0 0 0 0 0 0 0 --- ICR1L ---
ビット番号 7 6 5 4 3 2 1 0 マクロ - - - - - - - - 初期値 0 0 0 0 0 0 0 0
- タイマ/カウンタ割り込みマスクレジスタ(TIMSK)(タイマ/カウンタ間共通)※タイマ/カウンタ1に関係有るのは TICIE1/OCIE1A/OCIE1B/TOIE1 です。
ビット番号 7 6 5 4 3 2 1 0 マクロ OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 OCIE0 TOIE0 初期値 0 0 0 0 0 0 0 0 各ビットの説明を以下に書きます。
ビット名 内容 TICIE1(捕獲割り込み許可) 1 を設定すると、捕獲割り込みが有効になります。 OCIE1A(比較A一致割り込み許可) 1 を設定すると、比較A一致割り込みが有効になります。 OCIE1B(比較B一致割り込み許可) 1 を設定すると、比較B一致割り込みが有効になります。 TOIE1(オーバーフロー割り込み許可) 1 を設定するとオーバーフロー割り込みが有効になります。
- タイマ/カウンタ割り込み要求フラグレジスタ(TIFR)(タイマ/カウンタ間共通)※タイマ/カウンタ1に関係有るのは ICF1/OCF1A/OCF1B/TOV1 です。
ビット番号 7 6 5 4 3 2 1 0 マクロ OCF2 TOV2 ICF1 OCF1A OCF1B TOV1 OCF0 TOV0 初期値 0 0 0 0 0 0 0 0 各ビットの説明を以下に書きます。
ビット名 内容 ICF1(捕獲フラグ) ICP1 ピンで捕獲を認識した場合に 1 が設定されます。割り込み処理時に自動的に 0 となる他、1 を書き込むことで 0 となります。 OCF1A(比較A一致フラグ) TCNT1 と OCR1A の値が一致した場合に 1 が設定されます。割り込み処理時に自動的に 0 となる他、1 を書き込むことで 0 となります。 OCF1B(比較B一致フラグ) TCNT1 と OCR1B の値が一致した場合に 1 が設定されます。割り込み処理時に自動的に 0 となる他、1 を書き込むことで 0 となります。 TOV1(オーバーフローフラグ) TCNT1 でのオーバーフロー発生時に 1 が設定されます。割り込み処理時に自動的に 0 となる他、1 を書き込むことで 0 となります。
○ 回路図
LECTURE 1 ATmega8535 および使用環境について に掲載してある全体回路図に対して、点滅させる LED 部分を赤枠で囲んだ図をこちらに置いておきます。…とは言っても、LECTURE 2 LED を点滅させる と全く同じなのでそちらの図へのリンクです。
○ サンプルプログラムと説明
タイマ/カウンタ1を使って LED を点滅させるサンプルプログラムを 08timer1.tar.gz からダウンロードできます。はじめに のページから、全てのサンプルプログラムを 固めた tar ファイルをダウンロードすることもできます。
中には
- Makefile
- util.h
- util.c
- timer1.h
- timer1.c
- main-ov.c
- main-comp.c
が格納されています。util.h/util.c については LECTURE 4 A/D 変換でボリューム(可変抵抗)値を読む の内容と同じで Makefile もほとんど変わらないので、それ以外について以下に載せます。なお、以下に掲載しているソースコードには修正 BSD ライセンス条項を含めていませんが、ソースコード配布は修正 BSD ライセンスに従います(はじめに のページの免責事項を参照してください)。
これまでにヒューズビットの設定を行ったことが一度も無い場合は、まず最初に make fuse を実行してください。fuse ターゲットについては、LECTURE 2 LED を点滅させる のサンプルプログラムの項を参照してください。
make 実行後、オーバーフロー割り込みを使用したプログラムをアップロードする場合は make uisp-ov を実行してください。また、比較一致割り込みを使用したプログラムをアップロードする場合は make uisp-comp を実行してください。実装方法が異なるだけで動作内容は同じです。
LED が約 500ms 毎に(1 秒間に 2 回程)ON/OFF を繰り返します。前回 と動作内容が同じなので、動画は載せません。
- timer1.h
1 #ifndef ___TIMER1_H_INCLUDED_ 2 #define ___TIMER1_H_INCLUDED_ 3 4 #include <avr/io.h> 5 #include <inttypes.h> 6 7 8 /* タイマークロック選択用マクロ */ 9 #define TIMER1_STOP 0x00 10 #define TIMER1_CK (_BV(CS10)) 11 #define TIMER1_CK_8 (_BV(CS11)) 12 #define TIMER1_CK_64 (_BV(CS11) | _BV(CS10)) 13 #define TIMER1_CK_256 (_BV(CS12)) 14 #define TIMER1_CK_1024 (_BV(CS12) | _BV(CS10)) 15 16 /* 比較出力モード選択用マクロ */ 17 #define COM_A_NONE 0x00 18 #define COM_A_TOGGLE (_BV(COM1A0)) 19 #define COM_A_HIGH_FIRST (_BV(COM1A1)) 20 #define COM_A_LOW_FIRST (_BV(COM1A1) | _BV(COM1A0)) 21 22 #define COM_B_NONE 0x00 23 #define COM_B_TOGGLE (_BV(COM1B0)) 24 #define COM_B_HIGH_FIRST (_BV(COM1B1)) 25 #define COM_B_LOW_FIRST (_BV(COM1B1) | _BV(COM1B0)) 26 27 /* 波形生成種別選択用マクロ */ 28 #define WGM1_NORMAL 0x00 29 #define WGM1_CTC_ICR1 (_BV(WGM13) | _BV(WGM12)) 30 #define WGM1_CTC_OCR1A (_BV(WGM12)) 31 #define WGM1_FAST_PWM_ICR1 (_BV(WGM13) | _BV(WGM12) | _BV(WGM11)) 32 #define WGM1_FAST_PWM_OCR1A (_BV(WGM13) | _BV(WGM12) | _BV(WGM11) | _BV(WGM10)) 33 34 #define timer1_ov_enable() { TIMSK |= _BV(TOIE1); } 35 #define timer1_ov_disable() { TIMSK &= ~_BV(TOIE1); } 36 #define timer1_compa_enable() { TIMSK |= _BV(OCIE1A); } 37 #define timer1_compa_disable() { TIMSK &= ~_BV(OCIE1A); } 38 #define timer1_compb_enable() { TIMSK |= _BV(OCIE1B); } 39 #define timer1_compb_disable() { TIMSK &= ~_BV(OCIE1B); } 40 #define timer1_ic_enable() { TIMSK |= _BV(TICIE1); } 41 #define timer1_ic_disable() { TIMSK &= ~_BV(TICIE1); } 42 #define timer1_clear_coma_mode() { TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0)); } 43 #define timer1_clear_comb_mode() { TCCR1A &= ~(_BV(COM1B1) | _BV(COM1B0)); } 44 45 #define timer1_stop()\ 46 { TCCR1B &= ~(_BV(CS12) | _BV(CS11) | _BV(CS10)); } 47 48 #define timer1_set_coma_mode(mode) {\ 49 timer1_clear_coma_mode();\ 50 TCCR1A |= (mode) & (_BV(COM1A1) | _BV(COM1A0));\ 51 } 52 53 #define timer1_set_comb_mode(mode) {\ 54 timer1_clear_comb_mode();\ 55 TCCR1A |= (mode) & (_BV(COM1B1) | _BV(COM1B0));\ 56 } 57 58 #define timer1_clear_wave_mode() {\ 59 TCCR1A &= ~(_BV(WGM11) | _BV(WGM10));\ 60 TCCR1B &= ~(_BV(WGM13) | _BV(WGM12));\ 61 } 62 63 #define timer1_set_wave_mode(mode) {\ 64 timer1_clear_wave_mode();\ 65 TCCR1A |= (mode) & (_BV(WGM11) | _BV(WGM10));\ 66 TCCR1B |= (mode) & (_BV(WGM13) | _BV(WGM12));\ 67 } 68 69 #define timer1_start(clock) {\ 70 timer1_stop();\ 71 TCCR1B |= (clock) & (_BV(CS12) | _BV(CS11) | _BV(CS10));\ 72 } 73 74 /* 75 * TCNT1 に設定するカウンタ値を指定する。 76 * 77 * 16ビットレジスタにアクセスするため、16ビットレジスタ用の 78 * 一時レジスタへの他アクセスが起きない状態で実行すること。 79 */ 80 static inline void 81 timer1_set_count(uint16_t count) 82 { 83 TCNT1 = count; 84 } 85 86 87 /* 88 * OCR1A に設定するカウンタ値を指定する。 89 * 90 * 16ビットレジスタにアクセスするため、16ビットレジスタ用の 91 * 一時レジスタへの他アクセスが起きない状態で実行すること。 92 */ 93 static inline void 94 timer1_set_ocr1a(uint16_t ocr1a) 95 { 96 OCR1A = ocr1a; 97 } 98 99 100 /* 101 * OCR1A に設定するカウンタ値を指定する。 102 * 103 * 16ビットレジスタにアクセスするため、16ビットレジスタ用の 104 * 一時レジスタへの他アクセスが起きない状態で実行すること。 105 */ 106 static inline void 107 timer1_set_ocr1b(uint16_t ocr1b) 108 { 109 OCR1B = ocr1b; 110 } 111 112 113 /* 114 * ICR1 に設定するカウンタ値を指定する。 115 * 116 * 16ビットレジスタにアクセスするため、16ビットレジスタ用の 117 * 一時レジスタへの他アクセスが起きない状態で実行すること。 118 */ 119 static inline void 120 timer1_set_icr1(uint16_t icr1) 121 { 122 ICR1 = icr1; 123 } 124 125 126 void timer1_ov_set_interrupt(void (*func)(void)); 127 void timer1_compa_set_interrupt(void (*func)(void)); 128 void timer1_compb_set_interrupt(void (*func)(void)); 129 void timer1_ic_set_interrupt(void (*func)(void)); 130 131 132 #endif 133 134 /* End of timer1.h */
- 8 〜 14 行目
タイマ/カウンタ1 用のクロック指定を楽にできる様にマクロを定義しています。TCCR1B レジスタの CS12-10 ビットに対応するビットを _BV() マクロで設定しています。本マクロは 後述の timer1_start() マクロ実行時に指定します。
- 16 〜 25 行目
比較出力モードを楽に指定できる様にマクロを定義しています。TCCR1A レジスタの COMaA1/COM1A0 - COM1B1/COM1B0 ビットに対応するビットを _BV() マクロで設定しています。本マクロは後述の timer1_set_coma_mode()/timer1_set_comb_mode() マクロ実行時に指定します。
- 27 〜 32 行目
波形生成種別を楽に指定できる様にマクロを定義しています。TCCR1A レジスタの WGM11-10 ビットおよび TCCR1B レジスタの WGM13-12 ビットに対応するビットを _BV() マクロで設定しています。 本マクロは後述の timer1_set_wave_mode() マクロ実行時に指定します。
- 34 〜 72 行目
記述が楽になる様に、あるいは分りやすくなる様にいくつかのマクロを定義しています。
timer1_ov_enable()/timer1_ov_disable() マクロは、TIMSK レジスタの TOIE1 ビットを操作することでオーバーフロー割り込みの有効化/無効化を行います。
timer1_compa_enable()/timer1_compa_disable() マクロは、TIMSK レジスタの OCIE1A ビットを操作することで比較A一致割り込みの有効化/無効化を行います。
timer1_compb_enable()/timer1_compb_disable() マクロは、TIMSK レジスタの OCIE1B ビットを操作することで比較B一致割り込みの有効化/無効化を行います。
timer1_ic_enable()/timer1_ic_disable() マクロは、TIMSK レジスタの TICIE1 ビットを操作することで捕獲割り込みの有効化/無効化を行います。
timer1_clear_coma_mode() マクロは、TCCR1A レジスタの COM1A1/COM1A0 ビットをクリアします。
timer1_clear_comb_mode() マクロは、TCCR1A レジスタの COM1B1/COM1B0 ビットをクリアします。
timer1_stop() マクロは、TCCR1B レジスタの CS12-10 ビットをクリア(クロック無し) することでタイマ/カウンタ1 を停止します。
timer1_set_coma_mode() マクロは、timer1_clear_coma_mode() で TCCR1A レジスタの COM1A1/COM1A0 ビットをクリアした後に、指定されたクロック設定を COM1A1/COM1A0 ビットに設定します。
timer1_set_comb_mode() マクロは、timer1_clear_comb_mode() で TCCR1A レジスタの COM1B1/COM1B0 ビットをクリアした後に、指定されたクロック設定を COM1B1/COM1B0 ビットに設定します。
timer1_clear_wave_mode() マクロは、TCCR1A レジスタの WGM11-10 ビットおよび TCCR1B レジスタの WGM13-12 ビットをクリアします。
timer1_set_wave_mode() マクロは、timer1_clear_wave_mode() で TCCR1A レジスタの WGM11-10 ビットおよび TCCR1B レジスタの WGM13-12 ビットをクリアした後に、指定された波形生成種別を WGM13-10 ビットに設定します。
timer1_start() マクロは、timer1_stop() でタイマ/カウンタ1 を停止した後に、 指定されたクロック設定を TCCR1B レジスタの CS12-10 ビットに設定することでタイマ/カウンタ1 を開始します。
- 74 〜 123 行目
こちらは型チェックを有効にしたかったので、マクロではなく inline 関数としました。
timer1_set_count() 関数は、指定された 16 ビット値を TCNT1 に書き込みます。 TCNT1 の初期値を設定したり、割り込み等のタイミングでカウンタ値を変えたい場合に使います。
timer1_set_ocr1a()/timer1_set_ocr1b()/timer1_set_icr1() は、指定された 16 ビット値をそれぞれ OCR1A/OCR1B/ICR1 に書き込みます。これらの値はそれぞれ比較A一致/比較B一致/捕獲に使用されます。
- timer1.c
1 #include <avr/interrupt.h> 2 #include <avr/io.h> 3 #include <inttypes.h> 4 5 #include "timer1.h" 6 7 8 static void (*timer1_ov_interrupt_handler)(void); 9 static void (*timer1_compa_interrupt_handler)(void); 10 static void (*timer1_compb_interrupt_handler)(void); 11 static void (*timer1_ic_interrupt_handler)(void); 12 13 14 /* 15 * オーバーフロー割り込みハンドラ 16 */ 17 ISR(TIMER1_OVF_vect) 18 { 19 timer1_ov_interrupt_handler(); 20 } 21 22 23 /* 24 * オーバーフロー時に割り込みハンドラ内で実行する 25 * ユーザ関数を設定する。 26 */ 27 void 28 timer1_ov_set_interrupt(void (*func)(void)) 29 { 30 timer1_ov_interrupt_handler = func; 31 } 32 33 34 /* 35 * 比較A一致割り込みハンドラ 36 */ 37 ISR(TIMER1_COMPA_vect) 38 { 39 timer1_compa_interrupt_handler(); 40 } 41 42 43 /* 44 * 比較A一致時に割り込みハンドラ内で実行するユーザ関数を設定する。 45 */ 46 void 47 timer1_compa_set_interrupt(void (*func)(void)) 48 { 49 timer1_compa_interrupt_handler = func; 50 } 51 52 53 /* 54 * 比較B一致割り込みハンドラ 55 */ 56 ISR(TIMER1_COMPB_vect) 57 { 58 timer1_compb_interrupt_handler(); 59 } 60 61 62 /* 63 * 比較B一致時に割り込みハンドラ内で実行するユーザ関数を設定する。 64 */ 65 void 66 timer1_compb_set_interrupt(void (*func)(void)) 67 { 68 timer1_compb_interrupt_handler = func; 69 } 70 71 72 ISR(TIMER1_CAPT_vect) 73 { 74 timer1_ic_interrupt_handler(); 75 } 76 77 78 /* 79 * 捕獲割り込みハンドラ内で実行するユーザ関数を設定する。 80 */ 81 void 82 timer1_ic_set_interrupt(void (*func)(void)) 83 { 84 timer1_ic_interrupt_handler = func; 85 } 86 87 /* End of timer1.c */
- 14 〜 20 行目
オーバーフロー割り込みを有効にした場合に使用する、割り込みハンドラを記述しています。 ATmega8535 のタイマ/カウンタ1 オーバーフロー割り込みを表すマクロは TIMER1_OVF_vect です。 実際には、後述する timer0_ov_set_interrupt() で登録されたユーザ関数を実行する様に実装しています。
- 23 〜 31 行目 (timer1_ov_set_interrupt())
前述のオーバーフロー割り込みハンドラ内で実際に実行する、ユーザ関数を登録します。
- 34 〜 40 行目
比較A一致割り込みを有効にした場合に使用する、割り込みハンドラを記述しています。 ATmega8535 のタイマ/カウンタ1 比較A一致割り込みを表すマクロは TIMER1_COMPA_vect です。 実際には、後述する timer1_compa_set_interrupt() で登録されたユーザ関数を実行する様に実装しています。
- 43 〜 50 行目 (timer1_compa_set_interrupt())
前述の比較A一致割り込みハンドラ内で実際に実行する、ユーザ関数を登録します。
- 53 〜 59 行目
比較B一致割り込みを有効にした場合に使用する、割り込みハンドラを記述しています。 ATmega8535 のタイマ/カウンタ1 比較一致割り込みを表すマクロは TIMER1_COMPB_vect です。 実際には、後述する timer1_compb_set_interrupt() で登録されたユーザ関数を実行する様に実装しています。
- 62 〜 69 行目 (timer1_compb_set_interrupt())
前述の比較B一致割り込みハンドラ内で実際に実行する、ユーザ関数を登録します。
- 72 〜 75 行目
捕獲割り込みを有効にした場合に使用する、割り込みハンドラを記述しています。 ATmega8535 のタイマ/カウンタ1 捕獲割り込みを表すマクロは TIMER1_CAPT_vect です。 実際には、後述する timer1_ic_set_interrupt() で登録されたユーザ関数を実行する様に実装しています。
- 78 〜 85 行目 (timer1_ic_set_interrupt())
前述の捕獲割り込みハンドラ内で実際に実行する、ユーザ関数を登録します。
- main-ov.c(オーバーフロー割り込み使用時の main)
1 #include <avr/interrupt.h> 2 #include <avr/io.h> 3 #include <avr/sleep.h> 4 5 #include "timer1.h" 6 #include "util.h" 7 8 9 static void timer1_ov_interrupt(void); 10 11 12 int 13 main(void) 14 { 15 /* PB0 ピンのみ出力設定 */ 16 DDRB |= _BV(DDB0); 17 pullup(); 18 19 timer1_ov_enable(); 20 timer1_ov_set_interrupt(timer1_ov_interrupt); 21 timer1_set_count(0); 22 23 sei(); 24 25 /* (8MHz/1)/65536 = 約122Hz */ 26 timer1_start(TIMER1_CK); 27 28 while (1){ 29 sleep_mode(); 30 } 31 32 return 0; /* 警告を避けるため */ 33 } 34 35 36 static void 37 timer1_ov_interrupt(void) 38 { 39 static int count = 0; 40 41 /* 42 * LED の状態変更周波数を約 2Hz (500ms) とする。 43 * 割り込み周期が約 122Hz なので 61回毎に状態を変える。 44 * 45 * ON-----OFF-----ON-----... 46 * 500ms 500ms 47 */ 48 if (++ count != 61) { 49 return; 50 } 51 52 count = 0; 53 PORTB ^= _BV(PB0); 54 } 55 56 /* End of main-ov.c */
本ファイルは、オーバーフロー割り込みを使う場合の main() を記述しています。
- 12 〜 33 行目 (main())
- pullup() 前に PORTB0 のみ出力方向に設定
- pullup() (pullup.h、PORTB0 以外の全入力ポートの内部プルアップを有効化)
- timer1_ov_enable() (timer1.h、オーバーフロー割り込み有効化)
- timer1_ov_set_interrupt() (timer1.h、オーバーフロー割り込み時に実行するユーザ関数の登録)
- timer1_set_count() (timer1.h、TCNT1 の初期値を設定)
を行った後、sei() (avr/interrupt.h) を実行してシステムの割り込みを有効化しています。
その後に timer1_start() を実行してタイマ/カウンタ1 の動作を開始します。 timer1_start() に TIMER1_CK を指定しているため、オーバーフロー割り込みの周期は約 122Hz ((8MHz/1)/65536)となります。
以後 sleep_mode() にてアイドル動作へ移行し、LED の点滅処理はオーバーフロー割り込みハンドラに任せます。
- 36 〜 54 行目 (timer1_ov_interrupt())
オーバーフロー割り込み時に実行されるユーザ関数です。
static 変数である count で割り込み回数を数え、61 回に一度 PORTB0 の値を反転します。 割り込み周期が約 122Hz であるため、反転周期は約 122/61 = 2 Hz となります。
- main-comp.c(比較一致割り込み使用時の main)
1 #include <avr/interrupt.h> 2 #include <avr/io.h> 3 #include <avr/sleep.h> 4 5 #include "timer1.h" 6 #include "util.h" 7 8 9 static void timer1_comp_interrupt(void); 10 11 12 int 13 main(void) 14 { 15 /* PB0 ピンのみ出力設定 */ 16 DDRB |= _BV(DDB0); 17 pullup(); 18 19 timer1_compa_enable(); 20 timer1_compa_set_interrupt(timer1_comp_interrupt); 21 timer1_set_wave_mode(WGM1_CTC_OCR1A); 22 timer1_set_count(0); 23 timer1_set_ocr1a(127); 24 25 sei(); 26 27 /* (8MHz/256)/128 = 約244Hz */ 28 timer1_start(TIMER1_CK_256); 29 30 while (1){ 31 sleep_mode(); 32 } 33 34 return 0; /* 警告を避けるため */ 35 } 36 37 38 static void 39 timer1_comp_interrupt(void) 40 { 41 static int count = 0; 42 43 /* 44 * LED の状態変更周波数を約 2Hz (500ms) とする。 45 * 割り込み周期が約 244Hz なので 122回毎に状態を変える。 46 * 47 * ON-----OFF-----ON-----... 48 * 500ms 500ms 49 */ 50 if (++ count != 122) { 51 return; 52 } 53 54 count = 0; 55 PORTB ^= _BV(PB0); 56 } 57 58 /* End of main-comp.c */
本ファイルは、比較一致割り込みを使う場合の main() を記述しています。
- 12 〜 35 行目 (main())
- pullup() 前に PORTB0 のみ出力方向に設定
- pullup() (pullup.h、PORTB0 以外の全入力ポートの内部プルアップを有効化)
- timer1_compa_enable() (timer1.h、比較A一致割り込み有効化)
- timer1_compa_set_interrupt() (timer1.h、比較A一致割り込み時に実行するユーザ関数の登録)
- timer1_set_wave_mode() (timer1.h、波形生成種別を設定)
- timer1_set_count() (timer1.h、TCNT1 の初期値を設定)
- timer1_set_ocr1a() (timer1.h、OCR1A の値を設定)
を行った後、sei() (avr/interrupt.h) を実行してシステムの割り込みを有効化しています。
この初期化フェーズで、timer1_set_wave_mode(WGM1_CTC_OCR1A) によって波形生成種別を "比較一致タイマ/カウンタクリア(CTC)(カウンタ最大値は OCR1A)"に設定しています。 これにより TCNT1 と OCR1A が一致した時点で TCNT1 をクリアし、0 からカウントを再開する動作を選択しています。
その後に timer1_start() を実行してタイマ/カウンタ1 の動作を開始します。 timer1_start() に TIMER1_CK_256 を指定しており、かつ OCR1A の値によりカウンタ最大値は 127 となるため、比較一致割り込みの周期は約 244Hz ((8MHz/256)/128)となります。
以後 sleep_mode() にてアイドル動作へ移行し、LED の点滅処理は比較A一致割り込みハンドラに任せます。
- 38 〜 56 行目 (timer1_comp_interrupt())
比較A一致割り込み時に実行されるユーザ関数です。
static 変数である count で割り込み回数を数え、122 回に一度 PORTB0 の値を反転します。 割り込み周期が約 244Hz であるため、反転周期は約 244/122 = 2 Hz となります。
以上で解説は終わりです。次回からは、タイマ/カウンタの機能を使ってサーボモータを動かしてみます。