技術を間違った情熱に使いがちな人のページ

[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端子外す 事。

 

 

<<目次へ戻る

Posted in AVR, 電子

Comments are currently closed.