[AVRexample] Timer1 オーバーフロー
<<目次へ戻る
8bit の Timer0 に比べてずっと長い時間が扱える。
また、カウンタ値が大きく1/256 1/64 などの短いプリスケーラでもイケるので
生成できる周波数が多彩。
今の所
- 5Hz (100ms割り込み)
- 50Hz(10ms割り込み)
を確認(測定器が無いので実際正確な値が出てるか?はわからん)
●多分正確?100ms毎の割り込み
CPUは内蔵発振 8MHz
8bit版 Timer0 と違う場所は赤で示す
#include <avr/io.h> #include <avr/interrupt.h> /* AVRwiki より拝借マクロ cbi() addrのbit番目をLowに sbi() addrのbit番目をHighに */ #define cbi(addr,bit) addr &= ~(1<<bit) #define sbi(addr,bit) addr |= (1<<bit) volatile int led; ISR (TIMER1_OVF_vect) { TCNT1 = 62411; led++; PORTB = led; } int main( void ) { DDRB = 0xFF; // PORTBの全ピンを出力に led = 0; TCCR1B = 0; // タイマ停止 TCNT1 = 62411; // カウンタは0からスタート TCCR1B = 4; // タイマ開始。プリスケールは ck/256 sbi(TIMSK,TOIE1); // タイマ1オーバーフロー割り込みの許可 sei(); // 割り込みの許可 for (;;); }
注意
ATtiny2313の場合 TIMSK はTimer0と共用。Megaの場合は別になる事がある
●計算方法
算数苦手なので自信無いです。
考え方は 8bit版の Timer0 と同じ。
100ms 10ms などの10で割り切れる波長を作るのを前提にしてる。
5Hz(100ms)を作る
- 内蔵発振8MHzを256分周する = 31,250 Hz
Timer0 では1024分周使ってた。
Timer1のこの説明では10で割り切ってビッタリの精度出したいので分周後の周波数下桁が 0 になるようにプリスケーラ値を下げてる。 - 欲 しい周波数というのは振幅の Low / High 両方合わせたもの。
しかしタイマーで設定できるのは片方だけの長さなので
欲しい周波 数を2倍して計算式に入れる。
5Hzが欲しいなら 100 を入れる。 - 16bit タイマは 0xFFFF の65536段分周器なので ” / 65536 ” の作用があると考える。
つまり、求める物は”何段分周するか?”である - 分周した い段数が決まったら 65536段 – (分周したい段) ← これを TCNT1 に入れる
5Hz(100ms)計算例
100Hz が欲しい。
「8MHz256分周後の周波数をさらに x 段分周すると、求めたい周波数 5Hz がでる。」
これの x について解く。
出た x を65536(段)から引く。
出た数値を TCNT1 に書き込む。
(8,000,000 / 256) / x = 2 * 5
x = 39.0625…..
65536 – 3125 = 62411
実測値
5Hz : 5.04〜5.07 Hz
50Hz :
秋月テスター使用
●注意
volatile int led; の volatile は割り込みルーチン内で変数使う場合に必要。
avr-libc: Frequently Asked Questions
割り込みルーチン内で書き換えたはずの変数が更新されません
割り込みルーチン内で書き換えたはずの変数が更新されません
を 参考の事。
ISP端子付けてるとPortB上位3bitが光るときリセットかかるっぽい。
回路図のようにISP端子外す 事。
<<目次へ戻る
Comments are currently closed.
