PIC24FJ64GB002でPWMを使うための覚え書き

自分用です.この内容には自信がないので,もし参考にする人がいたら最初にデータシートを読むことをおすすめします.
 
1.目的
LEDドライバのTLC5940をPICで制御しようと思ったら,クロックを入れる必要があるらしい.
なのでPWMをクロックにしたい.

2.簡単な流れ
2.1.(タイマを使う場合は)タイマの周期を設定する.
2.2.PWMのピンの割当を行う
2.3.PWMの周期とデューティを決める
2.4.クロックのソースを決める
2.5.(タイマを使う場合は)タイマ スタート!
 
3.データシートに沿った詳細な流れと設定方法
[参考]14.3 Pulse-Width Modulation (PWM) Mode
 
3.1.OCx をRPxピンに割り当てる.
例えばRP14(PICの25番ピン)にOC1を割り当てる場合,ピンを出力に設定して,デジタル設定にして,OC1を割り当てる必要がある.
なお,3行目の18はRP14に割り当てる機能を表す(今回の場合はOC1).機能一覧はTABLE 10-3: SELECTABLE OUTPUT SOURCES (MAPS FUNCTION TO OUTPUT)を参照.

TRISBbits.TRISB14=0;   //RP14を出力に
AD1PCFG=0xffff;        //全部のピンをデジタルに
RPOR7bits.RP14R = 18;  //RP14にOC1を割り当てる

 
3.2.デューティ(仕様書ではon-time)を計算し,OCxR に入れる.
最初にPWM周期とデューティ比を決める必要がある.
例えば(内蔵オシレータ8[MHz]をプリスケーラで分周した)32[MHz]をシステムクロックとし,PWM周波数が100[kHz]でデューティ比が50[%]の場合,EQUATION 14-1: CALCULATING THE PWM PERIODより,
PWM周期=[Value+1]*T_CY* (Prescaler Value)
1/100[kHz]=[Value+1]*(2*T_OSC)* (Prescaler Value)
10*10^(-6)=[Value+1]*(2*(1/32[MHz]))* (Prescaler Value)
10*10^(-6)=[Value+1]*(2*(31.25*10^(-9)))* (Prescaler Value)
10*10^(-6)=[Value+1]*(62.5*10^(-9))* (Prescaler Value)
[Value+1]=10*10^(-6)   /  (62.5*10^(-9))* (Prescaler Value)
[Value+1]=160*(1/Prescaler Value)
となる(はず).ここで,ValueはOCxRS やPR2に入れる値となる(?).
また,Prescaler Valueはタイマのプリスケーラで,周期を長くするために使う.システムクロックを使う場合は1固定.
Valueの値が極端な値ではないため,プリスケーラは1で良さそう.なのでValueは159となる.
Valueが求まり,デューティ比を50[%]と決めているので,OCxRに設定するべきデューティを求める事ができる.
OCxR =(Value+1)*50[%]
=80
よって,OCxRS とPR2には159,OCxRには80を入れれば良いことが分かる.

PR2 = 159;
OC1RS = 159;
OC1R = 80;

 
3.3.PWM周期を計算し,OCxRSに入れる.
3.2.を参照.
 
3.4.同期ソースの設定
仕様書通りに,SYNCSELに0x1F,OCTRIGに0を入れる.

OC1CON2bits.SYNCSEL=0x1f;
OC1CON2bits.OCTRIG=0;

 
3.5.クロックソースの選択
クロックソースをシステムクロックとするか,タイマにするかなどを決める.
システムクロックにする場合はOCTSELに0b111を入れ,timer2にする場合は0b000を入れる.
システムクロックでは以下のようになる.

OC1CON1bits.OCTSEL=0b111;

 
3.6.必要なら割込み許可する
今回は必要ないので割愛
 
3.7.PWMモードを決める.
Edge-AlignedとCenter-Alignedがあるけど,これはPWM信号の生成開始地点を決めるっぽい
こちらを参照.
今回はEdge-AlignedにするのでOCMに0b110を設定

OC1CON1bits.OCM=0b110;

 
3.8.タイマ使うならタイマ起動
TONを1に設定する.
timer2をオンにするなら以下のようになる.

T2CONbits.TON 1;

 
4.まとめ
上記の設定をすべてまとめると以下のようなコードとなる.
なお,PWMのクロックソースのにはシステムクロックを使い,システムクロックは32[MHz],PWM周波数は100[kHz],デューティ比は50[%]とする.

int main(void)
{
	CLKDIVbits.RCDIV = 0b000; //クロックの設定
	TRISBbits.TRISB14=0; //RP14を出力に
	AD1PCFG=0xffff; //全部のピンをデジタルに
	RPOR7bits.RP14R = 18; //RP14にOC1を割り当てる
	OC1RS = 159;  //計算は省略
	OC1R = 80;  //計算は省略
	OC1CON2bits.SYNCSEL=0x1f;  //仕様書から
	OC1CON2bits.OCTRIG=0;  //仕様書から
	OC1CON1bits.OCTSEL=0b111;   //クロックソースはシステムクロック
	OC1CON1bits.OCM=0b110;  //Edge-Alignedを使う
	while(1); //動作終了
}

 
 

結果はこうなる.fに100kHzと書かれているし多分正しい.
 
5.タイマを使う場合の変更点
タイマの設定を行う.
PWMのクロックソースを変更する.
タイマーON!
以上の3つをコードにすると以下のようになる.

T2CON = 0x0000;
T2CONbits.TCKPS=0b11;
OC1CON1bits.OCTSEL=0b000;
T2CONbits.TON = 1;