タイマとその応用

そもそもタイマとはなんぞや?
基本的には、時間を計るものであるが、マイコンに搭載されているタイマには、様々な機能がある。例えば、

イベントの発生間隔を計ったり

  • PWMを出力したり
  • パルスを出力したり
  • 時間が経過した事を知らせたり

などである。AVRマイコンにも、同様の機能が搭載されている。ATMega32U4には、4つのタイマが実装されている。それぞれ、

タイマ0 (1) カウンタ長8bit
(2) 独立した2つの比較器(TCNTとの)
(3) 比較一致(コンペア・マッチ)で設定値をTCNTに自動的に再設定
(4) PWM出力機能(高速PWM、位相基準PWM)
(5) PWMの周期を可変可能
(6) 周波数発生器(プリスケーラ)
(7) 3つの独立した割り込みイベント (TOV0, OCF0A, and OCF0B)
タイマ1
タイマ3
(1) カウンタ長16bit
(2) 完全な16bit構成
(3) 独立した3つの比較器(TCNTとの)
(4) インプット・キャプチャ機能(外部入力のイベント発生時刻の計測等)
(5) インプット・キャプチャ機能のノイズキャンセラ
(6) 比較一致(コンペア・マッチ)で設定値をTCNTに自動的に再設定
(7) PWM出力機能(高速PWM、位相基準PWM)
(8) PWMの周期を可変可能
(9) 周波数発生器(プリスケーラ)
(10) 外部イベントのカウンタ
(11) 10個の独立した割り込みイベント (TOV1, OCF1A, OCF1B, OCF1C, ICF1, TOV3, OCF3A, OCF3B,OCF3C and ICF3)
タイマ4
              

 
(1) カウンタ長8bit
(2) Up to 10-Bit Accuracy
(3) 独立した3つの比較器(TCNTとの)
(4) 比較一致(コンペア・マッチ)で設定値をTCNTに自動的に再設定
(5) PWM出力機能(高速PWM、位相基準PWM)
(6) 拡張PWM機能
(7) PWMの周期を可変可能
(8) PWMのチャネルごとに独立したデッドタイム生成器
(9) PWMのレジスタを同期更新
(10) 5個の独立した割り込みイベント (TOV4, OCF4A, OCF4B, OCF4D, FPF4)
(11) 高速 同期/非同期クロックモード
(12) 独立した周波数発生器(プリスケーラ)

の様な特徴を持つ。なんだかよく分からんと思うので、詳細については、以降に解説する。
それぞれのタイマの機能は、そのタイマに固有の機能で無ければ、同じように使う事が出来る。

 

タイマ0の構造

 タイマ0は8ビットのカウンタ/タイマである。8ビットというのはTCNTのデータ長で、このレジスタ(カウンタ)がタイマ機能の要となる。
以下に、タイマの全体構成を示す。


                            図1 タイマユニットの構成


タイマ0の動作モード

  タイマ0には、4つの動作モードがある。それぞれ、

  • 標準モード
     TCNT0は単純にカウントアップされる。比較一致などの動作は行わず、0 → 255 → 0(以降繰り返し)TCNT0が0になる時に割り込みイベントが発生し、割り込みがマスクされていなければ、割り込みハンドラが起動される。


                          図2  標準モードの動作 
  1. プリスケーラは、システムクロックを分周(何分の1かにすること)を行い、TCNTに供給する。
  2. TCNTはプリスケーラが分周した信号(パルス)をカウントする。
  3. TCNTは8ビットのカウンタなので、255になると0に戻る。この時、TOIE0割り込みイベントが発生する。
  4. 割り込みが許可されていれば、TIMER0_OVF割り込みハンドラが起動される。
  • CTCモード
    OCR0AがTCNT0の上限値を定める。TCNT0とOCR0Aの値が一致すると、TCNT0は0にクリアされる。同時に割り込みイベント(OCF0A)が発生する。
           
                         図3  CTCモードの動作
  1. 1,2については、標準モードと同様。
  2. TCNTとOCR0Aの値が一致した時にOCF0A割り込みイベントが発生。
  3. TCNTの値は0にリセット。
  4. 割り込みが許可されていれば、TIMER0_CMPA割り込みハンドラが起動される。
  • 高速PWM
    TCNT0とOCR0A、OCR0Bを使ってPWM(TCNT0の値はのこぎり状に変化する)を出力する。WGM02の設定によって、動作が変化する。いずれもTCNT0が上限値に達した時に、TOV割り込みイベントが発生する。
    • WGM02=0の場合:OCR0AとOCR0Bは独立して動作する。それぞれ、TCNT0と値の比較を行い、一致した場合は、PWM波形の出力を行う。TCNT0は0xFFに達した後、0にリセットされ、以降、+1ずつカウント動作を繰り返す。
    • WGM02=1の場合:OCR0Aは、TCNT0の上限値を設定する。上限値に達したTCNT0は0にリセットされ、以降、+1ずつカウント動作を継続する。OCR0BはTCNT0と値の比較を行い、一致した場合はPWM波形の出力を行う。
       
  • 位相基準PWM

 

レジスタの種類

タイマ0には4つのレジスタがある。それぞれの機能を以下に説明する。

レジスタ名 機能
TCNT   プリスケーラもしくは外部からのカウント信号をカウントアップ(もしくはダウン)するレジスタ。プリスケーラの出力するカウント信号は、システムクロックを何分の一かにしたものになる。(後述)
カウンタの起動・停止は、カウント信号の有無で行う。
OCR0A  比較・一致(コンペア・マッチ)を行うためのレジスタ。TCNTと比較する値を設定する。TCNTがカウントする数値と比較する事で、時間を計る。一致 が発生した場合は、比較器と波形発生器を通じてPWMやパルス信号の出力を行う。なお、信号の出力パターンについては、TCCR0A、TCCR0Bで設定 する。
OCR0B 比較・一致(コンペア・マッチ)を行うためのレジスタ。OCR0Aと同様。
TCCR0A タイマモードの切り替えなど、タイマユニットの設定を行うレジスタ。
 TCCR0B  プリスケーラの設定などを行う。
TIMSK0 タイマ0に関連する割り込みをマスクする。
bit2:OCIE0B  bit1:OCIE0A  bit0:TOIE0    (1で割り込み許可、0で禁止)    
TIFR0 タイマ0に関連する割り込みを記録する。
bit2:OCF0B  bit1:OCF0A  bit0:TOV0  
  (割り込み発生時に1にセット。0を書き込むとイベントをキャンセル出来る)

以上のレジスタの機能は、タイマモードの設定によって変化する事に注意。
 

TCCR0Aのビット配列

bit 7 6 5 4   3    2   1 0
ビットの名称 COM0A1 COM0A0 COM0B1 COM0B0 - - WGM01 WGM00
機能 OCR0AレジスタとTCNTの値が一致した
時の波形出力(OC0Aピン)を設定
OCR0BレジスタとTCNTの値が一致した
時の波形出力(OC0Bピン)を設定
    動作モードを設定


TCCR0Bのビット配列

bit 7 6    5      4      3      2   1 0
ビットの名称 FOC0A FOCOB - - WGM02 CS02 CS01 CS00
機能 ※1 ※2     動作モードを設定 プリスケーラ設定※3

※1   PWMモード以外で動作。1を書き込むと、OCR0AとTCNTが一致(コンペアマッチ)したとみなされ、OC0Aピンから信号が
   出力される。(割り込みイベントは発生しない)
※2   PWMモード以外で動作。1を書き込むと、OCR0BとTCNTが一致(コンペアマッチ)したとみなされ、OC0Bピンから信号が
      出力される。(割り込みイベントは発生しない)
※3 プリスケーラによるシステムクロックの分周比は、以下の通り。

CS02 CS01 CS00 動作
0 0 0 タイマ停止
0 0 1 分周しない(システムクロックを直接供給)
0 1 0 1/8
0 1 1 1/64
1 0 0 1/256
1 0 1 1/1024
1 1 0 外部クロック入力(T0ピン)、立ち下がりエッジ
1 1 1 外部クロック入力(T0ピン)、立ち上がりエッジ



標準モードの設定

  TCCR0AのWGM01,WGM00及びTCCR0BのWGM02ビットをそれぞれ0に設定すると、標準モードになる。
 また、OC0Aピン及びOC0Bピンからデジタル信号の出力を行う場合は、以下の様に設定する。

OC0A(29ピン)の出力設定

TCCR0A  bit 7 6 備  考
ビットの名称 COM0A1 COM0A0  
波形出力なし 0 0 PB7は通常のIOポート
TCNTが255→0で切替 0 1 一致する度にOC0Aが1→0→1の様に切り替わる
TCNTが255→0でLow 1 0  
TCNTが255→0でHigh 1 1  

 

 

 

 

 

 

 

OC0B(4ピン)の出力設定

TCCR0A  bit 5 4 備  考
ビットの名称 COM0B1 COM0B0  
波形出力なし 0 0 PD0は通常のIOポート
TCNTが255→0で切替 0 1 一致する度にOC0Bが1→0→1の様に切り替わる
TCNTが255→0でLow 1 0  
TCNTが255→0でHigh 1 1  


 

 

 

 

 

 


サンプルプログラム  (一定周期でボード上のLEDを点滅)

#define F_CPU 16000000

#include < avr/io.h >
#include < util/delay.h >
#include < avr/interrupt.h >

ISR (TIMER0_OVF_vect)       // 割り込みハンドラ
{
    PORTC++;
}

int main()
{
    CLKPR = 0x80; CLKPR = 0; // システムクロックを16MHzとして動作

    DDRC = 0b10000000;         // PC7を出力に
    DDRB = 0b10000000;         // OC0Aを出力
    DDRD = 0b00000001;         // OC0Bを出力

    TCCR0B = 0;             // タイマ停止
    TCCR0A = _BV(COM0A0)|_BV(COM0B0);    // TCNTが255→0に変化する度に0/1を切り替え
    TIMSK0 |= _BV(TOIE0);   // TIMER0_OVF割り込みを許可
    TCCR0B = 5;             // タイマスタート(プリスケーラは1/1024)

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

    while(1);
}



CTCモードの設定

 標準モードでは、割り込み周期はプリスケーラの設定でしか変化できないが、CTCモードでは、TCNTの上限値をOCR0Aで設定できるので、設定の自由度が大きくなる。

 TCCR0AのWGM1ビットを1、WGM0ビットを0、TCCR0BのWGM2ビットを0に設定すると、CTCモードになる。


OC0A(29ピン)の出力設定

TCCR0A  bit 7 6 備  考
ビットの名称 COM0A1 COM0A0  
波形出力なし 0 0 PB7は通常のIOポート
OCR0Aと値の一致で切替 0 1 一致する度にOC0Aが1→0→1の様に切り替わる
OCR0Aと値の一致でLow 1 0  
OCR0Aと値の一致でHigh 1 1  

 

 

 

 

 

 

 

OC0B(4ピン)の出力設定

TCCR0A  bit 5 4 備  考
ビットの名称 COM0B1 COM0B0  
波形出力なし 0 0 PD0は通常のIOポート
OCR0Bと値の一致で切替 0 1 一致する度にOC0Aが1→0→1の様に切り替わる
OCR0Bと値の一致でLow 1 0  
OCR0Bと値の一致でHigh 1 1  

 

 

 

 

 

 

 

サンプルプログラム

#define F_CPU 16000000

#include < avr/io.h >
#include < util/delay.h >
#include < avr/interrupt.h >

ISR (TIMER0_COMPA_vect)       // 割り込みハンドラ
{
    PORTC++;
}

int main()
{
//    CLKPR = 0x80; CLKPR = 0; // システムクロックを16MHzとして動作。この設定を行わないと2MHzで動作

    DDRC = 0b10000000;       // IOポートを出力に
    DDRB = 0b10000000;         // OC0Aを出力
    DDRD = 0b00000001;         // OC0Bを出力

    TCCR0B = 0;             // タイマ停止
    TCCR0A = _BV(COM0A0)|_BV(COM0B0);    // TCNTとOCR0A(OCR0B)が一致する度に0/1を切り替え
    TIMSK0 |= _BV(OCIE0A);   // TIMER0_CMPA割り込みを許可
    OCR0A = 208;            // TCNTの上限値を定める。
    OCR0B = 200;            //    OCR0AとOCR0Bを別々に設定すると、値の小さい方が有効になる。
    TCCR0B = 5;             // タイマスタート(プリスケーラは1/1024)

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

    while(1);
}

 

 

高速PWMモード

こちらを参照のこと。

最終更新:2016年03月22日 16:14