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