「天文屋のためのマイコン入門」プログラム解説
ロータリースイッチのプログラム解説です。
このプログラムをビルドし、書込み、実行すると、ロータリースイッチの値(0~9)が7セグメントLEDに表示されます。スイッチを回すと7セグメントLEDの値も変化します。
前半部分
後半部分
今日は前半部分の解説です。
まず、初期化の部分ですが、ポートAの下位4ビットが今度は入力になりますので、以下のように変更します。
MOVLW B'00101111' ;RA7 RA6 RA4出力、他入力
MOVWF 85h ;TRISA=B'11010000' ポートA入出力セット
1に設定したビットは入力で、0び設定したビットは出力になります。RA7は未接続ですが、未使用のピンはハイインピーダンス状態になるのを避けるため、出力に設定しておいた方が良いでしょう。
初期化の他の部分は前回と同じです。
次に、ロータリースイッチからの入力部分です。
LOOP
MOVF 5h,W ;ポートAをワーキングレジスタに格納
ANDLW B'00001111' ;下位4ビットをマスク
MOVWF 20h ;それを、汎用レジスタに格納
まず、MOVF 5h,Wで、ポートAの状態をワーキングレジスタに入力します。これでワーキングレジスタにはポートAの状態が入りました。
ただ、ポートAのうち、必要なのは下位4ビットで、上位4ビットは何が入っているか分かりません。正確に言えば、調べれば分かります。ただ、いちいち不要なビットのことを考えるのも無駄なので、上位4ビットを強制的に0にしてしまいます。
方法は論理積演算(AND)です。AND演算は、
0とのAND演算は相手が1であろうと0であろうと0になります。
1とのAND演算は相手の状態がそのまま反映されます。つまり相手が1なら1、0なら0です。
つまり、必要なビットは1とのANDをとり、
不要なビットは0とのANDをとります。
そうすると、不要なビットはすべて0になり、必要なビットのみ取り出せます。
ANDLW B'00001111' ;下位4ビットをマスク
このような理由からこのような演算をANDでマスクするといいます。
さて、これで純粋にスイッチの状態がワーキングレジスタに代入されました。次にこの値を汎用レジスタに保存します。
MOVWF 20h ;それを、汎用レジスタに格納
汎用レジスタは、レジスタファイルの後ろの方にあるレジスタで、プログラマがプログラム中に自由に使うことができます。汎用レジスタは20h番地からありますので、一番最初の20h番地のレジスタを使うことにします。(他の番地でもかまいません)
次は、取り込んだスイッチの状態を値に応じて、場合分けしなければなりません。つまり、スイッチが0の場合、1の場合、2の場合、という具合です。
あまり効率的ではありませんが、分かりやすい方法をここで紹介します。
取り込んだ値を、デクリメント(-1)してみます。
DECF 20h,F ;デクリメントする
もし、これが0なら、値は1だったことになります。したがって、0なら、GOTOで1を表示する部分にジャンプするようなプログラムにします。そうするには、0でないならGOTOをスキップする命令を書けば良いことになります。
ところで0でないということはZフラグがセットされないので0ということです。
演算結果が0 ->Zフラグが1
演算結果が0でない -> Zフラグが0
演算の結果が0でないなら、Zフラグが0という逆の状態になるのです。ややこしいですね。ここを注意して、Zフラグは3番地のビット2にありますから、次のような命令になります。
BTFSC 3h,2 ;0でないならGOTOをスキップ
GOTO disp_1 ;1を表示へ
disp_1は7セグメントLEDに1を表示するプログラムを記述している番地を示すラベルです。次回その部分の説明をします。
また、BTFSC命令ですが、次の2つの種類があります。
BTFSC f , b f番地のbビットが0なら(Clear)スキップ
BTFSS f , b f番地のbビットが1なら(Set)スキップ
区別は最後文字でします。最後がCならClearですから、0、
最後がSならSetですから1です。
分かりましたか?
さて、これで1かどうかの判断は終わりましたので、またデクリメントします。今度0なら、最初の値は2だったということになります。これで2を表示する部分にジャンプできます。以下同様に繰り返していき、最後9まで比較し、どれにも当てはまらなければ、0だったということになります。
今日はここまで、次回、後半部分を説明します。
| 固定リンク
コメント