「ATmega328でのタイマとPWMの使用方法」の版間の差分

📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

文字列「</source>」を「</syntaxhighlight>」に置換
 
(同じ利用者による、間の11版が非表示)
72行目: 72行目:
<br>
<br>
<center>
<center>
'''ピンの役割'''
{| class="wikitable"
{| class="wikitable"
! colspan = "4" | ピンの役割
|-
|-
!  !! 8bitタイマ(タイマ0) !! 16bitタイマ(タイマ1) !! 8bitタイマ(タイマ2)
!  !! 8bitタイマ(タイマ0) !! 16bitタイマ(タイマ1) !! 8bitタイマ(タイマ2)
81行目: 81行目:
| ピン出力 || OCR0A<br>OCR0B || OCR1A<br>OCR1B || OCR2A<br>OCR2B
| ピン出力 || OCR0A<br>OCR0B || OCR1A<br>OCR1B || OCR2A<br>OCR2B
|-
|-
| ピン名 || PD6(OCR0A)<br>PD5(OCR0B) || PB1(OCR1A)<br>PB2(OCR1A) || PB3(OCR2A)<br>PD3(OCR2A)
| ピン名 || PD6(OCR0A)<br>PD5(OCR0B) || PB1(OCR1A)<br>PB2(OCR1B) || PB3(OCR2A)<br>PD3(OCR2B)
|}
|}
</center>
</center>
105行目: 105行目:
|-
|-
|  
|  
! colspan="2" | PWM出力方法(コンペアマッチA)<br>出力ピン : OCR0A
! colspan="2" | PWM出力方法(コンペアマッチA)<br>出力ピン : OCR0A(PD6)
! colspan="2" | PWM出力方法(コンペアマッチB)<br>出力ピン : OCR0B
! colspan="2" | PWM出力方法(コンペアマッチB)<br>出力ピン : OCR0B(PD5)
! 設定なし
! 設定なし
! 設定なし
! 設定なし
159行目: 159行目:
! colspan="5" | WGMの役割 タイマモード設定
! colspan="5" | WGMの役割 タイマモード設定
|-
|-
! WGM02 !! WGM01 !! QGM00 !! 動作モード !! TOP
! WGM02 !! WGM01 !! WGM00 !! 動作モード !! TOP
|-
|-
| 0 || 0 || 0 || 標準 || 0xFF
| 0 || 0 || 0 || 標準 || 0xFF
165行目: 165行目:
| 1 || 0 || 0 || 予約 || -
| 1 || 0 || 0 || 予約 || -
|-
|-
| 0 || 1 || 0 || 位相基準PWM || 0xFF
| 0 || 0 || 1 || 位相基準PWM || 0xFF
|-
|-
| 1 || 0 || 1 || 位相基準PWM || OCRnA(nは0または1)
| 1 || 0 || 1 || 位相基準PWM || OCR0A
|-
|-
| 0 || 1 || 0 || CTC || OCRnA(nは0または1)
| 0 || 1 || 0 || CTC || OCR0A
|-
|-
| 1 || 1 || 0 || 予約 || -
| 1 || 1 || 0 || 予約 || -
175行目: 175行目:
| 0 || 1 || 1 || 高速PWM || 0xFF
| 0 || 1 || 1 || 高速PWM || 0xFF
|-
|-
| 1 || 1 || 1 || 高速PWM || OCRnA(nは0または1)
| 1 || 1 || 1 || 高速PWM || OCR0A
|}
|}
</center>
</center>
222行目: 222行目:
|-
|-
|  
|  
! colspan="2" | PWM出力方法<br>(コンペアマッチA)<br>出力ピン : OCR1A
! colspan="2" | PWM出力方法<br>(コンペアマッチA)<br>出力ピン : OCR1A(PB1)
! colspan="2" | PWM出力方法<br>(コンペアマッチB)<br>出力ピン : OCR1B
! colspan="2" | PWM出力方法<br>(コンペアマッチB)<br>出力ピン : OCR1B(PB2)
! 設定なし
! 設定なし
! 設定なし
! 設定なし
251行目: 251行目:
<center>
<center>
{| class="wikitable"
{| class="wikitable"
! colspan="9" | TCCR1B タイマ0設定レジスタ
! colspan="9" | TCCR1B タイマ1設定レジスタ
|-
|-
|  
|  
278行目: 278行目:
! colspan="6" | WGMの役割 タイマモード設定
! colspan="6" | WGMの役割 タイマモード設定
|-
|-
! WGM13 !! WGM12 !! WGM11 !! QGM10 !! 動作モード !! TOP
! WGM13 !! WGM12 !! WGM11 !! WGM10 !! 動作モード !! TOP
|-
|-
| 0 || 0 || 0 || 0 || 標準 || 0xFFFF
| 0 || 0 || 0 || 0 || 標準 || 0xFFFF
345行目: 345行目:
|-
|-
! 外部クロック<br>T0を立ち上がりエッジで
! 外部クロック<br>T0を立ち上がりエッジで
| 1 || 1 || 1
|}
</center>
<br><br>
== タイマ2のレジスタ設定 ==
タイマ2の設定レジスタであるTCCR2Aの設定を下表に示す。<br>
<center>
{| class="wikitable"
! colspan="10" | TCCR2A タイマ2設定レジスタ
|-
|
! colspan="2" | PWM出力方法(コンペアマッチA)<br>出力ピン : OCR2A
! colspan="2" | PWM出力方法(コンペアマッチB)<br>出力ピン : OCR2B
! 設定なし
! 設定なし
! colspan="3" | タイマのモード設定(一部)
|-
! ビット名
| 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0 ||
|-
! レジスタ名
| COM2A1 || COM2A0 || COM2B1 || COM2B0 || - || - || WGM21 || WGM20 ||
|-
! 波形出力なし
| 0 || 0 || 0 || 0 || - || - || 0 || 0 || 標準
|-
! コンペアマッチで出力が反転
| 0 || 1 || 0 || 1 || - || - || 1 || 0 || CTC
|-
! コンペアマッチでLow出力
| 1 || 0 || 1 || 0 || - || - || 0 || 1 || 位相基準PWM
|-
! コンペアマッチでHigh出力
| 1 || 1 || 1 || 1 || - || - || 1 || 1 || 高速PWM
|}
</center>
<br>
<center>
{| class="wikitable"
! colspan="9" | TCCR2B タイマ2設定レジスタ
|-
|
! colspan="2" | OCR2AおよびOCR2Bの強制変更
! 設定なし
! 設定なし
! タイマモード設定(一部)
! colspan="3" | クロック分周の設定
|-
! ビット名
| 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0
|-
! レジスタ名
| FOC2A || FOC2B || - || - || WGM22 || CS22 || CS21 || CS20
|-
! 役割
| colspan="2" | 強制コンペアマッチ<br>(非PWMモードのみ)
| - || - || 下で説明する
| colspan="3" | クロック分周の選択
|}
</center>
<br>
<center>
{| class="wikitable"
! colspan="5" | WGMの役割 タイマモード設定
|-
! WGM22 !! WGM21 !! WGM20 !! 動作モード !! TOP
|-
| 0 || 0 || 0 || 標準 || 0xFF
|-
| 1 || 0 || 0 || 予約 || -
|-
| 0 || 0 || 1 || 8bit位相基準PWM || 0xFF
|-
| 1 || 0 || 1 || 位相基準PWM || OCR2A
|-
| 0 || 1 || 0 || CTC || OCR2A
|-
| 1 || 1 || 0 || 予約 || -
|-
| 0 || 1 || 1 || 8bit高速PWM || 0xFF
|-
| 1 || 1 || 1 || 高速PWM || OCR2A
|}
</center>
<br>
<center>
{| class="wikitable"
! colspan="4" | クロック分周の設定
|-
! 設定 !! CS22 !! CS21 !! CS20
|-
! ビット名(TCCR2B)
| 2 || 1 || 0
|-
! タイマ停止
| 0 || 0 || 0
|-
! 分周なし
| 0 || 0 || 1
|-
! 分周 1 / 8
| 0 || 1 || 0
|-
! 分周 1 / 32
| 0 || 1 || 1
|-
! 分周 1 / 64
| 1 || 0 || 0
|-
! 分周 1 / 128
| 1 || 0 || 1
|-
! 分周 1 / 256
| 1 || 1 || 0
|-
! 分周 1 / 1024
| 1 || 1 || 1
| 1 || 1 || 1
|}
|}
363行目: 480行目:
*: レジスタ : TCCR2AとTCCR2B
*: レジスタ : TCCR2AとTCCR2B
*: HIGH時間を指定する : OCR2A(PB3)とOCR2B(PD3)
*: HIGH時間を指定する : OCR2A(PB3)とOCR2B(PD3)
<br><br>
== ソースコード ==
タイマ1を使用してPWM制御でLEDを点滅させる。<br>
PB0にスイッチを付けて、スイッチを押下した時にLEDが点滅するプログラムを以下に記述する。<br>
なお、PORTB = 0b00000001とすることで、PB0のプルアップが有効になるので、プルアップ抵抗を付ける必要はない。<br>
<br>
<syntaxhighlight lang="c++">
// タイマ0 : 8bit  : 0 -  255
// タイマ1 : 16bit : 0 - 65535
// 1[MHz]で動作すると仮定すると、1クロック0.000001[s]なので
// タイマ1 : 0.000001 * 65536 = 65.5[ms]までOK
/*  高速PWMモード
  ICR1 : 最大値
  OCR1A(データシートのピン配置ではOC1A) : 真ん中
    |
ICR1 ----/\------------------------
    |    /  \
    |  /      \        /
OCR1A /---------\------/-----------
    | /            \  /
    |/              \/
  PB1 出力波形
    |
    | ̄|                  | ̄|
    |  |__________________|  |___
    |
  CTCモード : 最大値はICR1
  通常モード : 最大値はOCR1A
*/
// タイマ1を使用
#include <avr/io.h>
int main()
{
    // 制御レジスタA
    TCCR1A = 0b10000010;  // 10 : コンペアマッチAでLOW, 10 : 高速PWM動作
    // 制御レジスタB
    TCCR1B = 0b00011001;  // 11 : 高速PWM動作, 001 : 分周なし
    // 最大値
    ICR1 = 64999;  // 0から数える(全体時間は65[ms])
    // 0.000001 * 65000 : 65[ms]
    // HIGHの時間(クロック数)
    OCR1A = 32499;  // 0から数える(High時間は32.5[ms])
    // 0.000001 * 32500 : 32.5[ms]
    // OCR1AはPB1ピン
    DDRB = 0b11111110;  // PB0のみ入力
    PORTB = 0b00000001; // PB0をプルアップ
    while(1)
    {
      if(bit_is_clear(PINB, PB0))
      {  // PB0が0(オン)の場合
          OCR1A = 32499;  // PB1 HIGH時間 32.5[ms]
          // OCR1Aの値を変えることで、LEDが光る時間を調節できる
      }
      else
      {
          OCR1A = 0;  // PB1 HIGH時間 0[ms]
      }
    }
    return 0;
}
</syntaxhighlight>
<br>
===== PWMの設定 =====
まず、TCCR1AとTCCR1Bで、タイマ1を使用するための設定を行う。<br>
<br>
次に、ICR1で、タイマ(カウンタ)のTOP値(上記では、ICR1 = 64999)を決める。0からカウントするので、65000回カウントアップされる。<br>
1[MHz](1[us])なので、0.000001 * 65000 = 65[ms]が1周期となる。<br>
<br>
最後に、OCR1Aで、PWM波形のHIGH時間(OCR1A = 32499)を決める。<br>
同様に、0.000001 * 32500 = 32.5[ms]が、1周期のHIGH時間となる。<br>
<br>
===== その他の設定 =====
まず、DDRBで入出力設定を行い、PORTBでPB0のプルアップを有効にする。<br>
<br>
次に、bit_is_clear(PINB, PB0)関数において、PB0が0(スイッチがオンの状態)の時、trueとなる。<br>
<br>
スイッチがオンの状態で、PWM出力波形のHIGH時間を32.5[ms]にする。<br>
スイッチがオフの状態で、HIGH時間を0[ms]にする。<br>
<br>
===== 作成した回路 =====
ここでは、スイッチを押下するとPWM制御により、LEDが点滅する回路を以下に記載する。<br>
[[ファイル:ATmega328 Timer PWM 2.jpg|フレームなし|中央]]
<br><br>
== サンプルコード2 ==
タイマ割り込みでデューティ比を変化せるプログラムを以下に記述する。<br>
PWMの周期を2048[us]、12.5[ms]ごとに割り込みを発生させて、デューティ比を0.78と0.04に切り替える。<br>
<syntaxhighlight lang="c++">
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
unsigned char i;
// タイマ2 コンペアマッチA割り込み
ISR(TIMER2_COMPA_vect)
{
    if(i == 255)
    {
      i = 0;
    }
    else
    {
      i++;
    }
    if(i % 2 == 0)
    {
      OCR0A = 10;
    }
    else
    {
      OCR0A = 200;
    }
}
int main()
{
    // タイマ0
    TCCR0A = 0b10100011;  // 1010 = OCR0A出力とOCR1A出力, 011 = 高速PWM(TOP値 = 0xFF)
    TCCR0B = 0b00000010;  // 010 = 分周比 : 8(PWM周期 = 1 / (1,000,000[Hz] / 8分周) * 256 = 2048[us])
    // タイマ2(割り込み用 : コンペアマッチAで割り込み開始)
    TCCR2A = 0b00000010;  // 0000 = ピン出力なし, 010 = CTC(TOP値 = OCR2A)
    TCCR2B = 0b00000101;  // 101 = 分周比 : 128
    OCR2A  = 97;          // 12.5[ms]ごとに割り込み(1 / (1,000,000[Hz] / 128分周) * 98)
    TIMSK2 = 0b0000010;   // コンペアマッチAの割り込みを有効
    // 方向レジスタの設定
    DDRB  = 0xFF;  // PORTB2を出力
    DDRD  = 0xFF;  // PORTD5を出力
    // 割り込み許可
    sei();
    while(1)
    {
      ;
    }
}
</syntaxhighlight>
<br><br>
<br><br>


__FORCETOC__
__FORCETOC__
[[カテゴリ:AVR]]
[[カテゴリ:AVR]]