PIC24FのPWM生成方法
(可変抵抗のツマミを回してLEDの点滅速度を可変します)

〔PICの動かせ方入門に戻る〕


PIC24FJ64GB002でPWMを行うやり方についてメモして置きます。
(PIC24FJ64GA002は機能が古い為にレジスタの使い方等が若干異なります)
PIC24FJ64GB002でPWMを生成させるには出力コンペアモジュールを利用する事になります。

ここでは、
MPLAB X V4.10MPLAB(R) XC16 C Compiler Version 1.30コンパイラ を使用しての記事です。
出力コンペア(PWM)のPIC24F用日本語リファレンスマニュアルはこちらを参照下さい。

出力コンペアモジュールは5個(OC1/2/3/4/5)有るので5個のPWM出力が出来ます
出力コンペアモジュール出力端子の"OC1/2/3/4/5"は、PPS機能でピンを割り付けないと使えません。

ピンの構成図
RP0-RP11/RP13-RP15のどこでも自由に割り付け可能

今回は、OC1/OC2の2モジュールを利用したので下記の様に割り付けました。
 #include <xc.h>
 #include <PPS.h>                  // Pin Re-Mapping peripheral library

 #pragma config IOL1WAY = OFF      // 周辺機器のピン割り付けは何度でも変更出来る様に許可

   PPSUnLock ;
     iPPSOutput(OUT_PIN_PPS_RP8,OUT_FN_PPS_OC2) ; // RB8(OC2)
     iPPSOutput(OUT_PIN_PPS_RP7,OUT_FN_PPS_OC1) ; // RB7(OC1)
   PPSLock ;
※ "#include <PPS.h>"のライブラリを使う場合はこちらを参照し、インストールを行います。

出力コンペアのモード

(1)単一比較一致モード
  タイマのカウント値がOCxRと一致した時にOCx出力ピンから出力するモード。
  出力パターンは以下の3パターンが有ります。
  ・LowからHighに出力する
  ・HighからLowに出力する
  ・出力を反転する

(2)二重比較一致モード
  タイマのカウント値がOCxRと一致した時にOCx出力ピンをHighにし、OCxRSと一致した時に
  Lowに駆動します。
  出力パルスパターンは以下の2パターンが有ります。
  ・ワンパルスの出力
  ・連続パルスの出力

(3)単純PWMモード
  このページではこのモードのみ以下で実験しています。
  又、エッジ整列PWMモードとセンター整列PWMモード(24FJ64GA002には無し)が有ります。
  尚、センター整列PWMモードが有ればモータアプリケーション等で利用出来るでしょう。

  ※ フォルト動作を有効にすれば、フォルトピン(OCFA/OCFB)の動作によりPWM出力を
    一時停止出来ます。

(4)カスケードモード
  通常は16ビットタイマですが、OC1/OC2とOC3/OC4と2モジュールをカスケードする事により
  32ビットタイマとして動作させるモードです。(24FJ64GA002には無し)

クロックのタイムベース

出力コンペアのタイムベースは、Timer1〜Timer5周辺クロック(FCY=Fosc/2)のいずれかを使います。
Timerを使うメリットは、プリスケーラが利用出来る事でしょう。

タイムベースの1カウント時間は?
 (1秒/FCY)X プリスケーラ設定値
 ・Fosc=32MHz(FCY:16MHz)でプリスケーラ=1:1での1カウント時間は
 (1 / 16MHz) * 1 = 0.0625(62.5ns) → これが最少単位の1カウントの時間です。
 因みに、プリスケーラは1:1/1:8/1:64/1:256が利用出来る。
 タイムベースが周辺クロック(FCY)使用する場合はプリスケーラ1:1で計算する。

1000HzのPWMを生成するには?
 1000000us/1000Hz=1000us(1ms)が1KHzの1サイクル時間なのでぇ、
 1000000ns/62.5ns=16000だから16000カウントさせれば1msになる。
 なのでPRx=16000-1でセットする。
 もしタイムベースが周辺クロックならOCxRS=16000-1でセットする。

《実験回路とサンプルプログラム》

配線図 左が実験回路で、電源は3.3Vです。
半固定抵抗はAN0(RA0:2番ピン)に接続しています。
RB7(16番ピン)にOC1を割り付けてPWM出力を行うので、
LEDを繋いでいます。
又、サンプルプログラムによっては、
RB8(17番ピン)にOC2を割り付けています。


↓ここからサンプルプログラムソースファイルをダウンロードして下さい。
PWM.zip

プログラムソースをダウンロードしたら解凍して下さい。
MPLAB Xにてプロジェクトを作成し、解凍ファイルをプロジェクトディレクトリにコピーして
プロジェクトに取込んで下さい。
次にコンパイルPIC書き込みを実行して下さい。

ダウンロードファイルを解凍すると下記の様なファイル構成です。
 PWM_FCY.c・・・・・・・・・・・・・・・出力コンペア機能のエッジ整列PWMモードサンプルプログラム1
 PWM_TIMER2.c・・・・・・・・・・・出力コンペア機能のエッジ整列PWMモードサンプルプログラム2
 PWM_Complement.c・・・・・・出力コンペア機能のエッジ整列PWMモードサンプルプログラム3
 PWM_Center.c・・・・・・・・・・・・出力コンペア機能のセンター整列PWMモードサンプルプログラム4
 このいずれかの1ファイルのみでコンパイルします。

 尚、CPUのクロックは32MHzを想定しています。

《周辺クロック(FCY)での使用例》

ここで使用するサンプルプログラムは、"PWM_FCY.c"を使います。

出力コンペアのモードは、”エッジ整列PWMモード”でOC1から出力を行います。
このモードではコンペアのクロックに、”周辺クロック(FCY)”を利用します。
又、このモードはタイマを使わないので OC1RS に1周期の設定を行います。
#define F_CYCLE 15999               // OC1RSのサイクル(1周期)

     // OC1機能をエッジ整列PWMモードで初期化
     OC1CON1 = 0b0001110000000110 ; // FCY使用エッジ整列PWMモード
     OC1CON2 = 0b0000000000011111 ; // 16bit、同期イベントはOC1(OC1RS))
     OC1R    = 0 ;                  // デュティ比は0%で初期化
     OC1RS   = F_CYCLE ;            // 16000(0x3E80)=1ms(1000Hz)が1周期
OC1R にデュティ比を設定しますが、値は"F_CYCLE"が1周期なので0〜F_CYCLE(100%)です。
なので、可変抵抗値(0-1023)をスケール変換して OC1R にセットしています。
可変抵抗を回すとLEDの明るさが変わるでしょう。

《タイマ2での使用例》

ここで使用するサンプルプログラムは、"PWM_TIMER2.c"を使います。

出力コンペアのモードは、”エッジ整列PWMモード”でOC1から出力を行います。
このモードではコンペアのクロックに、”タイマ2”を利用します。
タイマ2を使うので1周期の設定は PR2 で行います。
#define F_CYCLE 15999               // Timer2のサイクル(1周期)

     // OC1機能をエッジ整列PWMモードで初期化
     OC1CON1 = 0b0000000000000110 ; // Timer2使用エッジ整列PWMモード
     OC1CON2 = 0b0000000000001100 ; // 16bit、同期イベントはTimer2
     OC1R    = 0 ;                  // デュティ比は0%で初期化
     // タイマー2の設定
     T2CON = 0b0000000000000000 ;   // プリスケーラカウント値 1:1、内部クロック(FCY)で使用、16ビット動作
     TMR2  = 0 ;                    // タイマー2のカウンターを初期化する
     PR2   = F_CYCLE ;              // 16000(0x3E80)=1ms(1000Hz)が1周期
     T2CONbits.TON = 1 ;            // タイマー2開始
OC1R にデュティ比を設定しますが、値は"F_CYCLE"が1周期なので0〜F_CYCLE(100%)です。
なので、可変抵抗値(0-1023)をスケール変換して OC1R にセットしています。
可変抵抗を回すとLEDの明るさが変わるでしょう。

《相補出力PWM》

ここで使用するサンプルプログラムは、"PWM_Complement.c"を使います。

出力コンペアのモードは、”エッジ整列PWMモード”でOC1とOC2から出力を行います。
又、相補出力PWMなのでOC2出力を反転させます。
このモードではコンペアのクロックに、”タイマ2”を利用します。
タイマ2を使うので1周期の設定は PR2 で行います。
複数の出力コンペアを同期させる場合は必ず同じクロックベースを使いましょう。
#define F_CYCLE 15999               // Timer2のサイクル(1周期)

     // OC1機能をエッジ整列PWMモードで初期化
     OC1CON1 = 0b0000000000000110 ; // Timer2使用エッジ整列PWMモード
     OC1CON2 = 0b0000000000001100 ; // 16bit、同期イベントはTimer2
     OC1R    = F_CYCLE/2 ;          // デュティ比は50%で初期化
     // OC2機能をエッジ整列PWMモードで初期化
     OC2CON1 = 0b0000000000000110 ; // Timer2使用エッジ整列PWMモード
     OC2CON2 = 0b0001000000001100 ; // 16bit、同期イベントはTimer2、出力は反転
     OC2R    = F_CYCLE/2 ;          // デュティ比は50%で初期化
     // タイマー2の設定
     T2CON = 0b0000000000000000 ;   // プリスケーラカウント値 1:1、内部クロック(FCY)で使用、16ビット動作
     TMR2  = 0 ;                    // タイマー2のカウンターを初期化する
     PR2   = F_CYCLE ;              // 16000(0x3E80)=1ms(1000Hz)が1周期
     T2CONbits.TON = 1 ;            // タイマー2開始
OC1RとOC2Rにデュティ比を設定しますが、50%固定デュティ比なのでF_CYCLE/2としています。
尚、OC1(RB7)/OC2(RB8)の出力ピンには、このサンプルでは何も接続していません。

相補出力PWM波形


《センター整列PWMモード》

ここで使用するサンプルプログラムは、"PWM_Center.c"を使います。

出力コンペアのモードは、”センター整列PWMモード”でOC1とOC2から出力を行います。
又、OC2側出力にはデッドバンド出力を施してみました。
このモードではコンペアのクロックに、”タイマ2”を利用します。
タイマ2を使うので1周期の設定は PR2 で行います。
#define F_CYCLE 15999               // Timer2のサイクル(1周期)

     // OC1機能をセンター整列PWMモードで初期化
     OC1CON1 = 0b0000000000000111 ; // Timer2使用センター整列PWMモード
     OC1CON2 = 0b0000000000001100 ; // 16bit、同期イベントはTimer2
     OC1R    = 5000 ;               // TMR2=OC1Rで出力HIGH、50%のデュティ比
     OC1RS   = 13000 ;              // TMR2=OC1RSで出力LOW、50%のデュティ比
     // OC2機能をセンター整列PWMモードで初期化
     OC2CON1 = 0b0000000000000111 ; // Timer2使用センター整列PWMモード
     OC2CON2 = 0b0000000000001100 ; // 16bit、同期イベントはTimer2
     OC2R    = 5000  + 500 ;        // TMR2=OC2Rで出力HIGH、30us立ち上げを遅くしている
     OC2RS   = 13000 - 500 ;        // TMR2=OC2RSで出力LOW、30us立ち下げを早くしている
     // タイマー2の設定
     T2CON = 0b0000000000000000 ;   // プリスケーラカウント値 1:1、内部クロック(FCY)で使用、16ビット動作
     TMR2  = 0 ;                    // タイマー2のカウンターを初期化する
     PR2   = F_CYCLE ;              // 16000(0x3E80)=1ms(1000Hz)が1周期
     T2CONbits.TON = 1 ;            // タイマー2開始
センター整列PWMモードでは、1周期内のどこでパルスを作成するのかを決めます、
即ち、OCxRでパルスのHighする位置を指定し、OCxRSでパルスのLowする位置を決めます。
     0         15999 0
  |←―(PR2)―→|←―(PR2)―→|
      ┌――┐      ┌――┐
 ―――┘   └―――┘   └――――
       ↑  ↑      ↑  ↑
      OCxR  OCxRS   OCxR  OCxRS
      (5000) (13000)
とセットすれば50%のデュティ比が生成出来るでしょう。
でぇ、OC2にデッドバンドを作成する為に、
OC2R = 5000 + 500 ; と立ち上がりを遅くさせています。
さらに、
OC2RS = 13000 - 500 ; と立ち下げを早くしています。
"500"で30us程のデッドバンドが出来ます。
尚、OC1(RB7)/OC2(RB8)の出力ピンには、このサンプルでは何も接続していません。

センター整列PWM波形





【きむ茶工房ガレージハウス】
Copyright (C) 2006-2019 Shigehiro Kimura All Rights Reserved.