list p=16f877a ; PIC16F877A用のプログラムであることを宣言 #include p16f877a.inc ; PIC16F877A用のヘッダ・ファイルを読み込む __config _HS_OSC & _CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF CT_DELAY1MS equ 0x20 CT equ 0x22 CT2 equ 0x23 CT_DELAYNMS equ 0x24 PORTB_OLD equ 0x25 PORTC_ equ 0x26 ; 初期設定をする bcf STATUS, RP0 ; この2行でバンク0にする bcf STATUS, RP1 clrf PORTC ; LEDが点灯しないように0に clrf PORTD ; 出力は0にしておく clrf PORTE ; 出力は0にしておく bsf STATUS, RP0 ; バンク1にする clrf ADCON1 ; ポートAはアナログ入力 movlw 0xff movwf TRISB ; ポートBはディジタル入力 bcf OPTION_REG, NOT_RBPU ; ポートBのウィーク・プルアップを有効に clrf TRISC ; 全ピン出力に clrf TRISD ; 全ピン出力に clrf TRISE ; 全ピン出力に bcf STATUS, RP0 ; バンク0にする ; 初期設定は終了 ; メイン・ルーチン clrf PORTC_ movlw D'20' ; デューティ比の初期値 movwf CT movfw PORTB andlw B'00000011' ; スイッチのついているビットだけ取り出す movwf PORTB_OLD ; 直前のPORTBの値として覚えておく loop: movlw D'25' movwf CT2 loop05s: ; このループは20[ms]×25回繰り返される movfw PORTB ; 時刻tのスイッチの状態をwへ andlw B'00000011' ; スイッチのついているビットだけ取り出す xorwf PORTB_OLD, f ; 排他的論理輪をとりスイッチの状態が ; 変わったかチェックする(wは変化しない). ; 変化がないなら0になる movwf PORTB_OLD ; w(時刻t のスイッチの状態)を代入(zは変化しない) btfsc STATUS, Z ; 0かチェック goto chk02 ; 0なので変化していない ;; スイッチ0か1のどちらが押されたかをチェック btfsc PORTB_OLD, 0 ; スイッチ0が0かどうかをチェック goto chk01 ; 1なので押されていない ;; スイッチ0が押された movlw B'00100000' xorwf PORTC_, f ; LED1の点灯/消灯を反転する goto chk02 chk01 btfsc PORTB_OLD, 1 ; スイッチ1が0かどうかをチェック goto chk02 ; 1なので押されていない ;; スイッチ1が押されたときに行う処理はここに書く goto chk02 chk02 bsf PORTC_, 0 movfw PORTC_ movwf PORTC ; 点灯 movfw CT call delaynms ; CT×1[ms] 待ち bcf PORTC_, 0 movfw PORTC_ movwf PORTC ; 消灯 movfw CT sublw D'20' call delaynms ; (20−CT)×1[ms] 待ち decfsz CT2, f ; 20×25=0.5[s] を数える goto loop05s decfsz CT, f ; デューティ比を変える goto loop movlw D'20' ; 0なら20に戻す movwf CT goto loop delay10us: goto $+1 ; 2 goto $+1 ; 2 goto $+1 ; 2 goto $+1 ; 2 goto $+1 ; 2 goto $+1 ; 2 goto $+1 ; 2 goto $+1 ; 2 goto $+1 ; 2 goto $+1 ; 2 nop ; 1 return ; 2 delay1ms: movlw D'89' ; 1 movwf CT_DELAY1MS ; 1 delay1msl1: call delay10us ; 25 decfsz CT_DELAY1MS, f ; 1(次の行を実行)、2(次の行はとばす) goto delay1msl1 ; 2 nop ; 1 goto $+1 ; 2 return ; 2 delaynms: movwf CT_DELAYNMS movf CT_DELAYNMS, f btfsc STATUS, Z ; 0なら、すぐに戻る return delaynmsl1: call delay1ms ; 1[ms] decfsz CT_DELAYNMS, f ; goto delaynmsl1 ; return ; end リスト4-18 Copyright 2005 Noriaki Mitsunaga