目次>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
; =========================== ここまで ===============================