PWM + LPF(ローパスフィルタ) による
DA出力制御
(→プロジェクトファイル(Harmony Ver.2.04版 ) ダウンロード)
OC(Output Compare)モジュールのPWM制御とLPF(ローパスフィルタ)を使ったDA出力制御の例を紹介します。 目的によっては、
それほど高精度(低リップル、高応答性、直線性等)でない直流出力で足る場合があります。こういった場合は PWM+LFPは1つの
安価で有効な方法です。
<仕様>
・PIC32MZのOCモジュールのPWM制御とLPFを組み合わせて三角波(のこぎり波)の電圧出力を生成する。
・三角波の周期は1秒、振幅は0~3.3Vとする。
・PWMの周波数は、1KHzとする。
・フィルタは2次のCRフィルタとし、レール ツー レールのオペアンプをバッファアンプとする。
・PWM出力値は 割り込みタイマを用い10msec毎にデューティを変えて出力電圧を制御する。
・OC制御
Harmonyは、OCモジュールのスタティックライブラりを用いる。
割り込みタイマ(タイマ1) 及び PWM用タイマ(タイマ2)はダイナミックライブラリを用いる。
<回路図> (→ PDFファイル)
<外観>PIC32MZ評価ボード(→購入方法)を使った実験品の外観です。
<動作結果> (→ 動画:1080pのHD動画を見ることができます。)
オペアンプ AD8532の出力電圧 (1v/div、500msec/div) |
![]() |
PWM出力電圧(RD9 68ピン 出力電圧) (1V/div、200μsec/div) |
|||
Duty = 4 % | Duty = 20 % | Duty = 60 % | Duty = 99 % |
![]() |
![]() |
![]() |
![]() |
<解説> 記載してある内容は要点だけです。 詳細はプロジェクトファイルを精読願います
(以下は、Harmony v2.04 をもとに作成しています。最新のバージョンとは異なる点があるかもしれませんので注意してください。)
■ MHC設定
■ Ootions
■ Pin Settings
項目 | ④ポート設定 |
MHC | ![]() |
備考 | デフォルトからの変更要領: RD9/Functions: OC5 |
■ app.cに、青字部分を追加します。 system_interrupt.cへの追記はありません。
① ここでOC_ID_5をコンパイルするには、peripheral/oc/plib_oc.hをインクルードする必要があるようです。
変数の宣言、定義を行います。
#include "peripheral/oc/plib_oc.h" //要追加 OC_ID_5のコンパイル
DRV_HANDLE myHandle;
bool Timer_Trigger;
……
……
② インターバルタイマのコールバック関数が呼ばれたらフラグをたてます。
void tmrISR(uintptr_t context, uint32_t alarmCount ) //タイマ1コールバック関数
{
Timer_Trigger = 1;
};
③ APP_Initialize ( )の中で、OC(PWM)の周期、デューティなどの設定を行った後、OCをイネーブルにします。
//PWM周期 Fpwm = 1000Hz = 1 KHz //分解脳 1/100000000/16 / 1/1000 = 16/100000
= 0.00016 = 0.016%
//PR(PRレジスタ値) = Fpbclk3(ペリフェラルバスクロック周波数)/Fpwm(PWM周波数)/タイマプリスケール値 -
1;
myPR = (int)(100000000/Fpwm/PS_T2 -1); //=100000000/1000/16 -1 // Fpbclk3
= 100 MHz
PLIB_TMR_Period16BitSet(TMR_ID_2, myPR); //PWMの周期を設定 //Set period
……
……
④ ダイナミックインターバルタイマの定数、コールバック関数名などを設定します。
myHandle = DRV_TMR_Open ( DRV_TMR_INDEX_0, DRV_IO_INTENT_EXCLUSIVE
);
//タイマ1ハンドル取得
uint32_t divider = 3907; //周期レジスタ初期値 //最初の割り込みまでの時間をセット
//5 nsec x2 x 3907 x 256 = 10.00192msec = 10 msec at Fblclk3( = 10MHz)
DRV_TMR_AlarmRegister ( myHandle, divider, true, 0, tmrISR );
⑤ APP_Tasks ( )のcase APP_STATE_SERVICE_TASKS:の中で コールバック関数にフラグが立った場合
インクリメントして、PWMのデューティの計算、設定を行います。
if(Timer_Trigger == 1)
{
Timer_Trigger = 0;
ix++;
……
……
以下、app.c