PIC16F84電子遊戯(11)
最終更新日:2001年2月3日
温度計(1ページ)へ (2ページ)へ (3ページ)

温度計の温度センサーの出力電圧の調整
A/D変換されたデータを表示データに変換する処理を説明する前に、温度センサーの出力電圧を調整しておきましょう。
温度センサーの出力電圧は1℃につき10mVです。これをオペアンプで10倍に増幅します。
まず、LM35DZの出力電圧をデジタルテスタで計測します。uPC358Cの3ピンの電圧でOKです。次にその電圧の10倍値になるように1ピンにテスタを当てて10kVRを調整しましょう。
温度計のA/D変換値の表示データへの変換
さて、読み込んだA/D変換値はどのようにして表示データに変換するのでしょうか。
まず、オペアンプを含めた温度センサーからの電圧は、例えば40℃のとき、4Vとなります。A/D変換の基準電圧が5Vなので、4VのときのA/D変換値は204(256/5*4=204.8)となります。この値を5で割れば40(204/5=40.8)となりほぼ測定値に合った表示となります。
(正確には1ビットを0.2℃として表示します。256のときに51.2℃となるので50℃を超えてしまいますが、10kVRを再調整して近似になるようにしましょう。)
ここで難しいのがA/D変換値を5で割るということです。
温度表示は10℃、1℃、0.1℃の位を順に表示しますので、位ごとに表示データを算出します。まず10℃の表示データはA/D変換値を50で割った値です。50で割るというのは難しいので、A/D変換値から50が何回引けるかで算出します。
同様にその残りのデータから5が何回引けるか算出して1℃の表示データとします。
ここまで計算すると残りは4以下となります。
このデータを2倍して0.1℃の表示データとします。
以上より、温度表示は0.2℃きざみとなります。実用になる上限は45℃くらいです。
最終的には温度センサーの出力電圧をテスターで計測しながら、表示データを合うように10kVRを微調整しましょう。
A/D変換値を演算エリアにコピーする
10℃、1℃計算エリアをクリアする
演算エリア値を50で割った商を10℃のデータとする
残りの値を5で割った商を1℃のデータとする
残りの値を2倍したものを0.1℃のデータとする
それぞれの計算結果を表示データへコピーする
表示データの計算にはそれぞれの計算用RAMを用意しました。
adsub_data sub2_data sub3_data
A/D変換値を演算エリア 1℃計算エリア 10℃計算エリア
割り算(減算の繰り返し)に使用する値もデータとして定義しておきましょう。
data10 data1
32H 5H
表示データへの変換は0.5秒ごとに行います。
メインルーチンで毎回行ってもいいのですが、そうすると表示が常に変化してしまうので、見栄えが悪くなります。
7セグの表示は常に行われますが、変換は0.5秒ごとに行うため、見かけ上は0.5秒ごとにセンスしているように見えます。(いかにも温度計のようです。)
温度計の全ソースリスト公開
温度計の全ソースリストです。
まだ未熟な点もありますので、皆さんでお好みに改造して下さい。
;**********************************************************************
;    Filename:	    ondokei.asm                                       *
;    Date:          2001/1/20                                        *
;    File Version:                                                    *
;**********************************************************************
	list      p=16F84             ; list directive to define processor
	#include <p16F84.inc>         ; processor specific variable definitions
	__CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;***** VARIABLE DEFINITIONS
w_temp        EQU     0x0C        ; variable used for context saving 
status_temp   EQU     0x0D        ; variable used for context saving
wait_data	EQU	0x10		;wait data
ondo1_data	EQU	0x11		;ondo(0.1) LED data ram
ondo2_data	EQU	0x12		;ondo(1) LED data ram
ondo3_data	EQU	0x13		;ondo(10) LED data ram
adin_data	EQU	0x14		;ad input data ram
count_data	EQU	0x15		;0.5sec keisoku count ram
adsub_data	EQU	0x16		;ad keisanyou ram
sub2_data	EQU	0x17		;sub(1) data ram
sub3_data	EQU	0x18		;sub(10) data ram
tm0_setdata	EQU	63h		;255-156=99=63H  156*128=19.968msec
cnt_setdata	EQU	19h		;19.968*25=0.4992sec
data10		EQU	32h		;henkanyou data 1
data1		EQU	5h		;henkanyou data 2
;**********************************************************************
		ORG     0x000             ; processor reset vector
  		goto    main              ; go to beginning of program
;----------------------------------------------------------------------------------
		ORG     0x004             ; interrupt vector location
		movwf   w_temp            ; save off current W register contents
		movf	STATUS,w          ; move status register into W register
		movwf	status_temp       ; save off contents of STATUS register
		;---------------------------------	
		bcf	INTCON,T0IF
		movlw	tm0_setdata
		movwf	TMR0
		decfsz	count_data,1
		goto	next_int
time_up		movlw	cnt_setdata		
		movwf	count_data
		;-------------------------------- data henkan
		movf	adin_data,0
		movwf	adsub_data
		movlw	00h	
		movwf	sub2_data
		movwf	sub3_data
next10
		movlw	data10
		subwf	adsub_data,0
		btfsc	STATUS,0
		goto	next20
		goto	next21
next20
		movwf	adsub_data
		incf	sub3_data,1
		goto	next10
next21
		movlw	data1
		subwf	adsub_data,0
		btfsc	STATUS,0
		goto	next30
		goto	next31
next30
		movwf	adsub_data
		incf	sub2_data,1
		goto	next21
next31
		movf	adsub_data,0
		movwf	ondo1_data
		bcf	STATUS,0
		rlf	ondo1_data,1	
		movf	sub2_data,0
		movwf	ondo2_data
		movf	sub3_data,0
		movwf	ondo3_data		
		;---------------------------------
next_int
		;----------------------------------
		movf    status_temp,w     ; retrieve copy of STATUS register
		movwf	STATUS            ; restore pre-isr STATUS register contents
		swapf   w_temp,f
		swapf   w_temp,w          ; restore pre-isr W register contents
		retfie                    ; return from interrupt
;---------------------------------------------------------------------------------------
main
		call	porta_set_out
		call	portb_set_out
		movlw	0ffh		;port initial set
		movwf	PORTA
		movlw	00h
		movwf	PORTB
		movlw	00h
		movwf	ondo1_data
		movwf	ondo2_data
		movwf	ondo3_data
		movwf	adin_data
		call	timer0_set
		movlw	cnt_setdata
		movwf	count_data
main_loop
;--------------------------------------- led7_disp
		bcf	INTCON,GIE
		call	portb_set_out
		bsf	INTCON,GIE
		movf	ondo1_data,0
		movwf	PORTB
		bcf	PORTA,0
		call	wait_1
		bsf	PORTA,0
		movf	ondo2_data,0
		movwf	PORTB
		bcf	PORTA,1
		call	wait_1
		bsf	PORTA,1		
		movf	ondo3_data,0
		movwf	PORTB
		bcf	PORTA,2
		call	wait_1
		bsf	PORTA,2
;--------------------------------------- ad input
		bcf	INTCON,GIE
		call	portb_set_in
		bcf	PORTA,3
		nop
		nop
		nop
		bcf	PORTA,4
		nop
		nop
		nop
		bsf	PORTA,4
		nop
		nop
		nop
		movf	PORTB,0
		movwf	adin_data
		nop
		nop
		bsf	PORTA,3
		bsf	INTCON,GIE
;---------------------------------------
main_next
		goto	main_loop
;-------------------------------------------------------------------------------
wait_1		
		movlw	0ffh
		movwf	wait_data
wait_2
		decfsz	wait_data,1
		goto	wait_2
		return
;-------------------------------------------------------------------------------
porta_set_out				;RA0,RA1,RA2,RA3,RA4(OUT)
		bsf	STATUS,RP0
		clrf	TRISA
		bcf	STATUS,RP0
		return
;-------------------------------------------------------------------------------
portb_set_out				;RB0,RB1,RB2,RB3,RB4,RB5,RB6,RB7(OUT)
		bsf	STATUS,RP0
		clrf	TRISB
		bcf	STATUS,RP0
		return
;-------------------------------------------------------------------------------
portb_set_in				;RB0,RB1,RB2,RB3,RB4,RB5,RB6,RB7(IN)
		bsf	STATUS,RP0
		clrf	TRISB
		comf	TRISB,1
		bcf	STATUS,RP0
		return
;-------------------------------------------------------------------------------
timer0_set
		bsf	STATUS,RP0
		movlw	086h		;(1)PORTB NOT PULLUP
					;(0)INTEDG
					;(0)TOCS
					;(0)TOSE
					;(0)PSA
					;(110)1/128
		movwf	OPTION_REG
		bcf	STATUS,RP0
		
		movlw	tm0_setdata
		movwf	TMR0
		bsf	INTCON,T0IE
		bsf	INTCON,GIE
		return
;-----------------------------------------------------------------------------
		END                     ; directive 'end of program'
温度計の全HEXコード
HEXコードです。メモ帳などのテキストエディタにコピー&ペーストしてファイルすればPICに書き込めるデータに出来ます。
:020000003028A6
:080008008C0003088D000B11B0
:1000100063308100950B2B28193095001408960049
:1000200000309700980032301602031818281B2859
:100030009600980A13280530160203182028232852
:100040009600970A1B28160891000310910D1708B7
:100050009200180893000D0883008C0E0C0E090006
:100060006A206E20FF30850000308600003091004D
:100070009200930094007720193095008B136E2026
:100080008B171108860005106520051412088600DC
:100090008510652085141308860005116520051557
:1000A0008B13722085110000000000000512000073
:1000B0000000000005160000000000000608940083
:1000C0000000000085158B173E28FF309000900B34
:1000D00067280800831685018312080083168601AD
:1000E000831208008316860186098312080083168E
:1000F000863081008312633081008B168B170800D5
:02400E00F13F80
:00000001FF
(ondokei.hex)
温度計の各処理概要
ソースリストの赤い部分が割り込み処理、青の部分がメイン処理です。
後半の黒の部分が各種サブルーチンです。
割り込み処理
STATUSレジスタ退避
0.5秒カウンタ処理
A/D変換値の表示データへの変換
STATUSレジスタ復帰
メイン処理
初期設定
7セグメント表示処理
A/D変換入力
温度計の完成
以上で温度計は大完成です。A/D変換って結構簡単でしたね。
皆さんもオリジナルな仕様になるよう、どんどん改造してみて下さい。
これからも面白くなる「PIC16F84電子遊戯」をよろしくお願いします。

不明点などあればメールお願いいたします。nonchansoft@nifty.com

Copyright(c)2000-2001 nonchansoft