PIC18F14K50の基本動作から応用プログラムまでを学びます。

ホーム
16F18313
16F18325
16F18346
16F1619
Curiosity
---
---
    
12F1822
16F1455
16F1459
18F14K50
18F26J50
dsPIC
その他
正弦波発生回路(PWM)

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で繰り返す
    }
}