8bitPICシリーズ②PWMモジュールの使い方

8BitPICシリーズ

概要

現在発売されている8bit~32BitPICの数多くのマイコンにPWMモジュールが搭載されています。
単純なPWMであればアウトプットコンペアモジュールでも出力が可能ですが、このPWMモジュールはより高度なPWM波形を生成するために使用されます。

PWMとは

PWMとはPulse Width Modulationの略で、周期は固定でデューティ比を変化させてパルス変調させて制御する。電源やモータ制御など様々なシーンで使用される。

PRGとは

PRGとは Programmable Ramp Generatorの略でランプ波形を生成できる機能
スイッチング電源のピーク電流モードなどで低調波発振を防止可能

更新履歴

更公開/変更日更新内容
2022.08.15初版公開
2023.02.13誤記修正
2025.04.13タイトル修正、リンク追加、カテゴリ変更

関連リンク

記事リンク
第1回8bitPICシリーズ①
PRGモジュールの使い方
8bitPICシリーズ①PRGモジュールの使い方 – ぴくおの電子工作的な何かWP
第2回8bitPICシリーズ②
PWMモジュールの使い方
8bitPICシリーズ②PWMモジュールの使い方 – ぴくおの電子工作的な何かWP
第3回8bitPICシリーズ③
SMTモジュールの使い方
8bitPICシリーズ③SMTモジュールの使い方 – ぴくおの電子工作的な何かWP
第4回8bitPICシリーズ④
Timerモジュールの使い方
8bitPICシリーズ④Timerモジュールの使い方 – ぴくおの電子工作的な何かWP
第5回8bitPICシリーズ⑤
Angular Timer モジュールの使い方
8bitPICシリーズ⑤Angular Timer モジュールの使い方 – ぴくおの電子工作的な何かWP
第6回8bitPICシリーズ⑥
CLB(Configurable Logic Block)モジュールの使い方
8bitPICシリーズ⑥CLB(Configurable Logic Block)モジュールの使い方 – ぴくおの電子工作的な何かWP
第7回
第8回
第9回
第10回
内部リンク

PICシリーズのPWMモジュール

各マイコンに搭載されるPWMモジュールのハードウェアの内部構成はシリーズによって異なり使用方法も大きく異なります。

1.PIC16(L)F176xシリーズなど

シンプルな構造。Dutyや周期は10Bit幅しか設定できない。
相補パルスやデッドタイムは後段に接続するCOGやCWGで生成。

(fig.1)DS40001775E-page 263 10BitPWMブロックダイアグラム

Bit幅が16Bitに拡張され位相やオフセットが設定。
相補パルスやデッドタイムは後段に接続するCOGやCWGで生成。

(fig.2)DS40001775E-page 269より抜粋 16Bit PWMブロックダイアグラム

2.PIC18FxxQ43シリーズなど

Bit幅は16Bit。単独のPWMモジュールで2出力のパルスが出力可能。
相補パルスやデッドタイムは後段に接続するCOGやCWGで生成。

(fig.3)DS40002147F-page 465より抜粋 16Bit PWMブロックダイアグラム

以下に8BitPICシリーズの新旧PWMモジュールの比較表を転載します

(fig.4a)DS40002136A-page 1より抜粋 旧16BitPWMと新16BitPWMの比較
(fig.4b)DS40002136A-page 2より抜粋 旧16BitPWMと新16BitPWMの比較

3.PIC33Cシリーズなど

非常に高性能な16Bitタイマ。分解能が250psecまで設定可能。電源制御やモーター制御アプリケーション向けにフォルトや外部PWM同期など機能は多数。

(fig.5a)DS70005320D-page 51より抜粋 PWMハイレベルブロックダイアグラム
(fig.5b)DS70005320D-page 52より抜粋 SinglePWMジェネレータブロックダイアグラム


今回は「PIC18F57Q43」のPWMモジュールを使用します。

ハードウェア構成と制御ブロック

PIC18FxxQ43シリーズの16BitPWMは下記のようにクロックソース、プリスケーラ、タイマー、周期レジスタ、P1,P2レジスタと出力モジュールによって構成されています。
また出力モードは大きく以下の5モードに分かれます。

  • Left Aligned Mode(左詰め)
  • Right Aligned Mode(右詰め)
  • Center Aligned Mode(中央詰め)
  • Variable Alignment Mode(可変詰め)
  • Compare Modes(比較モード)

1.Left Aligned Mode

周期の開始からPWMはアクティブ(High)になりP1、P2パラメータで指定された期間継続します。その後インアクティブ(Low)になります。

(fig.6a)DS40002147F-page 465より抜粋 Left Aligned Modeブロックダイアグラム
(fig.6b)DS40002147F-page 465より抜粋 Left Aligned Modeタイミングチャート

2.Right Aligned Mode

周期の開始からPWMはインアクティブ(Low)になり周期値 – P1、P2パラメータで指定された期間継続します。その後アクティブ(High)になります。

(fig.7a)DS40002147F-page 466より抜粋 Right Aligned Modeブロックダイアグラム
(fig.7b)DS40002147F-page 466より抜粋 Right Aligned Modeタイミングチャート

3.Center Aligned Mode

周期の開始からPWMはインアクティブ(Low)になり周期値 – P1、P2パラメータで指定された期間継続します。その後アクティブ(High)になります。また次の周期では周期の開始からPWMはアクティブ(High)になりP1、P2パラメータで指定された期間継続します。その後インアクティブ(Low)になります。つまり他のモードに比べ2倍の周期になります

(fig.8a)DS40002147F-page 467より抜粋 Center Aligned Modeブロックダイアグラム
(fig.8b)DS40002147F-page 467より抜粋 Center Aligned Modeタイミングチャート

4.Variable Alignment Mode

タイマーとP1の値が一致した時にPWMはアクティブ(High)になり、タイマーとP2の値が一致した時にPWMはインアクティブ(Low)になります。P1出力とP2出力は同一パルスとなります。

(fig.9a)DS40002147F-page 468より抜粋 Variable Alignment Modeブロックダイアグラム
(fig.9b)DS40002147F-page 468より抜粋 Variable Alignment Modeタイミングチャート

5.Compare Modes

コンペアモードは更に2つのモードに分かれます

1.パルスコンペアモード

タイマーとP1の値が一致した時に1クロック分のパルスがP1から出力され、タイマーとP2の値が一致した時に1クロック分のパルスがP2から出力されます。

(fig.10a)DS40002147F-page 469より抜粋 パルスコンペアモードブロックダイアグラム
(fig.10b)DS40002147F-page 469より抜粋 パルスコンペアモードタイミングチャート

2.トグルコンペアモード

タイマーとP1の値が一致した時にP1出力が反転し、タイマーとP2の値が一致した時にP2出力が反転します。

(fig.11a)DS40002147F-page 470より抜粋 トグルコンペアモードブロックダイアグラム
(fig.11b)DS40002147F-page 470より抜粋 トグルコンペアモードタイミングチャート

ハードウェア構成

今回はPWM1を右詰めモードで動作させ、その生出力と出力にデッドバンド(デッドタイム)を付加させた信号を観察します。

(fig.12)今回のソースコードのブロックダイアグラム

ソースコード

ソースコードは以下の通りです。
特筆すべき点はありませんが、CWGのデッドバンドを設定した後にレジスタに反映するためはCWG1CON0bits.LDをセットしてロードすることが必要です。

#include "xc.h"

#pragma config FEXTOSC = ECH
#pragma config RSTOSC = EXTOSC 

//CONFIG2
#pragma config CLKOUTEN = OFF
#pragma config FCMEN = ON
#pragma config CSWEN = ON
#pragma config PR1WAY = ON 

//CONFIG3
#pragma config MVECEN = OFF 
#pragma config MCLRE = EXTMCLR
#pragma config BOREN = SBORDIS 
#pragma config PWRTS = PWRT_OFF 
#pragma config IVT1WAY = ON    
#pragma config LPBOREN = OFF    

//CONFIG4
#pragma config XINST = OFF  
#pragma config LVP = ON    
#pragma config ZCD = OFF    
#pragma config STVREN = ON    
#pragma config BORV = VBOR_1P9  
#pragma config PPS1WAY = ON     

//CONFIG5
#pragma config WDTCPS = WDTCPS_31   
#pragma config WDTE = OFF  

//CONFIG6
#pragma config WDTCWS = WDTCWS_7 
#pragma config WDTCCS = SC 

//CONFIG7
#pragma config SAFEN = OFF    
#pragma config BBEN = OFF     
#pragma config BBSIZE = BBSIZE_512     
#pragma config DEBUG = OFF     

//CONFIG8
#pragma config WRTB = OFF     
#pragma config WRTC = OFF     
#pragma config WRTD = OFF     
#pragma config WRTAPP = OFF    
#pragma config WRTSAF = OFF     

//CONFIG10
#pragma config CP = OFF     


int main(void)
{
    /*--------------------------------------------------------------------------------*/
    /* オシレータ設定 */
    /*--------------------------------------------------------------------------------*/
        OSCCON1 = 0x60;
        OSCCON3 = 0x0;
        OSCEN = 0x0;
        OSCFRQ = 0x8;
        OSCTUNE = 0x0;
        ACTCON = 0x0;
    /*--------------------------------------------------------------------------------*/
    /* ピン設定*/
    /*--------------------------------------------------------------------------------*/
        TRISD = 0xFC;
        TRISF = 0x3C;

        RD0PPS = 0x0B;      //RD0->CWG1:CWG1C;
        RD1PPS = 0x0C;      //RD1->CWG1:CWG1D;
        RF0PPS = 0x18;      //RF0->PWM1_16BIT:PWM11;
        RF1PPS = 0x19;      //RF1->PWM1_16BIT:PWM12;
    /*--------------------------------------------------------------------------------*/
    /* CWG設定*/
    /*--------------------------------------------------------------------------------*/
        CWG1CON0 = 0x84;    //CWG1 ON & ハーフブリッジモード
        CWG1CLKCON = 0x0;
        CWG1CON1 = 0x0;
        CWG1DBR = 0x23;     //立ち上がりデッドバンド
        CWG1DBF = 0x23;     //立ち下がりデッドバンド
        CWG1AS0 = 0x14;
        CWG1AS1 = 0x0;
        CWG1STR = 0x0;
        CWG1ISM = 0x4;          //CWGInput = PWM11

        CWG1CON0bits.LD = 1;    //デッドバンドロード(重要)
    /*--------------------------------------------------------------------------------*/
    /* PWM設定 */
    /*--------------------------------------------------------------------------------*/
        PWM1ERS = 0x0;
        PWM1CLK = 0x2;      //CLOCK = FOC
        PWM1LDS = 0x0;
        PWM1PRL = 0x7F;     //周期下位8Bit
        PWM1PRH = 0x2;      //周期上位8Bit
        PWM1CPRE = 0x0;
        PWM1PIPOS = 0x0;
        PWM1GIR = 0x0;
        PWM1GIE = 0x0;
        PWM1S1CFG = 0x1;
        PWM1S1P1L = 0x40;   //P1下位8Bit
        PWM1S1P1H = 0x1;    //P1上位8Bit
        PWM1S1P2L = 0x20;   //P2下位8Bit
        PWM1S1P2H = 0x0;    //P2上位8Bit

        PIR4bits.PWM1PIF = 0;
        PIR4bits.PWM1IF = 0;
        PWM1GIRbits.S1P1IF = 0;
        PWM1GIRbits.S1P2IF = 0;
        PIE4bits.PWM1IE = 0;
        PIE4bits.PWM1PIE = 0;
        PWM1CON = 0x80;
    
    while(1)
    {

    }    
}

結果

以下のようにP1、P2の生出力とP1にデッドバンドをつけた相補PWMが出力されています。

(fig.13)Ch1 =P1出力 , Ch2 = P2出力 , Ch3 = CWG1C出力 , Ch4 = CWG1D出力

コメント

タイトルとURLをコピーしました