PIC16F88に,ステータスイベントマトリクス駆動ソフトを実装
いよいよメインループを作成して,これまでの要素を組立,陸上計測器に仕上げる.
この手の単体機のメインルーチンは大方条件判断を基にしたシーケンシャル処理になる.
だから,設計に当たっては状態遷移図で表し,実装設計はステータス&イベントマトリクスに従ってイベントドリブンで組むのが楽.
PICだからってこうした実装が不得手とは限らない.PIC16F88には100H単位のバウンダリを跨がぬ範囲で255方向へPC相対ジャンプができる.良く”テーブル引き”に使われる,
addwf PCL,F
命令だ.本ソフトでもctoaで使っている.これを使って,ステータスイベント方式のメインループ処理テンプレートを作ってみよう.
指針として,以下を考える.
・様々な実装への自由度を考え,ステータスイベントマトリクスマシーンは0800H以降に置く.メインループの中で毎回PCLATHを書き換えることにはなるが,他のソフトが混在すると,他のソフトの改造の影響で100Hの協会をずれるようなアドレスズレが起こることはなるべく避けたいから.800H-FFFHまでの広大なPIC16F88のメモリの半分をメインループの中身の記述に使ったって,文句は無いだろう.
・テンプレートの実装においては,メインルーチンからのコーリングシーケンスとリターンのルールを決め打ちにしてgoto文でこれを行う.ソフトを構造化するというと,関数実装にするのが一般的だがなにしろPICのスタックは8レベルしかないのだ.コーリング&リターンシーケンスを統一すればgoto文でも事足りるのなら,スタックは使わないほうが良い.あとは,ラベルの命名規則と構造を守るだけ.
まずは,メインループへの追加.コーリングシーケンスは,StatusEventDriver変数にステータス&イベントコードを入れて,PCLATHをドライバーソフトの記述アドレスに合わせてセットし,goto文で飛ばす.ReturnPointOfSEDラベルは,ステータスイベントコードにあわせたアクションが終了した時にメインルーチンへ戻ってくる箇所を表している.当然戻ってくると言っても,goto文で「往った」のだから,goto文で還って来る.還って来るgoto文の直前には,PCLATHをメインループの記述されている所に合わせてやる必要がある.
movf StopDisplay,W
movwf statusEvent
movlw StatusEventDriver/0x100
movwf PCLATH
goto StatusEventDriver
ReturnPointOfSED
次に,StatusEventDriverの記述だ.メインルーチンからここに飛んでくる.ここでは,StatusEventに合わせて相対ジャンプするためのジャンプポイントへ飛ばす.ジャンプポイントとは,例の,Wレジスタの値に応じたPC相対ジャンプを行う(addwf PCL,W命令が書かれている)箇所だ.ただ,その前に,ジャンプテーブルにあわせたPCLATHにしてやる必要がある.ここでは,A00H番地から書かれているジャンプテーブルエリアに飛ぶことを前提としている.(ジャンプテーブルの名前は,ここではSED0A00Hとした)このジャンプテーブルは,くどい様だが物理アドレスの100Hごとの境界を跨ぐことは許されない.
なお,続くLabelは,statusEvent変数に応じてジャンプした先にあるアクションルーチンからの戻り先である.一度ExitOfSEDに戻って,更にPCLATHをメインループの記述がある0x000-0x7ff用にゼロにしてやった後に,メインループの戻り先にgoto命令で返してやる.
org 0x0800
StatusEventDriver movlw SED0A00H/0x100
movwf PCLATH
movf statusEvent,W
goto SED0A00H
ExitOfSED clrf PCLATH
goto ReturnPointOfSED
続くエリアは,statusEvent変数により相対ジャンプされた先の,アクションルーチンの記述だ.800Hのページに記述しているが,今回は,0A00H以降をジャンプテーブルにしているため,09ffHまでしか記述できない.もしも,ジャンプテーブルの数がそう沢山は要らず,むしろ,ジャンプ先のアクションソフトが複雑でメモリを沢山要すようだったら,ジャンプテーブルを例えば0E00Hに移すなどしてやれば良いことになる.
act0a00_00 movlw 0x30
movwf mdo_01
goto ExitOfSED
act0a00_01 movlw 0x31
movwf mdo_01
goto ExitOfSED
act0a00_02 movlw 0x32
movwf mdo_01
goto ExitOfSED
act0a00_03 movlw 0x33
movwf mdo_01
goto ExitOfSED
act0a00_04
|
act0a00_FC
act0a00_FD
act0a00_FE movwf mdo_01
goto ExitOfSED
ここからが,ジャンプテーブルそのものの記述だ.初めにorg擬似命令でジャンプテーブルの先頭アドレスを定義する.ここでは,0A00Hとした.普通は,0A00Hにジャンプソフト(addwf PCL,F)を書くが,ここではあえて,その0A00Hページの最終アドレス0AFFHにこのジャンプ命令を書いた.こうすると,Wレジスタに格納されているstatusEvent変数の値とジャンプ先変数名のサフィックス,及びそのジャンプ文が書かれている絶対アドレスが揃って気持ちがイイ.例えば,Wレジスタの値がゼロの場合,今相対ジャンプ命令(addwf PCL,F)の飛び先は,(0AFFH+1)+0でA00Hとなるの(PCLへの足し算だから,キャリーはPCHに反映されない)ので0A00Hとなり,そこに書いてあるラベル名は,act0a00_00という,サフィックス部が00となっているラベルである.これは単なる趣味だ.PICとココロを合わせるための.
org 0x0A00
goto act0a00_00
goto act0a00_01
goto act0a00_02
goto act0a00_03
goto act0a00_04
|
goto act0a00_FC
goto act0a00_FD
goto act0a00_FE
org 0x0aff
SED0A00H addwf PCL,F
もちろん,statusEvent(Wレジスタ)の値に0ffHが入ることは許されない.と,いうより,0ffHだったら,自分自身へ永久ジャンプしてしまうので,無限ループ状態になってしまう.そういう使い方が無いとも限らないが....
また,テーブルは必ずオフセット0から始まって0ffh個無ければならないことはない.そのシステムにより必要とされるステータスとイベントの数文あればいいのだ.ステータスが3種類,イベントが4種類で12個でも良いし,ステータスが3ビット,イベントが4ビットの128個でも良い.
もちろん,0100Hのアドレス境界を跨がない制限内で余ったメモリエリアを別のステータスイベントジャンプテーブルとして定義をして,ステータスイベントドライブソフトをネスティングするような構成も実現できる.
ソース作りは秀丸のコピペとマクロと置換で作ったので手間はかからないけど,テーブルの数が多いと,ソースリストがやたらに長くなるのだけが,ちょっと困るかな.だけど,アセンブル&リンク,焼きこみの時間は殆ど変わらない.だけどそこが正直者で愛らしい.
「mesure88081202.asm」をダウンロード
「ms88.inc」をダウンロード (こちらは変わっていない)
本当にすごいな,PICは.


コメント