もう少しだけ,重要なサブルーチンを作成する.サブルーチンというよりも,計測装置の心臓部ともいうべき,計測をどのように実施するかである.既に1/1000単位でそこそこの精度を持つ時計機能もストップウオッチの機能もほぼできたのであるが,これらの機能を使って陸上タイム計測装置に仕立てることを考えると,LAPはいくつまで考慮すれば良いんだろう,タイマーのようなものも欲しくなるかもな,時報だって正確に出さないといけないのだから,タイマー機も結構重要だ...その度に割り込みルーチンを含んだ改造やTMR1の初期化などやってしまったら,複雑なソフトになってしまう.
ここは,面倒くさいけれど今回もいつものの私流で行こう.時刻計測を”時間差”で行う方式だ.システムとしては,正確に秒を刻む”時計”が一つだけ用意する.STARTイベントが入ったら,この時の時刻を記憶する.GOALイベントが入った瞬間にその時の時刻を記憶し,この時刻からSTART時刻を引いた値がタイム(STARTからの経過時間)だ.計測中に現在時刻を読み出し,START時刻を引いてやれば,途中の経過秒表示もできる.更に,この経過時間を常時算出して何かの基準時間と比較してやる毎にタイマーアラーム機能も簡単に実装できる.複数の時間を計りたいとか,複数のアラーム機能とも組み合わせてゆきたい等,個別のタイマや時間計数の要求が出ても,それに対応した変数を設け,割り込み外のループで頻繁に引き算が起こるだけで,事実上タイマ機能に数の制限は無くなる.一見複雑に見えるこの,”時間差計算方式”で実装してやるほうが融通が利く.それ程PICは十分速い.
と,いうわけで,”時間差計算”ファンクションで準備するのは以下とした.
【主役たち(変数)】
☆現在時刻(nowSec.nowSubSec)
[nowSecH] [nowSecL].[nowSubSecH] [nowSubSecL]
☆開始時刻(startSec.startSubSec)
[startSecH] [startSecL].[startSubSecH ] [startSubSecL]
☆経過時間(passwdTimeSec.passedTimeSubSec)
[passedTimeSecH] [passedTimeSecL].[passedTimeSubSecH] [passedTimeSubSecL]
☆比較参照時間(referenceTimeSec,referenceTimeSubSec)
[referenceTimeSecH] [referenceTimeSecL].[referenceTimeSubSecH] [referenceTimeSubSecL]
【サブルーチン】
[readWatch] システムのリアルタイムクロック変数から現在時刻(nowSec.nowSubSec)を更新する.メインループの中から毎回呼び出す.
[setStartTime] 現在の時刻を読みスタート時刻(startSec.startSubSec)に格納する.
[calcPassedTime]現在時刻を読み,スタート時刻からの経過時間を算出し,passedTimeSec.passedTimeSubSecに格納する.
[isTimePassed]スタート時刻からの経過時間(passedTimeSec.passedTimeSubSec)が,参照時間(referenceTimeSec.refereceTimeSubSec)を超えたかどうかを判断する.
以下のように使う.
movlw .500/0x100
movwf referenceTimeSubSecH
movlw .500&0xff
movwf referenceTimeSubSecL
movlw .00
movwf referenceTimeSecH
movlw .00
movwf referenceTimeSecL
call isTimePassed
btfsc STATUS,C
bsf mdo_01,6
bsf mdo_01,7
参照時間referenceTimeに00.500秒を入れ,isTimePassedをコールし,スタート時刻から0.5秒経過していれば(Carryがゼロならば)デジタル出力6をONにする.デジタル出力7は常にONする.ソフトが走ると,はじめに出力7のLEDが点灯し,その後0.5秒後に出力6のLEDが点灯する.
うまくいったぞ.ちょっと心配なのは,桁上がり処理だ.全ての時刻・時間変数は2バイトの秒と2バイトの1/1000秒が割り当てられているので,表現できるのは,0.000~65535.999秒までだ.例えば,スタート時刻が65535.000秒だったとすると,1秒後に現在時刻は0.000秒に戻ってしまうから.しかし,すべて同じルールで桁あふれして循環する変数なので,経過時間計算でボローを無視しやることでて正しい時刻差(=時間)になるはずである.0.000~65535.999までの経過時間は正しく算出できるので,そのあとのreferenceTimeとの比較には影響を及ぼさないはずだ.
ともあれ,確認は必要だ.

液晶画面が小さいので,小数点を省き,各変数を表示し,ところどころ表示を止めて見て検証しよう.でも,65536秒って,20時間弱になるので,長丁場だ.
左上は,現在時刻(nowSecを10進数5桁+nowSubSec10進数3桁)を続けて表示している)写真左の64443.228秒ということだから,17時間54分3秒228という意味だ.同様の表記で下段左はstar時刻,下段右の8文字は経過時間を示す.この場合は,
現在:64443.228
START:00016.052
経過:64427.176
ということで確かに現在時刻からSTART時刻を引いたものが経過時間になっている.

これは,現在時刻変数が桁あふれした瞬間の様子.
現在: 00003.326
START: 00016.052
経過: 65523.274
現在時刻は3.326であるが,実際には65536秒+3.326秒が経過している.3.326+65536-16.052=65523.274となり,この状態でも正しく経過時間が算出されていることがわかる.
更に,現在時刻が進み,Start時刻から65536.000を超えてしまった場合,当然経過時間のレジスタも桁あふれしてゼロに戻る.要は,STARTボタンを押した瞬間にもどるだけだ.当然,表示してある数字の計算結果はあっている様に見える.
ちなみに,経過時間が65535.999から0.000に戻る時の瞬間は,前述のLEDも一度初期状態に戻り(LED6が消える)0.5秒後にLED6が再び点灯することも目視ながら確認できた.
一番ややこしい部分が終わって,あーさっぱりした.
「mesure88081129.asm」をダウンロード
「ms88.inc」をダウンロード (こちらは変わっていない)
最近のコメント