概要
PIC16F1シリーズの一部のマイコンにはPRGモジュールが搭載されています。
今回は「PIC16F1769」のPRGモジュールを使用して高速PWMを出力します。
PIC16F1769には16BitPWMが搭載されていますが、最高PWMクロックは32MHzなので、分解能は31.25nsecになります。そのためPWMモジュールで約3MHzのPWMを出力する時、周期レジスタが10となり、Dutyは10%程度の分解能しかありません。
今回はこのPRGモジュールを用いて高速なPWMでも分解能を1%程度まで向上させます。
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モジュールのブロックは以下のようになっており、充電開始のトリガ、放電開始のトリガ、定電流設定、リファレンス設定が主な機能です。

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

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

実際には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に設定した場合

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

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


コメント