PICでPWM波形を生成する

PCファンコントローラーを作成したくなって、当初はタイマー555のICチップで試したが、思うような周波数、Duty比の設定ができなかった。
そこでPICのタイマー2モジュールを使ってPWM波形を生成したときのメモを残す。これが扱えるようになると、ステッピングモーターの制御なども可能になるはずである。

PICのタイマー2で使用するPR2値の算出が結構面倒で、わかりづらいのでjavascriptで算出ツールを作成してみた。

自作のビット計算、PWM設定ツール Bit calculator

このツールを使うと、PICのクロック周波数と希望するPWM周波数Duty値を入力すると、設定に必要なT2CONCCP1CONCCPR1Lの値が算出できるようにしてある。ただし、制限として1サイクル4クロックで動作するPIC18以下のマイコンでしか使えないので注意する。(PIC24、PIC32の場合は、ほんの少し計算式が異なるのとレジスタ名が違う。いずれは対応する予定)

さっそく上記ツールで、内部クロック4MHz、PWM2.5kHz、Duty値0.5のときの設定値を求めたのが以下の結果になる。

今回使用したPICは8ピンのPIC12F1822で、自作のPIC試験ボードに刺してPICkit3で書き込みをおこなう。


とりあえず、ピンはすべて出力、PICの初期設定と上記のPWM設定だけしたコードが以下になる。

/*
 * File:   main.c
 */
#include <xc.h>

// コンフィグレーション設定
#pragma config FOSC     = INTOSC   // 内部クロックを使用する(INTOSC)
#pragma config WDTE     = OFF      // ウォッチドックタイマー設定
#pragma config PWRTE    = ON       // 電源ONから64ms後にプログラムを開始する
#pragma config MCLRE    = OFF      // 外部リセットかデジタル入力(RA3)ピンとして使用するか
#pragma config CP       = OFF      // プログラムメモリの保護
#pragma config CPD      = OFF      // データメモリの保護
#pragma config BOREN    = ON       // 電源電圧降下常時監視機能
#pragma config CLKOUTEN = OFF      // CLKOUTピンをRA4ピンで使用する
#pragma config IESO     = OFF      // 外部・内部クロックの切替えでの起動設定
#pragma config FCMEN    = OFF      // 外部クロックの監視

#pragma config WRT    = OFF        // Flashメモリの保護
#pragma config PLLEN  = OFF        // クロックのプルアップ(x4)の設定 ※32MHzで使用する
#pragma config STVREN = ON         // スタックがオーバフローやアンダーフローしたらリセットをする
#pragma config BORV   = HI         // 電源電圧降下常時監視電圧(2.5V)設定
#pragma config LVP    = OFF        // 低電圧プログラミング機能

// delay用のクロック設定
#define _XTAL_FREQ 4000000         // delay用に必要(クロック4MHzを指定)

void main(void){
    
    // クロック設定
    // 内部4MHz
    OSCCON =  0b01101010;
    
    // ピン設定
    // すべてデジタル
    ANSELA = 0b00000000;
    // すべて出力
    TRISA = 0b00000000;
    
    // PWM設定(Timer2使用)
    // Clock = 4MHz, PWM = 2.5kHz, Prescala x4
    T2CON =   0b00000101;
    PR2 = 99;
    CCP1CON = 0b00011100;
    
    //CCPR1L =  0b00010011;//0.2
    CCPR1L =  0b00110001;//0.5
    //CCPR1L =  0b01001111;//0.8
    
    // 初期化
    TMR2 = 0;
    PORTA  = 0b00000000;
    
    // タイマー2開始
    TMR2ON = 1;
    
    while(1){
        
    }
    
    return;
}

PICkit3でPICへの書き込みが成功すると、RA2ピンに5V前後のPWM波形が出力されるはずである。手持ちのアナログなオシロスコープで観察した結果を以下に示す。

ほぼ5V、PWM周期2.5kHz、Duty値0.5の方形波が作成されていることがわかる。


Duty値を0.8に変更した結果

Duty値を0.2に変更した結果

なかなか良いのではないでしょうか?