PIC18シリーズのマイコンで、PWM出力を利用してLEDをふんわり点滅させてみます。
今回はCCP機能に含まれるPWM出力を使用して明るさの制御を行います。
この為、LEDはPWM出力ピンであるCPP1のピンに接続します。
#include "p18f4620.h" #include "timers.h" #include "delays.h" #include "pwm.h" // Configuration bitの指定 #pragma config OSC = HS // HS oscillator #pragma config FCMEN = OFF // Fail-Safe Clock Monitor disabled #pragma config IESO = OFF // Oscillator Switchover mode disabled #pragma config PWRT = ON // PWRT enabled #pragma config BOREN = OFF // Brown-out Reset disabled in hardware and software #pragma config WDT = OFF // WDT disabled (control is placed on the SWDTEN bit) #pragma config PBADEN = OFF // PORTB<4:0> pins are configured as digital I/O on Reset #pragma config MCLRE = ON // MCLR pin enabled; RE3 input pin disabled #pragma config STVREN = ON // Stack full/underflow will cause Reset #pragma config LVP = OFF // Single-Supply ICSP disabled #pragma config XINST = OFF // Instruction set extension and Indexed Addressing mode disabled #pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF, CPB = OFF, CPD = OFF #pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF #pragma config WRTC = OFF, WRTB = OFF, WRTD = OFF #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF, EBTRB = OFF void main( void ) { int offset = -1; int duty = 255; int loop = 0; //-------------------------------------------------- // PWM出力を開始する // プリスケーラ 1:1, 255までカウント // -> CPUが40MHz駆動で、PWMサイクルが39kHz // 40M / ( 4 * (255+1) ) = 39.0625kより //-------------------------------------------------- OpenTimer2( TIMER_INT_OFF & T2_PS_1_1 & T2_POST_1_1 ); OpenPWM1( 0xff ); while( 1 ) { //------------------- // duty比をセット //------------------- SetDCPWM1( duty ); //------------------------------------ // duty比を変化させる(5%~100%を往復) //------------------------------------ duty += offset; if ( duty <= 64 ) { offset = 1; } if ( duty >= 1023 ) { offset = -1; } //------------------------------------------ // ゆっくり点滅させる為に,ディレイを入れる //------------------------------------------ for ( loop = 0; loop < 100; loop++ ) { ; // nop } } } |
periferal libararyを使用せずにPWM機能を使う
上記のコードではMicrochipが用意しているperiferal libararyの関数を使用しています。具体的には、OpenTimer2() OpenPWM1(), SetDCPWM1()がライブラリの関数です。
これらの関数を使用せずにレジスタへ直接値をセットしたい場合は,以下のコードとなります。
(例ではduty比50%で,CPUが10MHz動作時にPWM周波数を20kHzとして出力しています)
//------------------------ // PWMモード初期設定 //------------------------ CCP1CONbits.CCP1M = 0b1100; //11xx:PWMモード TRISCbits.TRISC2 = 0; T2CONbits.TMR2ON = 0; PR2 = 124; // 124までいったらTMR2をリセット(CPU=10MHz時に20kHz出力) //------------------------ // Timer2初期設定 //------------------------ T2CONbits.T2CKPS1 = 0b00; // 0b00:プリスケーラ1/1, 0b01:1/4, 0b1x:1/16 TMR2 = 0; // タイマ値をクリア PIE1bits.TMR2IE = 0; // 割り込み未使用 //PIR1bits.TMR2IF = 0; // 割り込みフラグを落としておく T2CONbits.TMR2ON = 1; // Timer2スタート // Duty比50%でセット CCPR1L = PR2 / 2; |
PWM出力周波数の計算
PWMで出力する矩形波の周波数は、CPUクロック、TMR2プリスケーラ(T2CONレジスタのT2CKPS)、PR2レジスタの値で決まります。これは、計算するのが結構面倒なので、Excelで一覧表を作成しました。
以下のファイルをダウンロード後、クロック周波数の値(シートのB3セル)を変更すると、TMR2プリスケーラ、PR2の値毎の周波数一覧が表示されます。
ダウンロード:PIC_PWM周波数計算.zip
関連記事
このPWMのプログラムとても参考になりました。ありがとうございます。
ちなみに、CCPモジュールの使い方がいまいちわかりません。キャプチャモード、コンペアモード
よろしければ、CCPを使用したものもあげて頂けないでしょうか