タイマ0カウンタモード

 I/Oポートの次はタイマです。ATTiny2313にはtimer0とtimer1(それぞれ8bitと16bit)のタイマがありますが、ここではtimer0のオーバーフロー割り込みに絞って書いておきます。

対象マイコン

 タイマ自体はほとんどが対応してますが、種類によっては使えないタイマがあるので注意が必要です。今回もATTiny2313を前提として書きます。

割り込み

 タイマの前に割り込みが必要になってくるので先に。割り込みにはタイマによる割り込み・外部割り込みなどがあります。これらは割り込みベクタに登録されてて、ATTiny2313には21個あるようです。割り込みを使うにはinterrupt.hをインクルードします。
 割り込みが使えるようになるには

  • 割り込みハンドラ作成ISR(SIG_NAME)
  • 使用する割り込みをレジスタで許可
  • 全割り込み許可sei()

をやっていくことになります。因みにsei()に対して、全割り込みを禁止するにはcli()があります。

http://avrwiki.jpn.ph/wiki.cgi?page=Getting+Started+Notes+-+%B3%E4%A4%EA%B9%FE%A4%DF#p17

timer0概要

 基本的には、タイマを動かしてカウンタ内容を読み込む、オーバーフローや比較一致で割り込みをさせるという事をさせることが多いです。

レジスタ 名前
TCCR0 タイマ/カウンタ コントロールレジスタ
TCNT0 タイマ/カウンタ レジスタ
OCOR0 アウトプット コンペア レジスタ
TIMSK タイマ/カウンタ 割り込みマスクレジスタ
TIFR タイマ/カウンタ 割り込みフラグ レジスタ

 とりあえずTIFRに付いては省略します。
 TNCT0にカウンタの値が記録されていて、書き込んで値を変えることも可能です。OCOR0の値とTCNT0の値が一致したとき、あるいはTNCT0がオーバーフローしたときに(割り込みが許可されていれば)割り込みが起こります。

TCCR0 (ATTiny2313)

 今のところATTiny2313でしか調べてません。
 TCCR0は二つあります。


TCCR0

レジスタ 7 6 5 4 3 2 1 0
TCCR0A COM0A1 COM0A0 COM0B1 COM0B0 - - WGM01 WGM00
TCCR0B FOC0A FOC0B - - WGM02 CS02 CS01 CS00

TCCR0BレジスタのCS02, CS01, CS00でタイマのクロックを選択出来ます。


クロック選択

CS02 CS01 CS00 クロック
0 0 0 停止(カウンタが止まってる状態)
0 0 1 分周無し
0 1 0 8分周
0 1 1 64分周
1 0 0 256分周
1 0 1 1024分周
1 1 0 T0ピンの立ち下がり
1 1 1 T0ピンの立ち上がり

timer0割り込み関係

 TIMSKから設定します。


TIMSK (ATTiny2313)

レジスタ 7 6 5 4 3 2 1 0
TIMSK TOIE1 OCIE1A OCIE1B - ICIE1 OCIE0B TIOE0 OCIE0A

timer0で使うbitはOCIE0A, OCIE0B, TIOE0。それぞれ対応する割り込み名は

レジスタ SIG_NAME description
OCIE0A IMER0_COMPA_vect OCOR0A一致割り込み
OCIE0B IMER0_COMPB_vect OCOR0B一致割り込み
TIOE0 TIMER0_OVF_vect タイマ/カウンタ オーバーフロー割り込み

となっています。

サンプルコード


/*
 * タイマを使ってPD6を反転させる
 * 8MHzで1024分周ならおよそ110ms周期で点滅
 */
#include <avr/io.h>                                                                                                                                                                 
#include <avr/interrupt.h>

/* 割り込みハンドラ設定(タイマ0オーバーフロー) */
ISR(TIMER0_OVF_vect)
{
  PORTD ^= (1<<PD6); // PD6反転
}

int main(void)
{
  /* PD6を出力L設定 */
  DDRD  =  (1<<PD6);
  PORTD = ~(1<<PD6);

  TIMSK  = (1<<TOIE0); // タイマ0のオーバーフロー割り込み許可
  TCCR0B = 0x05;       // 1024分周でカウントスタート

  sei();               // 全体の割り込み許可

  while(1);
  return 0;
}