[AVRexample] Timer0 オーバーフロー
<<目次へ戻る
8bitタイマー 0 の件です。
タイマーは割り込みで使う場面がほとんどなので割り込み使用のサンプルのみ。
周波数は内蔵発振 8MHz。
オーバーフロータイマを使うより、CTCを使った方がずっと楽。
●単純なオーバーフロー割り込み
カウンタ0からスタートして 255 を超えたらオーバーフロー割り込みが発生する。
超えたら0に戻って勝手に再スタート。
#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 (TIMER0_OVF_vect) //オーバーフローするとここに飛んで来る { led++; PORTB = led; //変数 led の内容をPORTBに表示 } int main( void ) { DDRB = 0xFF; // PORTBの全ピンを出力に led = 0; TCCR0B = 0; // タイマ停止 TCNT0 = 0; // カウンタは0からスタート TCCR0B = 5; // タイマ開始。プリスケールは ck/1024 sbi(TIMSK,TOIE0); // タイマ0オーバーフロー割り込みの許可 sei(); // 割り込みの許可 for (;;); }
●ほぼ100Hzを創り出すオーバーフロー割り込み
#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 (TIMER0_OVF_vect) { TCNT0 = 217; // 単純オーバーフローにこれを追加しただけ led++; PORTB = led; } int main( void ) { DDRB = 0xFF; // PORTBの全ピンを出力に led = 0; TCCR0B = 0; // タイマ停止 TCNT0 = 217; // 217からスタート TCCR0B = 5; // タイマ開始。プリスケールは ck/1024 sbi(TIMSK,TOIE0); // タイマ0オーバーフロー割り込みの許可 sei(); // 割り込みの許可 for (;;); }
計算式
算数苦手なので自信無いです。
- 内蔵発振8MHzを1024分周する = 7,812.5 Hz
- 欲しい周波数というのは振幅の Low / High 両方合わせたもの。
しかしタイマーで設定できるのは片方だけの長さなので
欲しい周波数を2倍して計算式に入れる。
100Hzが欲しいなら 200 を入れる。 - 8bit タイマは 0xFF の256段分周器なので ” / 256 ” の作用があると考える。
つまり、求める物は”何段分周するか?”である - 分周したい段数が決まったら 256段 – (分周したい段) ← これを TCNT0 に入れる
計算例
100Hzが欲しい。
「8MHz1024分周後の周波数をさらに x 段分周すると、求めたい周波数 100Hz がでる。」
これの x について解く。
出た x を256(段)から引く。
出た数値を TCNT0 に書き込む。
(8,000,000 / 1024) / x = 2 * 100
x = 39.0625…..
256 – 39.0625 = 216.7… 約 217
実測値
100.3〜100.7 Hz
秋月テスター使用
●注意
ATtiny2313の TCCR0B レジスタは
ATmega では TCCR0 という名前になってる事多い。
volatile int led; の volatile は割り込みルーチン内で変数使う場合に必要。
avr-libc: Frequently Asked Questions
割り込みルーチン内で書き換えたはずの変数が更新されません
を参考の事。
ISP端子付けてるとPortB上位3bitが光るときリセットかかるっぽい。
回路図のようにISP端子外す事。
<<目次へ戻る
.
Comments are currently closed.
