<V.3版>
PWM + LPF(ローパスフィルタ) による
DA出力制御
(→プロジェクトファイル(Harmony Ver.3 版 MHC v3.6.0) ダウンロード)
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 % |
![]() |
![]() |
![]() |
![]() |
<解説> 記載してある内容は要点だけです。 詳細はプロジェクトファイルを精読願います
■ ステップ1: MHC作成
■ app.cに、青字部分を追加します。 system_interrupt.cへの追記はありません。
① 命令にレジスタ名を直接記載する場合必須となります。
#include "definitions.h" //レジスタ直接制御で必須
② 変数の宣言、定義を行います。
bool Timer_Trigger;
//bool LED;
float Duty = 0; //PWMのディューティ
int myPR; //PWM周期のレジスタ値( = PR2 at Timer2)
……
……
③ インターバルタイマのコールバック関数が呼ばれたらフラグをたてます。
void TMR1_Callback_Fn(uint32_t status, uintptr_t context) //タイマ1のコールバック関数
//10msec毎に呼び出される
{
Timer_Trigger = 1;
……
……
}
③ APP_Initialize ( )の中で、OC5(PWM)の周期設定を行った後、タイマ2、OCをイネーブルにします。
タイマ2のPR2レジスタ設定値が周期になります。 Fpbclk3(ペリフェラルバスクロック3周波数)100MHzのカウント数が
PR2レジスタ値になる時間がPWMの周期です。
……
……
//PWM周期 Fpwm = 1000Hz = 1 KHz //分解脳 1/100000000/16 / 1/1000 = 16/100000
= 0.00016 = 0.016%
//PR(PRレジスタ値) = Fpbclk3(ペリフェラルバスクロック3周波数)/Fpwm(PWM周波数)/タイマプリスケール値 -
1;
myPR = (int)(100000000/Fpwm/PS_T2 -1); //=100000000/1000/16 -1 // Fpbclk3
= 100 MHz
TMR2_PeriodSet(myPR); //周期レジスタ設定
//PR2 = myPR;
TMR2_Start(); //タイマ2スタート
//T2CONbits.ON = 1;
OCMP5_Enable (); //OC5イネーブル
//OC5CONbits.ON = 1;
……
……
④ APP_Tasks ( )で 最初の1回目だけ呼ばれる部分で
インターバルタイマのタイマ1の設定値記述 及びTMR1_CallbackRegister( )を使ったコールバック関数の設定などを行います。
最後にタイマを起動します。
……
……
if (appInitialized)
{
TMR1_PeriodSet(3907); //5nsec x2 x 3907 x 256 = 100001920nsec = 10.000192msec
= 10msec
//PR1 = 3907; //レジスタ直接
TMR1_CallbackRegister(TMR1_Callback_Fn, NULL); //コールバック関数設定
//void TMR1_CallbackRegister(TMR_CALLBACK callback_fn, uintptr_t
context);
TMR1_Start(); //タイマ1スタート
//T1CONbits.ON = 1;
……
……
}
⑤ APP_Tasks ( )のcase APP_STATE_SERVICE_TASKS:の中で コールバック関数にフラグが立った場合
インクリメントして、PWMのデューティの計算、設定を行います。
最後にデューティに対応する値をレジスタに書き込みます。
……
……
if(Timer_Trigger == 1)
{
Timer_Trigger = 0;
ix++;
if(ix == 100)ix = 0;
Duty = (float)ix/100; //float:
myDuty = (int)((float)PR2 * Duty);
OCMP5_CompareSecondaryValueSet(myDuty); //OC5のデューティ設定
// OC5RS = myDuty;
}
……
……
以下、app.c 全文