目次>6章 第3ステップ(実用品)>バッテリ放電器>ソース
バッテリ放電器(ソース)
<PIC16F873>
更新日2007.11.17
以下のソースを取り込んで、アセンブル→PIC書き込み→実行して下さい。
; ========================== ここから ============================== ; PIC16F873 ; clock:20MHz ; ; ニッケル水素充電池4本の放電 ; 4本の充電池が0.95Vになるまで放電する(独立制御で1本〜4本まで同時処理) ; 全ての放電が完了したらスリープモードに切り替える ; ; PORTA:RA0-3(AN0-3):1.2Vバッテリ4本の出力(電圧) ; 基準電圧はVdd(5V) ; ADRESLが195で0.95V (ADRESHが0以外の時は1.25V以上) ; PORTC:RC0-3:バッテリの残電圧を表示するLED ; PORTC:RC4-7:1.2Vバッテリ4本の放電指示(2SC3420のベースに接続) ; H:で放電 ; ; TMR0:AD変換器の充電時間(20μS)として使用 ; また、LED点滅時間(500mS)としても使用 ; ; list p=16f873 #include p16f873.inc __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_ON & _LVP_OFF & _CPD_OFF & _DEBUG_OFF timer equ 020h ;0:20μS save_st equ 021h ;STATUSのセーブ save_w equ 022h ;W-regのセーブ ad_h equ 023h ;ADRESHの保存 ad_l equ 024h ;ADRESLの保存 chanb equ 025h ;チャネル(ビット表現) chann equ 026h ;チャネル(数値表現) chanw equ 027h ;チャネル変換ワーク dchg_f equ 028h ;放電完了フラグ Bit0-3 cnt200 equ 029h cnt50 equ 02ah ledptn0 equ 02bh ;LED点滅パターン(CHANNEL#0) ledptn1 equ 02ch ;LED点滅パターン(CHANNEL#1) ledptn2 equ 02dh ;LED点滅パターン(CHANNEL#2) ledptn3 equ 02eh ;LED点滅パターン(CHANNEL#3) work equ 02fh ledof equ 030h cnt4 equ 031h f_t50u equ 00h f_t500m equ 01h org 0 goto init ;=================== 割込み処理 ================================== org 4 ;割込みの入口 intr bcf INTCON,T0IF ;割込みフラグクリア movwf save_w ;W-regセーブ swapf STATUS,w movwf save_st ;STATUSセーブ bsf timer,f_t50u ;50μS割込みフラグセット decfsz cnt200,F goto intr50 movlw d'200' movwf cnt200 decfsz cnt50,F goto intr50 movlw d'50' movwf cnt50 bsf timer,f_t500m ;500mS割込みフラグセット intr50 movlw d'131' ;カウント(125:256-131)値ロード movwf TMR0 ;TMR0へ出力(0.2μS*2*125=50μS) swapf save_st,w movwf STATUS ;STATUSロード swapf save_w,f swapf save_w,w ;W-regロード retfie ;割込み許可リターン ;=================== 初期化処理 ================================== init clrf timer movlw 08h movwf chanb ; ADチャネル#3 clrf dchg_f ;放電完了フラグリセット clrf ledptn0 ;チャネル0のLED表示パターンクリア clrf ledptn1 ;チャネル1のLED表示パターンクリア clrf ledptn2 ;チャネル2のLED表示パターンクリア clrf ledptn3 ;チャネル3のLED表示パターンクリア movlw 080h movwf ledof ;LED表示パターンの処理中ビット初期化 movlw d'200' movwf cnt200 movlw d'50' movwf cnt50 bsf STATUS,RP0 ;■バンク1に切替え movlw 03fh movwf TRISA ; RA0-5は入力 clrf TRISB ; TRISBをクリア。⇒RB0-7は出力 clrf TRISC ; TRISCをクリア。⇒RC0-7は出力 movlw 80h ; 2カウントモード指定(0.2μS*2=0.4μS) movwf OPTION_REG ;プリセットカウンタへ出力 bcf STATUS,RP0 ;■バンク0に切替え clrf PORTB movlw 0ffh movwf PORTC ;バッテリ4つ共放電開始 movlw d'131' ;カウント(125:256-131)値ロード movwf TMR0 ;TMR0へ出力(0.2μS*2*125=50μS) bsf INTCON,T0IE ;タイマ割込み許可 bsf INTCON,GIE ;全体割込み許可 ;=================== メイン処理 ================================== main0 btfss timer,f_t500m ;500mS割込み発生?(最初に500mS待つ) goto main0 bcf timer,f_t500m ;500mS割込みフラグOFF bcf timer,f_t50u ;50μS割込みフラグOFF call adinit ;AD変換器の初期化 main bcf STATUS,C ; rrf chanb,f ;処理中チャネル btfss STATUS,C ; の goto main01 ; 切り替え movlw 08h ; (3,2,1,0) movwf chanb ; main01 movf chanb,W ;該当バッテリは andwf dchg_f,W ; 放電を btfsc STATUS,Z ; 完了している? goto main05 ; no movf dchg_f,W ;全バッテリの sublw 0fh ; 放電 btfss STATUS,Z ; 完了? goto main ; no ; yes clrf INTCON ;全ての割込みを禁止し bcf ADCON0,ADON ; AD変換器を停止し clrf PORTB ; 全ポートを clrf PORTC ; クリアし sleep ; スリープモードに goto init main05 btfss timer,f_t50u ;50μSの残りを goto main05 ; 待つ bcf timer,f_t50u ;50μS割込みフラグOFF call chansel ;AD変換器のチャネル選択 btfsc timer,f_t500m ;500mS割込み発生? call ledset ; yes main1 btfss timer,f_t50u ;50μS経過?(アクイジション経過?) goto main1 ; NO bcf timer,f_t50u ;50μS割込みフラグOFF bsf ADCON0,GO ;AD変換開始 main2 btfsc ADCON0,GO ;AD変換完了? goto main2 ; NO call adread ;AD変換結果読み込み(放電完了?) goto main ;===================== AD変換器の初期化 =============================== adinit movlw 080h bsf STATUS,RP0 ;■バンク1に切替え movwf ADCON1 ;結果右詰め,RA0-3,5はADモード bcf STATUS,RP0 ;■バンク0に切替え return ;===================== AD変換結果読み込みと放電完了時の処理 ============ adread movf ADRESH,W btfsc STATUS,Z ;AD変換結果の上位が0 goto adr05 ; yes movlw d'0' ; no (1.24V以上) goto adr90 adr05 movwf ad_h bsf STATUS,RP0 ;■バンク1に切替え movf ADRESL,W bcf STATUS,RP0 ;■バンク0に切替え movwf ad_l movlw d'240' ;1.20V -0.03V subwf ad_l,W ;以上の btfss STATUS,C ;バッテリ電圧? goto adr10 ; no movlw d'0' goto adr90 adr10 movlw d'219' ;1.10V -0.03V subwf ad_l,W ;以上の btfss STATUS,C ;バッテリ電圧? goto adr20 ; no movlw d'1' goto adr90 adr20 movlw d'199' ;1.00V -0.03V subwf ad_l,W ;以上の btfss STATUS,C ;バッテリ電圧? goto adr30 ; no movlw d'2' goto adr90 adr30 movlw d'189' ;0.95V -0.03V subwf ad_l,W ;以上の btfss STATUS,C ;バッテリ電圧? goto adr40 ; no movlw d'3' goto adr90 adr40 movlw d'178' ;0.90V -0.03V subwf ad_l,W ;以上の btfss STATUS,C ;バッテリ電圧? goto adr50 ; no movlw d'4' goto adr90 adr50 ;放電終了 movf chanb,W iorwf dchg_f,F ;放電終了フラグON ;放電終了したバッテリの放電中表示OFF swapf dchg_f,W ; movwf work movlw 0fh andwf PORTC,W iorwf work,F movlw 0f0h xorwf work,W ;下位4ビットはそのまま、上位4ビット(放電終了フラグ)は反転 movwf PORTC movlw d'5' adr90 call ledpset ;LED表示パターンの選択 movwf work ;該当チャネルの movlw ledptn0 ; ledptn?に addwf chann,W ; LED movwf FSR ; 表示パターン movf work,W ; を movwf INDF ; セット adrext return ;===================== LED表示パターンの選択 ========================= ledpset addwf PCL,F retlw 0ffh ;0: 点灯 1.20V retlw 0feh ;1: 3.5秒点,0.5秒滅 1.10V retlw 0eeh ;2: 1.5秒点,0.5秒滅 1.00V retlw 0cch ;3: 1秒毎に点滅 0.95V retlw 0aah ;4: 0.5秒毎に点滅 0.90V retlw 00h ;5: 消灯 retlw 0ffh ;6: dummy ;===================== AD変換器のチャネル選択 ========================= ;===== chanb(ビット表現)をchann(数値表現に変換) chansel clrf chann movf chanb,W movwf chanw bcf STATUS,C chsel1 rrf chanw,F btfsc STATUS,C goto chsel4 incf chann,f goto chsel1 chsel4 ;===== AD変換器のチャネル選択 movf chann,W movwf chanw bcf STATUS,C rlf chanw,F rlf chanw,F rlf chanw,F movlw 081h iorwf chanw,W movwf ADCON0 ;FOSC/32(1.6μS),チャネル#chann,AD未,ADon return ;===================== 500mS割込み処理(LEDのon/off制御 ========== ledset bcf timer,f_t500m ;500mS割込みフラグクリア movlw ledptn3 ;ledptn3のアドレスを movwf FSR ; FSR(ポインタ)にセット clrf chanw ;各チャネルのLED表示をクリア movlw 04h movwf cnt4 bcf STATUS,C rrf ledof,F ;LED表示パターン処理中ビットのシフト btfss STATUS,C ; goto leds10 ; movlw 080h ; movwf ledof ; leds10 rlf chanw,F movf INDF,W ;LED表示パターンの andwf ledof,W ; 今回表示ビットが btfss STATUS,Z ; goto leds20 ; ONなら該当チャネルのLED表示をOFFにする bcf chanw,0 ; OFFなら該当チャネルのLED表示をONにする goto leds30 leds20 bsf chanw,0 leds30 decf FSR,F ;次のチャネルのLED表示パターンアドレスをセット decfsz cnt4,F ;4チャネル分 goto leds10 ; 繰り返す movlw 0f0h ;PORTCの下位4ビットに各チャネルの表示パターンセット andwf PORTC,W iorwf chanw,W movwf PORTC return end ; =========================== ここまで ===============================