---
---
8F14K50のPWM (Pulse Width Moduration) 機能を使用し50Hzの正弦波を発生させる回路を作りました。最近需要が高まっている正弦波インバータの基本実験のつもりでプログラムを作成しました。
PICkit2の本来機能は、PICにプログラムを書き込む機能ですが、デバッグなどに大いに役立つ、3チャンネルのロジックアナライザーとしても利用することができます。今回この機能で、PWM波形を観察しました。ロジックアナライザーとして使用する方法などは、ここをご覧ください。
アナライザーの波形をみると、各PWM周期毎に、その、デューティサイクルが変化しているのが良く分かります。この信号をRCによるローパスフィルターを通せば、きれいなアナログ正弦波として出力することができます。
プロジェクトファイル H07a_SineWavePolling.zip |
<プログラム>
main.c
//--------------------------------------------------------- // CCP PWM機能による正弦波の発生 <polling> // CCP → PWM機能で sin波を発生させる // Notes: 4MhzM内部クロック // PWM周期は4KHz、デューティは250段階。PWM周期ごとに、 // デューティを正弦波になるよう、変更していく。 // 変更を、80PWM周期で一巡すれば、4KHz/80 = 50Hzとなり、 // 4.5°毎のSIN関数をデューティにセットすればよい。 // RC2 signalOut P1D // RC3 signalOut P1C // RC4 signalOut P1B // RC5 signalOut P1A // Language: MPLAB xc8 Target: PIC18F14K50 //-------------------------------------------------------- #include <xc.h> #define _XTAL_FREQ 4000000 // delay_ms(x) のための定義 //-------------- コンフィグレーション ---------------------- #pragma config FOSC = IRC // 内部クロック #pragma config PWRTEN = OFF, BOREN = OFF, BORV = 30 #pragma config WDTEN = OFF, WDTPS = 32768 #pragma config MCLRE = OFF, STVREN = ON #pragma config PLLEN = ON, CPUDIV = NOCLKDIV, USBDIV = OFF #pragma config FCMEN = OFF, IESO = OFF, HFOFST = OFF #pragma config LVP = OFF, XINST = OFF, BBSIZ = OFF #pragma config CP0 = OFF, CP1 = OFF, CPB = OFF, CPD = OFF #pragma config WRT0 = OFF, WRT1 = OFF #pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF // ----------- 正弦波高のデータ ----------- const unsigned char sinValue[] = { 125,135,145,154,164,173,182,190,198,206, 213,220,226,232,236,240,244,247,248,250, 250,250,248,247,244,240,236,232,226,220, 213,206,198,190,182,173,164,154,145,135, 125,115,105, 96, 86, 77, 68, 60, 52, 44, 37, 30, 24, 18, 14, 10, 6, 3, 2, 0, 0, 0, 2, 3, 6, 10, 14, 18, 24, 30, 37, 44, 52, 60, 68, 77, 86, 96,105,115 }; //----------------------メインプログラム------------------ void main(void){ unsigned char cntDiv = 0; OSCCON = 0b01010010; // 内部クロック4Mhz TRISC = 0b11000011; // PortC RC2,3,4,5出力 // --------------- CCPの 設定 -------------------- CCP1CON = 0b00001100; // シングルアウト,正論理 CCPR1L = 0b00000000; // Duty Cycle PSTRCON = 0b00001111; // PWM出力はP1A,B,C,Dピン T2CON = 0b00000100; // PreS 1/1, Post 1/1 PR2 = 0b11111001; // PWM 周期 249 // --------------------------------------------- while(1){ while(PIR1bits.TMR2IF == 0); // Timer2の一致を待つ PIR1bits.TMR2IF = 0; // 一致フラッグをクリア CCPR1L = sinValue[cntDiv++]; // 4.5°毎の正弦波高を更新 if(cntDiv >= 80)cntDiv = 0; // 360°/4.5°= 80で繰り返す } }
上記プログラムのシステムクロックを32MHzにして、800Hzオーディオの正弦波を発生するプログラムです。PWM周期32KHzなのでかなり綺麗な正弦波です。
//--------------------------------------------------------- // CCP PWM機能による正弦波の発生 <polling> // CCP → PWM機能で sin波を発生させる // Notes: 32MhzM内部クロック Timer2 PR2 250 // PWM周期は32KHz、デューティは250段階。PWM周期ごとに、 // デューティを正弦波になるよう、変更していく。 // 変更を、40PWM周期で一巡すれば、32KHz/40 = 800Hzとなり、 // 9°毎のSIN関数をデューティにセットすればよい。 // RC2 signalOut P1D // RC3 signalOut P1C // RC4 signalOut P1B // RC5 signalOut P1A // Language: MPLAB xc8 Target: PIC18F14K50 //-------------------------------------------------------- #include <xc.h> #define _XTAL_FREQ 32000000 // delay_ms(x) のための定義 //-------------- コンフィグレーション ---------------------- #pragma config MCLRE = OFF, PWRTEN = OFF, BOREN = OFF, BORV = 30 #pragma config WDTEN = OFF, WDTPS = 32768, STVREN = ON #pragma config FOSC = IRC, PLLEN = ON #pragma config CPUDIV = NOCLKDIV, USBDIV = OFF #pragma config FCMEN = OFF, IESO = OFF, HFOFST = OFF, LVP = OFF #pragma config XINST = OFF, BBSIZ = OFF #pragma config CP0 = OFF, CP1 = OFF, CPB = OFF #pragma config WRT0 = OFF, WRT1 = OFF, WRTB = OFF, WRTC = OFF #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF // ----------- 正弦波高のデータ ----------- const unsigned char sinValue[] = { 125,145,164,182,198,213,226,236,244,248, 250,248,244,236,226,213,198,182,164,145, 125,105, 86, 68, 52, 37, 24, 14, 6, 2, 0, 2, 6, 14, 24, 37, 52, 68, 86,105 }; //----------------------メインプログラム------------------ void main(void){ unsigned char cntDiv = 0; OSCCON = 0b01100000; // 内部クロック8Mhz x PLL4 TRISC = 0b11000011; // PortC RC2,3,4,5出力 // --------------- CCPの 設定 -------------------- CCP1CON = 0b00001100; // シングルアウト,正論理 CCPR1L = 0b00000000; // Duty Cycle PSTRCON = 0b00001111; // PWM出力はP1A,B,C,Dピン T2CON = 0b00000100; // PreS 1/1, Post 1/1 PR2 = 0b11111001; // PWM 周期 249 // --------------------------------------------- while(1){ while(PIR1bits.TMR2IF == 0); // Timer2の一致を待つ PIR1bits.TMR2IF = 0; // 一致フラッグをクリア CCPR1L = sinValue[cntDiv++]; // 9°毎の正弦波高を更新 if(cntDiv >= 40)cntDiv = 0; // 360°/9°= 40で繰り返す } }