目次8章.機能が豊富なPICを使う(PIC16F88)>汎用PWMコントローラ

汎用PWMコントローラ

更新日2009.6.27

ここではPIC16F88のPWM(Pulse Width Modulation)機能を使った実験を行います。

PIC16F88には、CCP(CAPTURE/COMPARE/PWM)と言うモジュールが内蔵されていて、この中のPWM機能を使うとPWM信号を容易に出力できます。

PWMとは
下図ように、周期は一定にしてパルスの幅を変える方式を、PWM(Pulse Width Modulation:パルス幅変調)と言います。

パルス幅(ONの割合)が大きいほど出力の総量が大きくなるので、DCモータのスピード制御やLEDの明るさ制御などに使用されます。

PWM信号制御対象 例
LEDDCモータ


 
明るい高速


 
暗い低速
また、パルス幅に意味を持たせて制御するものとしてサーボモータなどがあります。

CCPモジュールとPWMモード
CCPモジュール

PIC16F88にはCCPモジュールが内蔵されています。
CCPモジュールは、レジスタの設定で以下の3種類の動作を選択できます。
キャプチャモードCCP1ピンの変化によりTMR1(TMR1H:TMR1L)レジスタの内容をCCPR1(CCPR1H:CCPR1L)レジスタにコピーし、キャプチャ割込みを発生する
コンペアモードTMR1(TMR1H:TMR1L)レジスタとCCPR1(CCPR1H:CCPR1L)レジスタの値が一致した時、CCP1ピンを変化させたりCCP1割込みを発生させる
PWMモードPR2レジスタで指定する周期と、CCPR1Lレジスタで指定するパルス幅により、CCP1ピンからパルス(矩形波)を出力する

今回は、PWMモードを使用します。

PWMモード

PIC16F88では、以下のようにPWMを実現しています。

PR2レジスタでPWMの周期を指定し、CCPR1Lレジスタでパルス幅を指定します。
それぞれのレジスタで指定する値は、TMR2のカウント数です。

従って、TMR2の周波数(または周期)を決定すると、PWMの周期とパルス幅の範囲が決まります。
TMR2は1命令サイクル毎に+1され、PR2レジスタの値と等しくなったらリセットされます。

具体例を以下に示します。
クロック周波数:4MHz
PR2:239
CCPR1L:50
TMR2プリスケーラ:1

命令サイクル:(1秒/4MHz)×4クロック=1uS(マイクロ秒)
PWM周期:1uS(マイクロ秒)×(239+1)=240uS
 実際の周期は、PR2レジスタの値+1となります。
PWM周波数:1秒/240uS=4167Hz
PWMパルス幅:1uS(マイクロ秒)×50=50uS


下の図は、PWM関連のレジスタを表しています。(データシートからの抜粋)


設定するレジスタは、一番上のCCPR1Lレジスタ(パルス幅)と一番下のPR2レジスタ(周期)です。

コンパレータが2つありますが、下のコンパレータはTMR2とPR2レジスタを比較し、周期のタイミングを作っています。
上のコンパレータは、TMR2とCCPR1H(間接的にCCPR1L)レジスタを比較し、パルス幅のタイミングを作っています。


補足1
TMR2は、プリスケーラを使用できます。
プリスケーラを使う場合、倍率は4倍/16倍の2種類で、T2CONレジスタで指定します。

補足2 (良く分からない場合は読み飛ばしても大丈夫です)
実際のパルス幅指定は、CCPR1Lレジスタ8ビットの下位にCCP1CONレジスタのビット5:4(CCP1X,CCP1Y)の2ビットを付加した10ビットでの指定になります。

また、TMR2がパルス幅と比較される場合は、TMR2レジスタ8ビットの下位に2ビットが付加され10ビットで使用されます。この10ビットは、1クロック毎にカウントアップされます。

従って、パルス幅の分解能は10ビットになります。

実験回路
今回の実験回路です。

RB3をCCP1ピンとして使い、PWM信号を出力します。

RA3,RA4はA/D変換で使います。可変抵抗を接続し、電圧に対応してPWMの周期とパルス幅を決定します。
RA3(AN3)A/D変換結果 → PWMの周期
RA4(AN4)A/D変換結果 → PWMのパルス幅
RA2のスイッチは、クロック切り替え用です。今回は内部クロック動作とし、1,2,4,8MHzをスイッチで選択します。

2つのA/D変換結果やクロックの状態をLCDに表示します。

上の回路のRB3からPWM信号を出力します。
ここに接続するものを変える事で色々な事ができます。下はその例です。

LEDの
明るさ制御
高輝度LEDの
明るさ制御
DCモータの
スピード制御
サーボモータの
制御
音を出す音を出す


ブレッドボードに組んだ状態。
RB3にはLEDを接続しています。(上の例の一番左の回路)
左上の6ピンのヘッダピン周りはICSP用回路です。

プログラムの仕様
AN3(RA3)とAN4(RA4)の電圧をA/D変換し、その結果でPWMの周期とパルス幅を決定します。
A/D変換結果は10ビットになりますが、上位8ビットを使います。
AN3 A/D変換結果 → PR2レジスタ
AN4 A/D変換結果 → CCPR1Lレジスタ

また、RA2のスイッチを押す毎にクロックの周波数を8→4→2→1MHzと変化させます。

クロック周波数変更に合わせて、以下の時間に関する定数を再設定します。
・A/D変換の基準時間(TAD
・ウェイトルーチン(時間待ち)のループカウント値
クロック周波数とPWMの周期(周波数)の関係は以下のようになります。
TMR2プリスケーラ=16
PR2=10の場合
クロック周波数
(MHz)
PWM
周期(uS)周波数(Hz)
88811,364
41765,682
23522,841
17041,420
TMR2プリスケーラ=16
PR2=255の場合
クロック周波数
(MHz)
PWM
周期(uS)周波数(Hz)
82,048488
44,096244
28,192122
116,38461

出力できる周波数は、約60〜11000Hzであり、スピーカをつなげた実験に使えます。
また、周期の最大は約16mSであり、サーボモータの実験も可能です。
周波数を可変にした理由はこのあたりから来ています。

プログラムの作成

A/D変換については、A/D変換を使うを参照して下さい。
また、LCDの使い方は、液晶ディスプレイを使うを参考にして下さい。

ここでは主に、PWM機能で使うレジスタの設定について説明します。

PWM機能で使うレジスタ

PWM機能で使う基本的なレジスタは以下の4つです。
レジスタ設定内容
CCP1CONCCP1CONレジスタでは、CCPモジュールの動作を指定します。
T2CONT2CONレジスタでは、TMR2の動作を設定します。
PR2PR2レジスタでは、PWMの周期を指定します。
CCPR1LCCPR1Lレジスタでは、PWMのパルス幅を指定します。
TMR2割込みを使う場合は、INTCON,PIR1,PIE1レジスタも使います。(今回は使いません)

<CCP1CONレジスタ>
ビットBit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
記号--CCP1XCCP1YCCP1M3CCP1M2CCP1M1CCP1M0
設定値

CCP1CONレジスタでは、CCPモジュールの動作を指定します。

CCP1X,CCP1Y
CCPR1Lレジスタの下位に連結されるビットで、合計10ビットでパルス幅を設定します。
今回は00固定としました。

CCP1M3-0
CCPモジュールの動作を指定します。
CCP1M3-0動 作
0000CCPモジュール未使用
0100キャプチャモード(立下りエッジ)
0101キャプチャモード(立ち上がりエッジ)
0110キャプチャモード(立ち上がりエッジ4回毎)
0111キャプチャモード(立ち上がりエッジ16回毎)
1000コンペアモード(出力セット,CCP1IFセット)
1001コンペアモード(出力クリア,CCP1IFセット)
1010コンペアモード(出力変化無し,CCP1IFセット)
1011コンペアモード(出力変化無し,CCP1IFセット,TMR1リセット,A/Dモジュールが有効ならA/D変換開始)
11xxPWMモード
今回は、PWMモードで使用しますので、CCP1M3-0に1100を設定します。

<T2CONレジスタ>
ビットBit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
記号-TOUTPS3TOUTPS2TOUTPS1TOUTPS0TMR2ONT2CKPS1T2CKPS0
設定値

T2CONレジスタでは、TMR2の動作を設定します。

TOUTPS3-0
TMR2の出力ポストスケーラで1〜16倍の範囲が設定できます。(TMR2のリセット何回でTMR2割込みを発生させるか)
今回はTMR2割込みを使いませんので何をセットしてもかまいません。

TMR2ON
このビットをセット(1)することでTMR2が動作します。

T2CKPS1-0
TMR2のプリスケーラで1,4,16倍の範囲が設定できます。
今回は16倍で使います。(16命令サイクル毎にTMR2を+1する)
T2CKPS1-0プリスケーラ
00
01
1x16

<PR2レジスタ>
ビットBit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
記号PWM周期
設定値AN3のA/D変換結果(上位8ビット)

PR2レジスタでは、PWMの周期を指定します。

<CCPR1Lレジスタ>
ビットBit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
記号PWMパルス幅
設定値AN4のA/D変換結果(上位8ビット)

CCPR1Lレジスタでは、PWMのパルス幅を指定します。

コンフィグレーションビット

__CONFIG命令では以下の記述をします。

__CONFIG _CONFIG1, _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTRC_IO & _CCP1_RB3 & _LVP_OFF

_WDT_OFFウォッチドックタイマ使用しない
_BODEN_ON電源電圧低下監視を有効にする
_PWRTE_ONパワーアップタイマを有効にする
_INTRC_IOオシレータは内部クロック使用(15番ピン:RA6,16番ピン:RA7)
_CCP1_RB3CCPの出力ピンはRB3を使用(省略するとRB0になる)
_LVP_OFF低電圧プログラミング無効

プログラム全体
今回のプログラムはこちらです。

概略処理フローを以下に載せておきます。

実験風景
LEDを接続し、明るさ制御の確認をしているところ。
Pは周期、Wはパルス幅です。表示は両方とも16進数です。
商品化するのであればミリ秒単位とかで表示させる所です。
圧電スピーカ(圧電サウンダ)も同時に接続すれば、音でも動作が確認できます。
LEDだけだとクロックを切り替えても変化が見えませんが、圧電スピーカを接続すると周波数の変化が良く分かります。

サーボモータを使う場合は、周期とパルス幅を特定の値にする必要があります。
サーボモータの制御を参考にして下さい。