概要
今回は高速PWMについて紹介します。
dsPIC33AKシリーズのPWMモジュールは、dsPIC33Cシリーズと比較して、PWMの分解能やタイムベースの幅が拡張されています(詳細は下表をご参照ください)。
さらに、レジスタの32bit化により、いくつかのレジスタが統合されていますが、機能自体には大きな変更は見られません。
(2nd Generation のPWMモジュールについては現時点(24/9/17)で不明です)
| dsPIC33C (MCシリーズ) | dsPIC33C (K,Hシリーズ) | dsPIC33AK (MCシリーズ) | dsPIC33AK (2nd Generation) | |
| 高分解能PWM(ペア) | 4 | 8 | 4 | 8 |
| PWM分解能(ps) | 2000 | 250 | 1250 | 78 |
| PWMタイムベース | 16bit | 16bit | 20bit | 20bit |
| コンビネーショントリガ | 4pair | 4pair | 6pair | 8pair |
関連記事
| 関連記事 | リンク |
| 高分解能PWMモジュールの使い方1 | 高分解能PWMモジュールの使い方1 – ぴくおの電子工作的な何かWP (electricpico.com) |
| 高分解能PWMモジュールの使い方2 | 高分解能PWMモジュールの使い方2 – ぴくおの電子工作的な何かWP (electricpico.com) |
| 高分解能PWMモジュールの使い方3 (コンビネーションロジック) | 高分解能PWMモジュールの使い方3(コンビネーションロジック) – ぴくおの電子工作的な何かWP (electricpico.com) |
| 高分解能PWMモジュールの使い方4 (スロープ補償) | 高分解能PWMモジュールの使い方4(スロープ補償) – ぴくおの電子工作的な何かWP (electricpico.com) |
| 高分解能PWMモジュールの使い方5 (PCI機能) | 高分解能PWMモジュールの使い方5(PCI機能) – ぴくおの電子工作的な何かWP (electricpico.com) |
開発環境
開発環境を以下に示します。
今回はCPUボード(EV02G02A)で動作確認を行います。
| 項目 | 値 | リンク |
| ベースボード | dsPIC33A CURIOSITY PLATFORM DEVELOPMENT BOARD | dsPIC33A Curiosity Platform Development Board User’s Guide (microchip.com) |
| CPUボード(EV68M17A) | EV68M17A – dsPIC33AK128MC106 Motor Control DIM | dsPIC33AK128MC106 Motor Control Dual In-Line Module (DIM) Information Sheet (microchip.com) |
| CPUボード(EV02G02A) | dsPIC33AK128MC106 General Purpose Dual In-Line Module (DIM) | dsPIC33AK128MC106 General Purpose Dual In-Line Module (DIM) | Microchip Technology |
| 統合開発環境 | MPLAB X IDE v6.20 | MPLAB® X IDE | Microchip Technology |
| コンパイラ | MPLAB XC DSC v3.10 | MPLAB® XC DSC Compiler | Microchip Technology |

PWMモジュールについて
ブロック図
下記にPWMモジュールのブロック図を示します。


レジスタ
以下にPWMレジスタとその説明を示します。
| レジスタ名(x=1~4,y=A~F) | 機能 | 説明 | 従来からの変更点 |
| PCLKCON | クロック制御レジスタ | PWMクロックを制御 | |
| FSCL | 周波数スケール周期レジスタ | 周波数スケールモードでの周期設定 | 20bitに拡張(ただし実質16bit) |
| FSMINPER | 周波数スケール最小周期レジスタ | 周波数スケールモードでの最小周期設定 | 20bitに拡張(ただし実質16bit) |
| MPHASE | マスターフェーズレジスタ | マスターフェーズを設定 | 20bitに拡張 |
| MDC | マスターデューティレジスタ | マスターDutyを設定 | 20bitに拡張 |
| MPER | マスター周期レジスタ | マスター周期を設定 | 20bitに拡張 |
| LFSR | リニアフィードバックシフトレジスタ | 疑似ランダム値 | |
| CMBTRIG | コンビネーショントリガレジスタ | コンビネーショントリガの設定 | レジスタ統合, |
| LOGCONy | ロジックコントロールレジスタ | 組み合わせロジックの制御 | |
| PWMEVTy | PWMイベントレジスタ | PWMイベントの制御 | |
| PGxCON | 制御レジスタ | PGxモジュールの全体制御 | レジスタ統合,TRGMODビットの拡張 |
| PGxSTAT | ステータスレジスタ | PGxモジュールのステータス | |
| PGxIOCON | IO制御レジスタ | I/Oピンの設定 | レジスタ統合,PPSENビット追加 |
| PGxEVT | イベントレジスタ | イベント発生用の設定 | レジスタ統合,PWMPCIの統合 |
| PGxFPCI | フォルトPCIレジスタ | フォルト時の動作を設定 | レジスタ統合,TERMPSビット追加 |
| PGxCLPCI | 電流PCIレジスタ | カレントリミット時の動作を設定 | レジスタ統合,TERMPSビット追加 |
| PGxFFPCI | FFPCIレジスタ | F/F時の動作を設定 | レジスタ統合,TERMPSビット追加 |
| PGxSPCI | 同期PCIレジスタ | 同期時の動作を設定 | レジスタ統合,TERMPSビット追加 |
| PGxLEB | ブランキングレジスタ | リーディングエッジブランキング時間を設定 | レジスタ統合 |
| PGxPHASE | フェーズレジスタ | フェーズを設定 | 20bitに拡張 |
| PGxDC | Dutyレジスタ | Dutyを設定 | 20bitに拡張 |
| PGxDCA | Duty調整レジスタ | Duty調整値を設定 | 12bitに拡張 |
| PGxPER | 周期レジスタ | 周期を設定 | 20bitに拡張 |
| PGxTRIGA | トリガレジスタA | トリガを設定 | 20bitに拡張, CAHALFビットの統合 |
| PGxTRIGB | トリガレジスタB | トリガを設定 | 20bitに拡張, CAHALFビットの統合 |
| PGxTRIGC | トリガレジスタC | トリガを設定 | 20bitに拡張, CAHALFビットの統合 |
| PGxDT | デッドタイムレジスタ | デッドタイムを設定 | 15bitに拡張,レジスタ統合 |
| PGxCAP | キャプチャレジスタ | イベント発生時のタイムベースキャプチャ | 20bitに拡張 |
動作確認
今回はフェーズシフト波形を出力します。
フェーズシフト波形については以前の記事を参考にしてください
下記の通りLED0~LED3に接続されているピンをPWMモジュールに割り当てます。
LED0,LED1はPG3のデフォルト出力ピンですが、LED3はPG4のデフォルト出力ピンではないため、PG4はリマッパブルピン経由で出力します。
構成

ソースコード
コンフィグレーションファイル、クロック設定ファイルは以下のファイルをインクルードしてください。
■コンフィグレーションファイル (config.h)
■クロック設定ソースファイル(Clock_Driver.c)
■クロックヘッダーファイル(clock_driver.c)
■ソースコード全体
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "config.h"
#include "clock_driver.h"
#include <dsp.h>
/*----------------------------------------------------------------------------*/
/**
* @fn main(int argc, char** argv)
* @brief PROJECT_3_2_1_PWM
* @param[in] argc argument count
* @param[in] argv argument vector
* @retval EXIT_SUCCESS 成功
* @retval EXIT_FAILURE 失敗
* @detail PWM
* @note
*/
/*----------------------------------------------------------------------------*/
int main(int argc, char** argv)
{
/*-----------------------------------------------------------------------*/
/*初期化*/
/*-----------------------------------------------------------------------*/
vdg_Clock_Set_Register();
//RPOR9bits.RP37R = 6u; //PWM3L
//RPOR8bits.RP36R = 5u; //PWM3H
RPOR9bits.RP38R = 8u; //PWM4L
RPOR9bits.RP39R = 7u; //PWM4H
/*-----------------------------------------------------------------------*/
/* PWM設定*/
/*-----------------------------------------------------------------------*/
PCLKCONbits.MCLKSEL = 0u;
PCLKCONbits.DIVSEL = 0u;
MPER = 1000;
MDC = MPER / 2;
PG3PHASE = 0u;
PG3CONbits.MODSEL = 1u; //可変フェーズ
PG3CONbits.CLKSEL = 1u; //MCLKSEL
PG3CONbits.TRGCNT = 0u;
PG3CObits.SOCS = 0u;
PG3CONbits.TRGMOD = 0u;
PG3CONbits.UPDMOD = 0u;
PG3CONbits.MSTEN = 0u;
PG3CONbits.MPHSEL = 0u;
PG3CONbits.MPERSEL = 1u; //MPER
PG3CONbits.MDCSEL = 1u; //MDC
PG3IOCONbits.DBDAT = 0u;
PG3IOCONbits.FFDAT = 0u;
PG3IOCONbits.CLDAT = 0u;
PG3IOCONbits.FLTDAT = 0u;
PG3IOCONbits.OSYNC = 0u;
PG3IOCONbits.OVRDAT = 0u;
PG3IOCONbits.OVRENL = 0u;
PG3IOCONbits.OVRENH = 0u;
PG3IOCONbits.SWAP = 0u;
PG3IOCONbits.CLMOD = 0u;
PG3IOCONbits.POLL = 0u;
PG3IOCONbits.POLH = 0u;
PG3IOCONbits.PENL = 1u; //PWMxL Output
PG3IOCONbits.PENH = 1u; //PWMxH Output
PG3IOCONbits.PMOD = 0u;
PG3IOCONbits.DTCMPSEL = 0u;
PG3IOCONbits.PPSEN = 0u;
PG3IOCONbits.CAPSRC = 0u;
PG4PHASE = 0;
PG4CONbits.MODSEL = 1u; //可変フェーズ
PG4CONbits.CLKSEL = 1u; //MCLKSEL
PG4CONbits.TRGCNT = 0u;
PG4CONbits.SOCS = 0u;
PG4CONbits.TRGMOD = 0u;
PG4CONbits.UPDMOD = 0u;
PG4CONbits.MSTEN = 0u;
PG4CONbits.MPHSEL = 0u;
PG4CONbits.MPERSEL = 1u; //MPER
PG4CONbits.MDCSEL = 1u; //MDC
PG4IOCONbits.DBDAT = 0u;
PG4IOCONbits.FFDAT = 0u;
PG4IOCONbits.CLDAT = 0u;
PG4IOCONbits.FLTDAT = 0u;
PG4IOCONbits.OSYNC = 0u;
PG4IOCONbits.OVRDAT = 0u;
PG4IOCONbits.OVRENL = 0u;
PG4IOCONbits.OVRENH = 0u;
PG4IOCONbits.SWAP = 0u;
PG4IOCONbits.CLMOD = 0u;
PG4IOCONbits.POLL = 0u;
PG4IOCONbits.POLH = 0u;
PG4IOCONbits.PENL = 1u; //PWMxL Output
PG4IOCONbits.PENH = 1u; //PWMxH Output
PG4IOCONbits.PMOD = 0u;
PG4IOCONbits.DTCMPSEL = 0u;
PG4IOCONbits.PPSEN = 1u;//PPS
PG4IOCONbits.CAPSRC = 0u;
PG3CONbits.ON = 1u;
PG4CONbits.ON = 1u;
while (1)
{
;
}
return EXIT_SUCCESS;
}
結果
以下の通りフェーズシフト波形が出力されました。

注意点としてPGモジュール間で同期をとっていない場合は、以下の通りモジュールを有効化した順番や時間差で位相が発生する事です。周波数が高い場合は影響が大きいので注意が必要です。
ONビット個別有効化
各種PGx設定後、PGxCONbits.ON を1に設定
→70nsec程度の遅延
// PG3各種設定
...
PG3CONbits.ON = 1u;
// PG4各種設定
...
PG3CONbits.ON = 1u;

ONビットほぼ同時設定
各種設定後、最後にPGxCONbits.ON を1に設定
→35nsec程度の遅延
// 各種設定
...
PG3CONbits.ON = 1u;
PG4CONbits.ON = 1u;

レジスタ一括設定
ビットアクセスは遅いため、各種パラメータ設定後、最後にPGxCONレジスタを設定
→10nsec程度の遅延
// 各種設定(PGxCON以外)
...
PG3CON = 0xC0008009;
PG4CON = 0xC0008009;

記事についての注意点
本記事は慎重に内容を検討し正確さに努めておりますが、内容に誤りがあったとしても、この記事を参考にして生じた損害等については一切の責任を負いません。

コメント