目次8章.機能が豊富なPICを使う(PIC12F683)>(6)PWM機能を使ってスピーカを鳴らす(単音を出す)

PWM機能を使ってスピーカを鳴らす (PIC12F683)
(動作確認:単音を出してみる)

更新日2006.3.11

PIC12F683のPWM機能を使ってスピーカを鳴らします。

PIC16F84Aでスピーカを鳴らす実験を行いましたが、PIC16F84AにはPWM機能が無いため、プログラムでパルスを生成し、スピーカに出力しました。

PIC12F683には、CCP(Capture/Compare/PWM)モジュールというものが内蔵されていて、PWMモードに設定すると5番ピン(GP2/CCP1)からパルス(矩形波)を出力できます。
ここでは、CCPのPWMモードを使ってスピーカを鳴らす実験を行います。

実験回路
今回の実験で使用する回路です。
5番ピン(GP2/AN2/T0CKI/INT/COUT/CCP1)にスピーカを接続します。
2番ピン(GP5)のLEDは、今回は使用しませんので無くてもかまいません。

ブレッドボードの右端にあるLEDと抵抗は、回路図にはありませんが電源ランプとして使っています。

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

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

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

PWMモード

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

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


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

PR2レジスタで周期を指定し、CCPR1Lレジスタでデューティを指定します。
それぞれのレジスタで指定する値は、TMR2のカウント数です。

従って、TMR2の周波数(または周期)を決定すると、周期とデューティを決められます。
TMR2のカウントアップは、1命令サイクル毎に+1されます。

具体例を以下に示します。
クロック:4MHz
PR2:239
CCPR1L:50

命令サイクル:(1秒/4MHz)×4クロック=1uS(マイクロ秒)
周期:1uS(マイクロ秒)×239=239uS
周波数:1秒/239uS=4184Hz
デューティ:1uS(マイクロ秒)×50=50uS


下の補足は、良く解らなければ、TMR2に4倍/16倍のプリスケーラが使用できることだけを理解し、後の記事は無視しても使用できます。

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

TMR2がデューティとして使用される場合は、プリスケーラ相当の2ビットが下位に付加され、10ビットで使用されます。

補足2
実際のデューティ指定は、CCPR1Lレジスタの8ビットにCCP1CONレジスタのビット5:4(DC1B1,DC1B0)の2ビットを付加した10ビットでの指定になります。
補足3
補足1と補足2から、デューティは10ビットの分解能があると言えます。

プログラムの仕様

今回作成するプログラムは、ドレミの「ド」の音をPWMを使用して出すというものです。
クロックは、内部クロックを使用し、4MHzとします。

「ド」の音は、261.5Hzとしました。TMR2は16倍のプリスケーラを付けて、動作させます。

《設定内容》

クロック:4MHz
PR2:239
CCPR1L:50
TMR2プリスケーラ:16倍

《結果》

命令サイクル:(1秒/4MHz)×4クロック=1uS(マイクロ秒)
周期:1uS(マイクロ秒)×239×16=3.824mS
周波数:1秒/3.824mS=261.5Hz
デューティ:1uS(マイクロ秒)×50×16=0.8mS

プログラムの作成

今回のプログラムは単純で、各種レジスタを初期設定するだけです。

PICの初期化(使用するレジスタ)

今回のプログラムで初期設定するレジスタと、その設定値について説明します。
ここでは、今回設定する値を中心に説明します。
レジスタのもう少し詳しい説明は、「PIC12F683のレジスタ(特殊レジスタ:SFR)」を参照して下さい。

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

ポート(GP0〜GP5)のON/OFFを制御するレジスタで、0をセットするとOFF(LEDは消灯),1をセットするとON(LEDは点灯)になります。
初期値としては、全て0にします。
尚、Bit3,6,7は設定が無視されますが、プログラムでは0をセットします。

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

ポート(GP0〜GP5)を入力で使うか出力で使うかを指定します。

該当ポートは出力
該当ポートは入力

尚、Bit3,6,7は設定が無視されますが、プログラムでは0をセットします。

<CMCON0レジスタ>
ビットBit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
記号-COUT-CINVCISCM2CM1CM0
設定値

コンパレータの動作を設定するために使用しますが、今回はGP0〜2をデジタル入出力として使用しますので、CM0〜CM2には1を設定します。

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

OSCCONレジスタでは、オシレータの動作モードを設定します。
今回は4MHzで動作させますので、IRCF2,IRCF1に1を設定します。

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

ANSELレジスタでは、アナログ入力(A/D変換)の設定を行います。
今回は、AN0〜AN3(GP0,1,2,4)はデジタル入出力で使用しますので、全て0にします。

<PR2レジスタ>
ビットBit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
記号PWM周期
設定値239(十進数)

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

<CCPR1Lレジスタ>
ビットBit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
記号PWMデューティ
設定値50(十進数)

CCPR1Lレジスタでは、PWMのデューティ(パルス幅)を指定します。

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

CCP1CONレジスタでは、CCPモジュールの動作を指定します。
今回は、PWMモードで使用しますので、CCP1Mxに1100を設定します。

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

T2CONレジスタでは、TMR2のプリスケーラ(T2CKPSx)とTMR2動作開始(TMR2ON)を設定します。

コンフィグレーションビット(__CONFIG命令の設定)

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

__CONFIG _CP_OFF & _CPD_OFF & _WDT_OFF & _BOD_ON & _IESO_OFF& _PWRTE_ON & _INTOSCIO & _MCLRE_OFF

_CP_OFFプログラムメモリコードプロテクトしない
_CPD_OFFEEPROMメモリコードプロテクトしない
_WDT_OFFウォッチドックタイマ使用しない
_BOD_ON電源電圧低下監視を有効にする
_IESO_OFF内部・外部切り替えモード無効
_PWRTE_ONパワーアップタイマ有効
_INTOSCIOオシレータは内部クロック使用(2番ピン:GP5,3番ピン:GP4)
_MCLRE_OFFマスタクリア無効(4番ピンをGP3として使用)

プログラム全体
上記の処理を組み込んだプログラムはこちらです。
メモ帳などのテキストエディタに取り込んで、P683PWM.ASMという名で保存し、MPLABでアセンブル&PICライタでPICに書き込んで動かしてみて下さい。

今まで、PIC16F84Aを使用していた場合は、MPLABのプロジェクトウィザードで「PIC12F683」を選択して下さい。
また、PICライタでも同様に「PIC12F683」を選択して下さい。