; Copyright 2005 Noriaki Mitsunaga list p=16f877a ; PIC16F877A 用のプログラムであることを宣言 #include p16f877a.inc ; PIC16F877A 用のヘッダファイルを読み込む __config _HS_OSC & _CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF ;; -------------------------------------------------------------------- ;; レジスタの割り当て ;; -------------------------------------------------------------------- CT_DELAY1MS equ 0x20 CT_DELAYNS equ 0x21 CT_DELAY_LOOP equ 0x22 PORTB_OLD equ 0x23 DARK_TH equ 0x24 ;; バンク切り替えをしても読める領域に次の2つはとる DATA_EE_ADDR equ 0x70 ; EEPROM 書き込みアドレス DATA_EE_DATA equ 0x71 ; EEPROM 書き込みデータ ;; -------------------------------------------------------------------- ;; EEPROM 領域(あらかじめEEPROMに書き込んでおくデータ) ;; -------------------------------------------------------------------- org 0x2100 ; EEPROM 領域の擬似アドレス de 0xff ; EEPROM に書く初期値 ; de に続いて書くと1バイトのデータとして ; EEPROM へ書かれる ;; -------------------------------------------------------------------- ;; ここからプログラム ;; -------------------------------------------------------------------- org 0 ; プログラム開始 ; 初期設定をする bcf STATUS, RP0 ; この2行でバンク0にする bcf STATUS, RP1 clrf PORTC ; LED が点灯しないように0に clrf PORTD ; 出力は0にしておく clrf PORTE ; 出力は0にしておく movlw B'01000001' ; ADコンバータの設定(ADCON0) movwf ADCON0 bsf STATUS, RP0 ; バンク1にする movlw 0xff movwf TRISB ; ポートBはデジタル入力 bcf OPTION_REG, NOT_RBPU ; ポートBのウィークプルアップを有効に clrf TRISC ; 全ピン出力に clrf TRISD ; 全ピン出力に movlw B'01000000' ; ADコンバータの設定(ADCON1) movwf ADCON1 bcf STATUS, RP0 ; バンク0にする ; 初期設定は終了 movlw B'00100000' ; LED0 は消灯 LED1 は点灯 movwf PORTC ; movfw PORTB andlw B'00000011' ; スイッチのついているビットだけ取り出す movwf PORTB_OLD ; 直前の PORTB の値として覚えておく ;; ------------------------------------------------ ;; EEPROM からの読み込み movlw 0x0 ; EEPROM のアドレス0を読む call EE_READ movwf DARK_TH ; EEPROM のデータを閾値とする ;; ------------------------------------------------ ; メインルーチン loop ; AD 変換する bsf ADCON0, GO ; A/D 変換開始 btfsc ADCON0, GO ; A/D 変換終了まで待つ goto $-1 movfw PORTB ; 時刻 t のスイッチの状態をwへ andlw B'00000001' ; スイッチのついているビットだけ取り出す xorwf PORTB_OLD, f ; 排他的論理輪をとりスイッチの状態が ; 変わったかチェックする(wは変化しない) ; 変化がないなら0になる movwf PORTB_OLD ; w (時刻t のスイッチの状態)を代入(Zは変化しない) btfsc STATUS, Z ; 0 かチェック goto chk01 ; 0 なので変化していない ;; スイッチ0か1のどちらが押されたかチェック btfsc PORTB_OLD, 0 ; スイッチ 0 が 0 かチェック goto chk01 ; 0 なので変化していない ;; スイッチ0が押された movfw ADRESH movwf DARK_TH ;; ------------------------------------------------ ;; EEPROM への書き込み movwf DATA_EE_DATA ; EEPROM データに閾値を書く clrf DATA_EE_ADDR ; EEPROM アドレスを0に call EE_WRITE ; 新しい閾値をEEPROMに書く ;; ------------------------------------------------ chk01 movfw ADRESH ; W に変換結果を代入 subwf DARK_TH, w ; 暗さの閾値と比較をする ; DARK_TH - W の結果が負(C が 0)なら暗い btfss STATUS, C goto blink_LED ; LED を点滅させる ;; 20ms 待つ movlw D'20' movwf CT_DELAY_LOOP call delay1ms decfsz CT_DELAY_LOOP, f goto $-2 goto loop ; 点滅の部分 blink_LED movlw B'00100001' ; movwf PORTC ; 点灯 movlw D'250' call delayns ; 250×2[ms]待ち movlw B'00100000' ; movwf PORTC ; 消灯 movlw D'250' call delayns ; 250×2[ms]待ち goto loop ; メインルーチンは、ここまで ;; ------------------------------------------------------------- ;; EEPROM 読み込みサブルーチン ;; 呼び出し:W レジスタに読み込むアドレスを入れる ;; 返り値:Wレジスタに EEPROM の内容が入る ;; ------------------------------------------------------------- EE_READ bsf STATUS,RP1 ; bcf STATUS,RP0 ; バンク 2 movwf EEADR ; 読み出すアドレスをセットする bsf STATUS,RP0 ; バンク 3 bcf EECON1,EEPGD ; 読み出す対象はデータメモリ bsf EECON1,RD ; 読み出し bcf STATUS,RP0 ; バンク 2 movfw EEDATA ; EEDATA から w レジスタへコピー bcf STATUS,RP1 ; バンク 0 return ;; ------------------------------------------------------------- ;; EEPROM 書き込みサブルーチン ;; 呼び出し:DATA_EE_ADDR に書き込みアドレス ;; DATA_EE_DATA に書くデータ ;; を入れて呼び出す ;; 返り値:なし ;; ------------------------------------------------------------- EE_WRITE bsf STATUS,RP1 ; bsf STATUS,RP0 ; バンク 3 btfsc EECON1,WR ; 前回の書き込みが終了するのを待つ goto $-1 ; bcf STATUS, RP0 ; バンク 2 movfw DATA_EE_ADDR ; Data Memory movwf EEADR ; Address to write movfw DATA_EE_DATA ; Data Memory Value movwf EEDATA ; to write bsf STATUS,RP0 ; バンク 3 bcf EECON1,EEPGD ; 書き込み対象はデータメモリ bsf EECON1,WREN ; 書き込みを有効に bcf INTCON,GIE ; 割り込み禁止 movlw 0x55 ; movwf EECON2 ; 0x55 を書く movlw 0xaa ; movwf EECON2 ; 0xaa を書く bsf EECON1,WR ; WR ビットを1にし書き込み開始 ; bsf INTCON,GIE ; 必要なら割り込み許可 bcf EECON1,WREN ; 書込み禁止 bcf STATUS, RP0 bcf STATUS, RP1 ; バンク 0 return ;; ------------------------------------------------------------- ;; ディレーループサブルーチン ;; ------------------------------------------------------------- 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 delayns: movwf CT_DELAYNS ; 1 movf CT_DELAYNS, f ; 1 btfsc STATUS, Z ; 1 return ; 2 delaynsl1: call delay1ms ; 2500 call delay1ms ; 2500 decfsz CT_DELAYNS, f ; 1(次の行を実行)、2(次の行はとばす) goto delaynsl1 ; 2 return ; 2 end