タイマ0その他モード

 前回の続きで、タイマ0の他の使い方。


前回:タイマ0カウンタモード - hijouguchiの日記


 TCCR0は前回を参考に。

タイマ/カウンタモード概要

前回の通常モードに加え様々な動作モードが存在します。


モード一覧

モード TOP値 OCR0x更新タイミング
通常 0xFF 即時
位相基準PWM 0xFF TOP(0xFF)
CTC OCR0A 即時
高速PWM 0xFF BOTTOM(0x00)
位相基準PWM OCR0A TOP(OCR0A)
高速PWM OCR0A BOTTOM(0x00)

 モードの設定はTCCRのWGM bitから設定します。WGMはTCCR0A, TCCR0Bにまたがっているので注意が必要です。TCCR0Bの方にあるWGM02は、TOP値を0xFFからOCOR0Aに変えるbit、TCCR0AにあるWGM01, WGM00が動作モードを設定するbitです。

OC0nピン

 OC0nピンは単純にタイマの状態によってHLのみを変更させることが出来る出力ピンです。例えばポーリングして複雑な事をさせるという場合は前回の様な割り込みを使うべきですが、PWMなどの単純なHとLを出すだけならこのピンを使った方が簡単です。ATTiny2313にはOC0A, 0C1A, OC0B, 0C1Bの4つありますがOC1nピンはきっとtimer1の方のピンだった気がしますのでこちらは割愛。基本的に動作は一緒ですし。


 これらのピンはIOポートとピンを共有しているので、衝突しているピンはあらかじめ出力設定にする必要があるので注意が必要です。


 詳しい動作はTCCRのCOM0 bitから設定しますが、モードによって若干異なるので、モードの項で適宜紹介します。

通常モード, Clear Timer on Compare Match Mode(CTCモード)

 TCNT0が255からカウントアップして0になるのが通常モードですが、CTCモードでは255でなくOCR0Aから任意に選択つまり、TOPを好きなように選ぶことが出来ます。


動作モード設定 通常,CTC

WGM02 WGM01 WGM00 MODE
0 0 0 通常
0 1 0 CTC


 CTCモードでは加えてOCOR0A(TOP値)を設定します。CTCモードではどんなタイミングでも更新することが出来ます。
 OC0は、TOPからBOTTOMに移ったとき(カウント洩れ)にCOM0 bitの状態によって以下のような変化をします。


COM0 通常,CTC

COM00 COM01 description
0 0 OC0変化させない
0 1 OC0トグル
1 0 OC0を0
1 1 OC0を1


OC0AはCOM0A1, COM0A0から、OC0BはCOM0B1, COM0B0から、設定できます。

設定の流れとしては

  • OC0を使う場合は出力ピンの設定
  • CTCモードで動作させる場合はOCR0Aの設定
  • TCCR0の設定

という具合になります。

高速PWM

 通常モードやCTCモードに加えて、OCOR0の値と一致したときピンの状態を変化させる事が出来るモードです。


動作モード設定 高速PWM

WMG02 WMG01 WMG00 TOP値
0 1 1 0xFF
1 1 1 OCOR0A


二つの違いはTOP値が固定(0xFF)か任意(OCOR0A)かです。OC0の挙動が一部異なるのでここも注意が必要です。


COM0 PWMモード(WMG0が011, AB共に共通)

COM00 COM01 description
0 0 OC0ピンを変化させない
0 1 OC0ピンを変化させない
1 0 OC0ピンをH→L(非反転動作)
1 1 OC0ピンをL→H(反転動作)

COM0 PWMモード(WMG0が111)*1

COM00 COM01 description
0 0 OC0ピンを変化させない
0 1 A:OC0Aピンをトグル
B:-
1 0 A:-
B:OC0BピンをH→L(非反転動作)
1 1 A:-
B:OC0BピンをL→H(反転動作)


 反転動作はBOTTOMでL出力、比較一致でHを出力するようになります。非反転はその論理値が逆になります。WMG0を111にした場合はTOPがOCOR0Aになるため、OCOR0Bの値はOCOR0Aより小さい値にしましょう。

位相基準PWM

 上記高速PWMと違いこちらはカウンタがカウントアップしたり、カウントダウンしたりします。BOTTOMからTOPまでカウントアップし、その後TOPからBOTTOMかでカウントダウンを、次にBOTTOMからTOPへ...と繰り返していきます。


動作モード設定 基準位相PWMモード

WGM02 WGM01 WGM00 TOP値
0 0 1 0xFF
1 0 1 OCOR0A

 二つの違いはTOPが0xFFか、OCOR0Aかの違いで高速PWMと基本的には同じです。OC0ピンの挙動も高速PWMに似たような動作です。

COM0 位相基準PWMモード(WMG0が001, AB共に共通)

COM00 COM01 description
0 0 OC0ピンを変化させない
0 1 OC0ピンを変化させない
1 0 ↑でL, ↓でH
1 1 ↑でH, ↓でL


COM0 位相基準PWMモード(WMG0が101)

COM00 COM01 description
0 0 OC0ピンを変化させない
0 1 A:OC0Aピンをトグル
B:-
1 0 A:-
B:↑でL, ↓でH
1 1 A:-
B:↑でH, ↓でL


 COM01:0が10の場合、比較一致がカウントアップ時に起きたときLを、カウントダウン時に起きたときHを出力します。COM1:0が11ならばその逆を出力します。

サンプルコード

CTC
PWM


CTCモード

/* ATTiny2313 */
#include <avr/io.h>                                                                                                                                                                 
int main(void)
{
  /* PD5(OC0B)を出力L設定 */
  DDRD  =  (1<<PD5);
  PORTD = ~(1<<PD5);
  
  OCR0A  = 192; // TOP値を192に設定

  /* OC0Bピンをトグル, CTC動作, 1024分周 */
  TCCR0A = 0x12;
  TCCR0B = 0x05;
  
  while(1);
  return 0;
}


高速PWMモード WGM:111

/* ATTiny2313 */
#include <avr/io.h>
int main(void)
{
  /* PD5(OCOB)を出力L設定 */
  DDRD  =  (1<<PD5);
  PORTD = ~(1<<PD5);

  /* PB2(OCOA)を出力L設定 */
  DDRB  =  (1<<PB2);
  PORTB = ~(1<<PB2);

  OCR0A  = 150;
  OCR0B  = 10; 

  /*  
   * CTC動作, 1024分周
   * OC0Aをトグル, OC0Bを非反転動作
   */
  TCCR0A = 0x63;
  TCCR0B = 0x0D;

  while(1);
  return 0;
}


基準位相PWMモード

/* ATTiny2313 */
#include <avr/io.h>
int main(void)
{
  /* PD5(OCOB)を出力L設定 */
  DDRD  =  (1<<PD5);
  PORTD = ~(1<<PD5);

  /* PB2(OCOA)を出力L設定 */
  DDRB  =  (1<<PB2);
  PORTB = ~(1<<PB2);

  OCR0A  = 200;
  OCR0B  = 100;

  /*  
   * 位相基準PWM動作, 1024分周
   * OC0A, OC0B共にカウントアップ時の一致ででL                                                                                                                                      
   */
  TCCR0A = 0xA1;
  TCCR0B = 0x05;

  while(1);
  return 0;
}

詳しくは

ATTiny2313データシート http://www.atmel.com/dyn/resources/prod_documents/doc8246.pdf

*1:一部データシートと内容を変更してあります。