PWMを利用してブザーを鳴らすプログラムを組んでみた。例によってこれだけでは何も役にはたちません。:)
回路は、
こちらと同じ。
使用したデバイスはPIC16F88。まあ、PWMがついていればどれでもいいですが、最近のECCPをつんだ物ではコンフィグが少し異なると思います。ECCPについては、また後日実験するつもりです。
RB3にBuzzer, RA0にLEDを接続していますので、この2つは出力に設定します。面倒なので全ポート出力にしてしまっています。
クロックは内部発振で8MHzにしています。
次にPWMの設定ですが、これはTMR2(タイマー2)の値で周期(period)とデューティー(onの期間)が決まります。
periodはPR2レジスタに、dutyはCCPR1Lレジスタにそれぞれ設定します。
計算方法はデータシートに詳細がありますが、この例ではカウンタがオーバーフローするのでプリスケーラーを利用します。
クロック8MHz(周期0.125usec)ですので、周波数を1khzにするためにはプリスケーラーを利用して1/16に分周し、
period=1000usec=(PR2+1)*0.125*4*16
PR2=0x7Dとなります。
dutyは50%で固定するので、CCPR1L=0x3Eとなります。(実際はdutyはCCP1CON<5:4>を用いて分解能10bitで表現可能ですがここでは使っていません。)
これらをふまえたアセンブラコードは次の通りです。
BCF INTCON,GIE ;Interrupt Disable
BSF STATUS,RP0 ;Set page 1
CLRF TRISA
CLRF TRISB
CLRF ANSEL ; Analog input disable
MOVLW 0x70 ; set INTOSC to 8Mhz
MOVWF OSCCON
MOVLW 0x7D
MOVWF PR2 ; period 1 msec
BCF STATUS,RP0 ;Set page 0
MOVLW 0xff
MOVWF PORTA
MOVWF PORTB
MOVLW 0x3e
MOVWF CCPR1L ; Duty cycle 50%
MOVLW 0x06
MOVWF T2CON ; TMR2 on, pre scaler 16
ブザーを鳴らしたいときは、このようにし、
MOVLW 0x0c
MOVWF CCP1CON ; CCP1 enable
とめたい時はこのようにすればよいです。
CLRF CCP1CON ; CCP1 disable
BSF PORTB,3
CCP1CONに11xxを設定するとPWMが有効になるのですが、はじめ1111(0xff)に設定したらエミュレーター上で動かなくて悩みました。
Microchip Technology社に問い合わせたところ、どうやらMPLAB IDE v7.0のバグのようで、v8.0にアップグレードしたら直りました。0x0cに設定している分にはバグにはヒットしません。
また、今回は必要なかったですが、dutyの設定値が有効になるのは、TMR2が0x0になったとき(つまり次の周期から)なので、直ちに反映させたい場合は次のようにしてカウンタをリセットしてしまうと良いです。
MOVLW 0xff
MOVWF TMR2
ソースコードは
こちら。