8bitPICシリーズ①PRGモジュールの使い方

PIC16F1シリーズ

概要

PIC16F1シリーズの一部のマイコンにはPRGモジュールが搭載されています。
今回は「PIC16F1769」のPRGモジュールを使用して高速PWMを出力します。

PIC16F1769には16BitPWMが搭載されていますが、最高PWMクロックは32MHzなので、分解能は31.25nsecになります。そのためPWMモジュールで約3MHzのPWMを出力する時、周期レジスタが10となり、Dutyは10%程度の分解能しかありません。

今回はこのPRGモジュールを用いて高速なPWMでも分解能を1%程度まで向上させます。

PRGとは

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

更新履歴

更公開/変更日更新内容
2022/7/17初版公開
2025/4/13リンク追加、カテゴリ変更

関連リンク

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

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

PRGモジュールのブロックは以下のようになっており、充電開始のトリガ、放電開始のトリガ、定電流設定、リファレンス設定が主な機能です。

PRGモジュール (DS40001775E-page 357より抜粋)

高速PWMの原理を説明します。
PRGのランプ変化速度は最高速の2.5V/usecと設定します。PRGの中心電圧を2.5Vにセットして5Vになった時放電開始、0Vになった時に充電開始とした場合、周期が4usec、周波数は250kHzとなります。
つまり放電開始電圧(DAC4)を2.71V、充電開始電圧(DAC3)を2.29Vにすると周波数は約3MHzになります。

PRGを使用した高速PWM

内部回路は以下のように構成します。
Cmp1の負入力はRAMP出力、正入力はDAC3出力
Cmp2の負入力はRAMP出力、正入力はDAC4出力
Cmp3の負入力はRAMP出力、正入力はDAC1出力
RAMPの充電トリガはCmp1の上昇エッジ、放電トリガはCmp2の下降エッジ
Opampの正入力はRAMP出力、負入力はユニティゲイン

高速PWM生成用内部ブロック

実際にはDAC3、4は5bitのため、1LSBは約161mV([REF+] – [REF-] = 5Vの場合)となります。
周波数を3MHz近くに設定する場合、DAC4は設定値17で2.74V、DAC3は設定値14で2.26Vとなり差分は0.48Vです。

対してDAC1は10bitであるため、1LSBは約0.0049mV([REF+] – [REF-] = 5Vの場合)です。
つまりDAC4とDAC3の間を0.48 / 0.0049で分割できるため、16BitPWMモジュールに比べ1/10の約1%の分解能で制御可能です。

ソースコード

ソースコードは以下の通りです。

#include "xc.h"

#pragma config FOSC = INTOSC
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = ON
#pragma config CP = OFF
#pragma config BOREN = ON
#pragma config CLKOUTEN = OFF
#pragma config IESO = ON 
#pragma config FCMEN = ON

// CONFIG2
#pragma config WRT = OFF    
#pragma config PPS1WAY = ON    
#pragma config ZCD = OFF    
#pragma config PLLEN = OFF    
#pragma config STVREN = ON    
#pragma config BORV = LO    
#pragma config LPBOR = OFF
#pragma config LVP = ONenabled

void main(void)
{
    /*------------------------------------------------------------------------------*/
    /* オシレータ設定 */
    /*------------------------------------------------------------------------------*/
        OSCCON = 0x38;
    /*------------------------------------------------------------------------------*/
    /* ピン設定 */
    /*------------------------------------------------------------------------------*/
        TRISCbits.TRISC2 = 1u;
        TRISBbits.TRISB4 = 0u;
        ANSELCbits.ANSC2 = 1u;
        RB4PPS = 0x1A;              //RB4->CMP3:C3OUT; 
           
    /*------------------------------------------------------------------------------*/
    /* コンパレータ設定 */
    /*------------------------------------------------------------------------------*/
        CM1NSELbits.NCH = 0x04u;    // CMP1負入力 = PRG1 Out                       
        CM1PSELbits.PCH = 0x0Cu;    // CMP1正入力 = DAC3 Out
        CM1CON0bits.ON = 1u;        // CMP1有効   
               
        CM2NSELbits.NCH = 0x04u;    // CMP2負入力 = PRG1 Out                
        CM2PSELbits.PCH = 0x0Du;    // CMP2正入力 = DAC4 Out
        CM2CON0bits.ON = 1u;        // CMP2有効                         
                       
        CM3NSELbits.NCH = 0x04;     // CMP3負入力 = PRG1 Out                          
        CM3PSELbits.PCH = 0x0A;     // CMP3正入力 = DAC1 Out
        CM3CON0bits.ON = 1u;        // CMP3有効          
    
    /*------------------------------------------------------------------------------*/
    /* DAC設定 */
    /*------------------------------------------------------------------------------*/
        DAC1REFH = 0x02u;           // DAC1電圧H
        DAC1REFL = 0x00u;           // DAC1電圧L
        DACLDbits.DAC1LD = 1u;      // DAC1電圧ロード
        DAC1CON0bits.EN = 1u;       // DAC1有効
        
        DAC2REFH = 0x02u;           // DAC2電圧H
        DAC2REFL = 0x00u;           // DAC2電圧L
        DACLDbits.DAC2LD = 1u;      // DAC2電圧ロード
        DAC2CON0bits.EN = 1u;       // DAC2有効
    
        DAC3REF = 0x02u;            // DAC3電圧     
        DAC3CON0bits.EN = 1u;       // DAC3有効

        DAC4REF = 0x1Du;            // DAC4電圧     
        DAC4CON0bits.EN = 1u;       // DAC4有効
        
    /*------------------------------------------------------------------------------*/
    /* OPAMP設定 */
    /*------------------------------------------------------------------------------*/
        OPA1PCHSbits.PCH = 0x08;    //PRG1 Out
        OPA1CONbits.UG = 1u;        //ユニティゲイン有効
        OPA1CONbits.EN = 1u;        //オペアンプ有効
    /*------------------------------------------------------------------------------*/
    /* PRG設定 */
    /*------------------------------------------------------------------------------*/
        PRG1CON1bits.RPOL = 0u;     // 下降イベントはアクティハイ
        PRG1CON1bits.FPOL = 1u;     // 上昇イベントはアクティブロー

        PRG1INSbits.INS = 0x04;     // REF電圧 = DAC2

        PRG1CON2bits.ISET = 0x1Fu;  // 電流充放電速度 2.5V/us
        PRG1CON2bits.LR = 0u;       // 高速充電

        PRG1CON0bits.FEDG = 1u;     // 上昇トリガはエッジモード
        PRG1CON0bits.REDG = 1u;     // 下降トリガはエッジモード
        PRG1CON0bits.MODE = 1u;     // 交互上昇・下降モード
        PRG1CON0bits.EN = 1u;       // RPG1 有効 (RTSS,FTSSより以前に有効化する必要)

        PRG1RTSSbits.RTSS = 0x00;   // sync_C1OUT
        PRG1FTSSbits.FTSS = 0x01;   // sync_C2OUT

        PRG1CON0bits.GO = 1;        // RPG1開始
    while (1)
    {

    }
}

結果

1 . PWM周波数を約275kHzに設定した場合

ISET = 0x1F(2.5V/us) , DAC3 = 0x02(30mV) , DAC4 = 0x1D(4.68V) / 充放電電流(1ch/黄色)、PWM出力

2. PWM周波数を約3.2MHzに設定した場合

ISET = 0x1F(2.5V/us) , DAC3 = 0x0F(2.34V) , DAC4 = 0x11(2.65V)

回路の電源はUSBパワーから取っていたので、[REF+] – [REF-]が5Vではなく約4.7Vまで降下していたので、理想の設定値とは若干ずれています。

コメント

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