; Copyright 2005 Yasuhiro Kanzaki ; PWMテスト f877088.asm        リスト8-3 list p=16f877A ; listはデバイス定義の擬似命令(ディレクティブ) #include ; デバイスに対応した変数定義のファイルを読み込む __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF ;***** 変数定義 w_temp equ 70h ; 汎用レジスタをWレジスタの保存用に定義 status_temp equ 71h ; 汎用レジスタをSTATUSレジスタ保存用に定義 sft_timer1 equ 78h ; ソフトウェア・タイマ用のカウンタと受け渡しフラグb7 sft_timer2 equ 79h ; 任意の数設定できる sft_timer3 equ 7ah ORG 000h ; プログラム開始アドレス goto main ; メイン・ルーチンへジャンプ ;割り込み処理ルーチン ORG 0x004 ; 割り込み処理の開始アドレス movwf w_temp ; Wレジスタを保存 movf STATUS,w ; STATUSレジスタの保存のためWレジスタへ移す movwf status_temp ; STATUSレジスタを保存 bcf STATUS,RP0 ; バンク0選択 btfsc sft_timer1,7; ソフトウェア・タイマのサービス要求チェック goto irskip1 ; サービス要求が無ければ次に進む decfsz sft_timer1,f; タイマの計数値をカウントダウン goto irskip1 ; ゼロでなければ次に進む bsf sft_timer1,7; 計数終了フラグをセット irskip1 btfsc sft_timer2,7; 2番目のソフトウェア・タイマのサービス要求チェック goto irskip2 ;  decfsz sft_timer2,f; goto irskip2 ; bsf sft_timer2,7; irskip2 bcf PIR2,CCP2IF ; 割り込みフラグのクリア movf status_temp,w ; movwf STATUS ; STATUSレジスタの回復 swapf w_temp,f ; STATUSレジスタに影響を与えないためswapf命令を利用 swapf w_temp,w ; Wレジスタを回復 retfie ; 割り込み処理を終えメイン・ルーチンに戻る ;メインルーチン ;PWM 設定(初期化ルーチン) main movlw 0ch ; SSP1をPWMモードに設定 movwf CCP1CON ; movlw 0FFh ; PWM 初期化ルーチン movwf CCPR1L ; デューティ・サイクルは 初期値 ff/ff %  bsf STATUS,RP0 ; バンク1を選択 movlw 0ffh ; 周期レジスタに,パルス周期を決める値をPR2レジスタにセット movwf PR2 ;   bcf TRISC,2 ; RC2を出力に設定 bcf STATUS,RP0 ; バンク0を選択 bsf T2CON,TMR2ON; タイマ2をプリスケーラ1:1でスタート ;タイマ1初期化 movlw 31h ; プリスケーラ1:8 クロック Fosc/4 OSC停止 movwf T1CON ; タイマの初期化を行う movlw 00bh ; CCP2 初期化 movwf CCP2CON ; CCP2 コンペア,スペシャル・イベント・トリガ  movlw d'53' ; タイマ1の周期を10msに割り込みを出すように movwf CCPR2L ; 設定する movlw d'12' ; movwf CCPR2H ; bsf STATUS,RP0 ; バンク1を設定 Clrf TRISD ; PORTD ポートBの設定 bcf OPTION_REG,NOT_RBPU ; ポートBプルアップ bsf PIE2,CCP2IE ; CCP2割り込みイネーブル bcf STATUS,RP0 ; バンク0を設定 bsf INTCON,GIE ; 全体の割り込み処理を許可; bsf INTCON,PEIE ; 周辺装置からの割り込み処理許可 loop movf CCPR1L,W ; デューティをの設定値Wレジスタに読み取る movwf PORTD ; ポートDへ出力 swapf PORTB,W ; DIPスイッチのデータを読み込む movwf sft_timer1 ; ソフト・タイマにセット bcf STATUS,C ; キャリをクリアする,ポートBから読み取ったデータを rrf sft_timer1,f; 右にシフトし7ビットにする.b7=0タイマセット rep11 btfss sft_timer1,7; タイマ完了を待つ goto rep11 ; 繰り返す decf CCPR1L,f ; 所定の時間完了したのでデューティ値をカウントダウンする goto loop ; Loopに戻り繰り返す END ; プログラムの終了