PIC編
PICで12ビット長の命令体系のソフトにつて学びましょう。
 12ビット長命令のPICは一番見慣れているのICでないでしょうか?
・PIC16F5XX、PIC16F2XX(8ピンDIPタイプ、6ピンフラットタイプ)
などがあります。種類は少ないですが小型の物がありますので省スペースにはバッチリです。
 上記例はほんの一部分ですがこれらのICのソフトについて調べてみましょう。あくまでも参考になればご利用下さい。
命令の説明は14ビットと同じです。但し12ビット長用に若干変更してある部分もあるよ!
■ PICの命令を覗いてみよう! ■
  それでは実際にPICの命令はどんな命令があるのかを見てみましょう。PIC16F84の命令を覗いてみましょう。
命 令 オペコード 命令の説明 フラグ サイクル
ADDLW  k −命令無し−  W + k の結果をWへ格納 C,DC,Z
ADDWF  f、d 0001-11df ffff  W + f の結果をWかfへ格納 C,DC,Z
ANDLW  k 1110-kkkk kkkk  W and k の結果をWへ格納
ANDWF  f、d 0001-01df ffff  W and f の結果をWかfへ格納
BCF    f、b 0100-bbbf ffff  f の b ビット目を0にする
BSF    f、b 0101-bbbf ffff  f の b ビット目を1にする
BTFSC  f、d 0110-bbbf ffff  f の b ビット目が0だったら次の命令をスキップ 1(2)
BTFSS  f、d 0111-bbbf ffff  f の b ビット目が1だったら次の命令をスキップ 1(2)
CLRF   f 0000-011f ffff  f を0にクリアする
CLRW 0000-0100 0000  W を0にクリアする
COMF   f、d 0010-01df ffff  f の反転結果をWかfへ格納
DECF   f、d 0000-11df ffff  f −1 の結果をWかfへ格納
DECFSZ f、d 0010-11df ffff  f −1 の結果をWかfへ格納し結果がゼロで次の命令をスキップ
INCF   f、d 0010-10df ffff  f +1 の結果をWかfへ格納
INCFSZ f、d 0011-11df ffff  f +1 の結果をWかfへ格納し結果がゼロで次の命令をスキップ 1(2)
IORLW  k 1101-kkkk kkkk  W or k  の結果をWへ格納
IORWF  f、d 0001-00df ffff  W or f の結果をWかfへ格納
MOVF   f、d 0010-00df ffff  f の内容をWかfへ格納
MOVLW  k 1100-kkkk kkkk  k を W へ格納
MOVWF  f 0000-001f ffff  W の内容をfへ格納
NOP 0000-0000 0000  1サイクル使い何もしない
RLF    f、d 0011-01df ffff  1ビット左シフトの結果をWかfへ格納
RRF    f、d 0011-01df ffff  1ビット右シフトの結果をWかfへ格納
SUBLW  k −命令無し−  k − W  の結果をWへ格納(引く方向に注意) C,DC,Z
SUBWF  f、d 0000-10df ffff  f − W  の結果をWかfへ格納(引く方向に注意) C,DC,Z
SWAPF  f、d 0011-10df ffff  f 上位と下位の内容を入替後Wかfへ格納
OPTION 0000-0000 0010  Wの内容を「OPTION」レジスタへ格納 (12ビット長専用)
TRIS   f 0000-0000 kkkk  Wの内容を「TRIS f」レジスタへ格納 (12ビット長専用)
XORLW  k 1111-kkkk kkkk  W xor k  の結果をWへ格納
XORWF  f、d 0001-10df ffff  W xor f の結果をWかfへ格納
CALL   k 1110-kkkk kkkk  サブルーチン「k」へジャンプ
GOTO   k 101k-kkkk kkkk  「k」へ無条件ジャンプ
RETFIE −命令無し−  割り込み許可で戻る
RETLW  k 01xx-kkkk kkkk  W に k を格納して戻る
RETURN −命令無し−  通常のサブルーチンから戻る
CLRWDT 0000-0100 0100  WDT(ウォッチドックタイマ)をクリアする
SLEEP 0000-0110 0011  スリープモードにする
■ PICの命令が12ビット長! ■
 ここではオペコード(機械語)について少し調べてみましょう。12ビット長のオペコードを持つPICって何でしょうね、一体12ビット長の命令とは何でしょうか?この辺を見てみましょう。
 まず12ビットとは下記の「0、c、d」の並びが12個ありますがこれ自体が12ビット長で個々の枠には「0」か「1」しか入りません2進数と言うことです。つまり12ビット長とは2進数で表示した時のビットの長さ(枠の数)をいいます。そのしくみを調べてみましょう。

◆上2ビットで4種類に分離し「00」をチェック
0 0 c c c c d f f f f f

・「cccc」 → 命令コードが入るが主に「XXXX f、d」の命令に使われている。「0111」の場合は「ADDWF」が該当する。
      その他に単独命令(メモリアクセスがない命令)が空いているところにちりばめられている。(NOP、RETURN、SLEEPなど)
・「d」 → f・Wの切り換えで
・「f ffff」 → RAM(ファイルレジスタ)のアドレスが入る。
      これを見ても解るとおり「f」は7ビット長なので直接アクセス出来るのは00H〜7FHとなりそれ以外はバンク切り替えで行う。

◆上2ビットで4種類に分離し「01」をチェック
0 1 c c b b b f f f f f

 ビット系の命令である4種類に当てられる。
・「cc」 → 命令コードで4種類しかない「00」=BCF、「01」=BSF、「10」=BTFSC、「11」=BTFSSと割り当てられる。
・「bbb」 → 対応するビットの値が収納される、「000」=0ビット目〜「111」=7ビット目となる。
・「f ffff」→ 上記と同じRAMのアドレスとなる。(後省略)

◆上2ビットで4種類に分離「10」をチェック
1 0 c s k k k k k k k k

・「c」 → 命令コードで「0」=CALLかRETLW、「1」=GOTOのジャンプ系で2種類に割り当てられる。
・「s kkkk kkkk」 → 「GOTO」の場合ジャンプさせたいアドレスがここに収納。これも000H番地〜1FFH番地までの範囲となります。
・「0 kkkk kkkk」 → 「CALL」でジャンプさせたいアドレスがここに収納。これも000H番地〜0FFH番地までの範囲となります。
・「1 kkkk kkkk」 → 「RETLW」で戻り値に00H〜0FFHまでの範囲が設定可能です。

◆上2ビットで4種類に分離し「11」をチェック
1 1 c c k k k k k k k k

・「cc」 → 命令コードで残りの命令が指定され「xxxLW」命令が主です。「1001」=ANDLWに割り当てられる。
・「kkkk kkkk」 → 8ビット長の値がここに収納されます。「00H」=0〜「1111H」=255の値を設定出来るよ。

●上記がマシン語(機械語)の取り決めです。自分でもアセンブル(ソースコードをマシン語へ変換する)することが出来ますがチョット大変ですのでマイクロチップ社からの無料アセンブラなどを使うと便利でしょう。14ビット長でのマシン語は14個の組合せで作られていますので、これが小規模PICの12ビット長となると2ビット減りますので命令も当然少なくなります、そのため14ビット長のソースを12ビット長のソースに変換するにはチョット工夫が必要ですよ!
■ PICの命令ないか簡単だ! ■
 上の表でも見ましたが命令はそんなに多くないので覚えるのも楽ですが少ないのも大変な事もあります。
実際の動きを調べてみましょう。例題は実際にプルグラムを作って実行したように見てみましょう。
 1.wレジスタとメモリー、フラグが変化した場合にはピンク色の表示にしました。
 2.Z,D,Cはフラグを意味しZ,DC(Dと記載),Cの順番で表示され変化は次のようにします。
   「0」に変化は”0”、「1」に変化は”Z,D,C”の立つフラグ、影響しない場合は=”-”、現在状態が不明=”x”
 3.RAM(ファイルメモリ)は2種類で「RAM_A」と「RAM_B」を仮に作りました。
   「--」は影響されない時に使います。
 4.枠内の色について「ピンク色」は変化、影響する可能性のある部分、「灰色」は命令をスキップする場合です。
 5.数字の表記は通常16進で記入し01H=01H、0FFH=FFHとします「H」がない場合は10進数扱いです。
■ PICの基本(MOV)命令! ■
◆ MOVLW k 動作:  k→(w)
 「MOVLW」は「MOV命令」です。「f」のRAMアドレスの内容を「W」へ書き込みます。
 この命令はWのみでRAMは指定できません。
◆基本例題1
W= 1FH
W RAM_A RAM_B Z,D,C ◆基本例題2
W= 100(10進)
W RAM_A RAM_B Z,D,C
-- -- -- x,x,x -- -- -- x,x,x
MOVLW 1FH 1FH -- -- -,-,- MOVLW 100 64H -- -- -,-,-
◆応用例題1 W RAM_A RAM_B フラグ 解 説(「(RAM_A= 25H」の場合)
-- -- -- x,x,x 初期状態
MOVLW 25H 25H -- -- 0,-,- Wの内容と25Hを論理和しWに格納
MOVWF RAM_A 25H 25H -- 0,-,- Wの内容をRAM_Aに格納
◆ MOVF f,d 動作:  (f)→(destination)
 「MOVLW」は「MOV命令」です。「K」で指定された値を「W」へ書き込みます。
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
◆基本例題1
W = RAM_A
W RAM_A RAM_B Z,D,C ◆基本例題2
RAM_A = RAM_A
W RAM_A RAM_B Z,D,C
-- 1FH -- x,x,x -- 00 -- x,x,x
MOVF RAM_A,W 1FH 1FH -- 0,-,- MOVF RAM_A,F -- 00 -- Z,-,-
◆応用例題1 W RAM_A RAM_B フラグ 解 説(「(RAM_A= RAM_B」の場合)
-- 5AH -- x,x,x 初期状態
MOVF RAM_A,W 5AH 5AH -- 0,-,- RAM_Aの内容をWに格納
MOVWF RAM_B 5AH 5AH 5AH 0,-,- Wの内容をRAM_Bに格納
◆ MOVWF f 動作:  (w)→(f)
 「MOVWF」は「MOV命令」です。「W」の内容をfで指定されたアドレス「f」へ書き込みます。
 WからRAMへの移動専用です。
◆基本例題1
RAM_A = W
W RAM_A RAM_B Z,D,C ◆基本例題2
RAM_B = W
W RAM_A RAM_B Z,D,C
2AH 1FH -- x,x,x 2AH -- 56H x,x,x
MOVWF RAM_A,W 2AH 2AH -- -,-,- MOVWF RAM_B,F 2AH -- 2AH -,-,-
◆応用例題1 W RAM_A RAM_B フラグ 解 説(「(RAM_A= RAM_B」の場合)
-- 5AH -- x,x,x 初期状態
MOVF RAM_A,W 5AH 5AH -- 0,-,- RAM_Aの内容をWに格納
MOVWF RAM_B 5AH 5AH 5AH 0,-,- Wの内容をRAM_Bに格納
◆ CLRF f 動作:00H → (f)
 「CLRF」は「クリア命令」です。「f」のRAMアドレスの内容へ「0」を書き込みます。
 この命令はRAMへの指定です、Wは別の命令があります。
◆基本例題1
RAM_A =00H
W RAM_A RAM_B Z,D,C ◆基本例題2
RAM_B =00H
W RAM_A RAM_B Z,D,C
-- 15H -- x,x,x -- -- 15H x,x,x
CLRF RAM_A -- 00H -- Z,-,- CLRF RAM_B -- -- 00H Z,-,-
◆ CLRW  動作:00H → W
 「CLRW」は「クリア命令」です。「W」の内容へ「0」を書き込みます。
 この命令はWレジスタ専用ですRAMへのは出来ません、RAM用は別の命令があります。
◆基本例題1
W =00H
W RAM_A RAM_B Z,D,C ◆基本例題2
W RAM_A RAM_B Z,D,C
15H -- -- x,x,x -- -- -- x,x,x
CLRW 00H -- -- Z,-,- -- -- -- -,-,-
◆ SWAPF f、d 動作:f<0:3> → d<4:7> & f<4:7> → d<0:3>
 「SWAPF」は「スワップ命令」です。fの下4ビットとdの上4ビットとfの上4ビットとdの下4ビットを交換します。
簡単に言うと上位4ビットと下位4ビットを入れ替えするのです。但し「f」と「d」の間で行われます。
 フラグが影響しない唯一のMOV命令なのでよく使うとした場合は割り込み処理の時にレジスタ保存と復帰のとき使われます。
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
◆基本例題1
W =SAWPF RAM_A
W RAM_A RAM_B Z,D,C ◆基本例題2
RAM_A =SAWPF RAM_A
W RAM_A RAM_B Z,D,C
15H 68H -- x,x,x 15H 68H -- x,x,x
SWAPF RAM_A、W 86H 68H -- -,-,- SWAPF RAM_A、F 15H 86H -- -,-,-
■ PICの加減算命令! ■
◆ ADDLW k 動作:(w)+k→(w)
12ビット長ではこの命令はありません。
◆ ADDWF f、d 動作:(w)+(f)→(destination)
 「ADDWF」は「加算命令」です。Wレジスタの内容と「f」のRAMアドレスの内容を加え「d」へ書き込みます。
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
◆基本例題1
35H =10H + 25H(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題2
35H =10H + 25H(Fの時)
W RAM_A RAM_B Z,D,C
10H 25H -- x,x,x 10H 25H -- x,x,x
ADDWF RAM_A,W 35H 25H -- 0,0,0 ADDWF RAM_A,F 10H 35H -- 0,0,0
◆基本例題3
10H=08H+08H(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題4
0FH =08H + 07H(Wの時)
W RAM_A RAM_B Z,D,C
08H 08H -- x,x,x 07H 08H -- x,x,x
ADDWF RAM_A,W 10H 08H -- 0,D,0 ADDWF RAM_A,W 0FH 08H -- 0,0,0
◆基本例題5
8EH =0A5H + 0E9H(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題6
00H =01H + 0FFH(Wの時)
W RAM_A RAM_B Z,D,C
A5H E9H -- x,x,x 01H FFH -- x,x,x
ADDWF RAM_A,W 8EH E9H -- 0,0,C ADDWF RAM_A,W 00H FFH -- Z,D,C
◆応用例題1 W RAM_A RAM_B Z,D,C 解 説(「(RAM_A=RAM_A+RAM_B」の場合)
-- 25H 65H x,x,x 初期状態
MOVF RAM_A,W 25H 25H 65H 0,-,- RAM_Aの内容をwに格納
ADDWF RAM_B,W 8AH 25H 65H 0,0,0 Wの内容とRAM_Bの内容を加算しWに格納
MOVWF RAM_A 8AH 8AH 65H 0,0,0 Wの内容をRAM_Aに格納
◆応用例題2 W RAM_A RAM_B Z,D,C 解 説(上記を一工夫、1命令減少)
-- 25H 65H x,x,x 初期状態
MOVF RAM_B,W 65H 25H 65H 0,-,- RAM_Bの内容をWに格納
ADDWF RAM_A,F 65H 8AH 65H 0,0,0 W(RAM_B)の内容とRAM_Aの内容を加算しRAM_Bに格納
◆ SUBLW k 動作:k−(w)→(w) ※ADDと違い引く方向がが逆だよ!
12ビット長ではこの命令はありません。
◆ SUBWF f、d 動作:(f)−(w)→(destination) ※ADDと違い引く方向がが逆だよ!
 「SUBWF」は「加算命令」です。「f」のRAMアドレスの内容からWレジスタの内容を引いて「d」へ書き込みます。
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
◆基本例題1
15H =25H - 10H(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題2
15H =25H - 10H(Fの時)
W RAM_A RAM_B Z,D,C
10H 25H -- x,x,x 10H 25H -- x,x,x
SUBWF RAM_A,W 15H 25H -- 0,D,C SUBWF RAM_A,F 10H 15H -- 0,D,C
◆基本例題3
00H=08H - 08H(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題4
0FH =10H - 01H(Wの時)
W RAM_A RAM_B Z,D,C
08H 08H -- x,x,x 01H 10H -- x,x,x
SUBWF RAM_A,W 00H 08H -- Z,D,C SUBWF RAM_A,W 0FH 10H -- 0,D,0
◆基本例題5
FFH =00H - 01H(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題6
00H =01H - 01H(Wの時)
W RAM_A RAM_B Z,D,C
00H 01H -- x,x,x 01H 01H -- x,x,x
SUBWF RAM_A,W FFH 01H -- 0,0,0 SUBWF RAM_A,W 00H 01H -- Z,D,C
◆応用例題1 W RAM_A RAM_B Z,D,C 解 説(「(RAM_A=RAM_B - RAM_A」の場合)
-- 1AH 65H x,x,x 初期状態
MOVF RAM_A,W 25H 10H 65H 0,-,- RAM_Aの内容をwに格納
SUBWF RAM_B,W 4BH 10H 65H 0,D,C RAM_Bの内容とWの内容とを引き算しWに格納
MOVWF RAM_A 4BH 4BH 65H 0,D,C Wの内容をRAM_Aに格納
◆応用例題2 W RAM_A RAM_B フラグ 解 説(「(RAM_A = RAM_A - 25H」の場合)
※引き算のみ引く方向があるためSUBLWが使えない
-- 3AH -- 初期状態
MOVLW 25H 25H 3AH -- 0,x,x 定数の25HをWに格納
SUBWF RAM_A,F 25H 15H -- 0,D,C RAM_Aの内容と25H(W)の内容とを引き算しRAM_Aに格納
◆ INCF f、d 動作:(f) +1 →(destination)
 「INCF」は「1つ加算(Increment)命令」です。「f」のRAMアドレスの内容を1つ加算して「d」へ書き込みます。
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
 この命令の兄弟で条件機能が付いた「INCFSZ」があります。
◆基本例題1
16H =15H  +01H(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題2
10H= 0FH  +01H(Fの時)
W RAM_A RAM_B Z,D,C
0FH 15H -- x,x,x 15H 0FH -- x,x,x
INCF RAM_A,W 16H 15H -- 0,-,- INCF RAM_A,F 15H 10H -- 0,-,-
◆基本例題3
00H=FFH +01H(Fの時)
W RAM_A RAM_B Z,D,C ◆基本例題4
5AH =59H +01H(Fの時)
W RAM_A RAM_B Z,D,C
5AH FFH -- x,x,x 01H 59H -- x,x,x
INCF RAM_A,f 5AH 00H -- Z,-,- INCF RAM_A,f 01H 5AH -- 0,-,-
◆ DECF f、d 動作:(f) −1 →(destination)
 「DECF」は「1つ減算(Decrement)命令」です。「f」のRAMアドレスの内容を1つ減算して「d」へ書き込みます。
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
 この命令の兄弟で条件機能が付いた「DECFSZ」があります。
◆基本例題1
14H =15H  -01H(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題2
0EH= 0FH  -01H(Fの時)
W RAM_A RAM_B Z,D,C
0FH 15H -- x,x,x 15H 0FH -- x,x,x
DECF RAM_A,W 14H 15H -- 0,-,- DECF RAM_A,F 15H 0EH -- 0,-,-
◆基本例題3
00H=01H -01H(Fの時)
W RAM_A RAM_B Z,D,C ◆基本例題4
5FH =60H -01H(Fの時)
W RAM_A RAM_B Z,D,C
5AH 01H -- x,x,x 01H 60H -- x,x,x
DECF RAM_A,f 5AH 00H -- Z,-,- DECF RAM_A,f 01H 5FH -- 0,-,-
例題:DECFを使った10回ループプログラムです。ループ数は2行目の「10」を変えることでループ数を変えることが出来、ループ数字の後に「H」を付けていないので10進数として扱われます。「10」の場合は16進では0AHで10進で最大255までです。
 また「NOP」の行とそれ以降に新たにプルグラムを組むことが出来ます。(現在はタイマープログラムですかね)
例題1:1回目のループの時の動きで実際にはRAM_Aの内容を1つ減算して0になるまで「LOOP」から「GOTO LOOP」まで繰り返す
例題2:最終10回目の時のプログラムの流れです。結果的にゼロ・フラグが立つのでGOTO LOOP文がスキップされます。
◆応用例題1 W RAM_A RAM_B Z,D,C 解 説(10回ループを作る、最初の1回目)
xx xx -- x,x,x 初期状態
MOVLW 10 0AH xx -- -,-,- Wに10(10進数)を設定する
MOVWF RAM_A 0AH 0AH -- -,-,- Wの内容をRAM_Aに格納
LOOP: NOP -- 0AH -- -,-,- ラベルを「LOOP」とする。NOPは何もせず1サイクル消費
DECF RAM_A,F 0AH 09H -- 0,-,- RAM_Aの値を−1してRAM_Aへ(1回目は9で0まで繰り返す)
BTFSS STATUS,Z 0AH -- -- -,-,- STATUSのZフラグが立っているかチェック(今回はは0)
GOTO LOOP 0AH -- -- -,-,- RAM_Aが「0」になるまでLOOPにジャンプ
◆応用例題2 W RAM_A RAM_B Z,D,C 解 説(10回ループを作る、最後の1回)
LOOP: NOP -- 01H -- -,-,- ラベルを「LOOP」とする。NOPは何もせず1サイクル消費
DECF RAM_A,F 0AH 00H -- Z,-,- RAM_Aの値を−1してRAM_Aへ(10回目は0で終了)
BTFSS STATUS,Z 0AH -- -- -,-,- STATUSのZフラグが立っているかチェック(今回は1)
GOTO LOOP -- -- -- -,-,- RAM_Aが「0」になったのでこの命令はスキップで次の行へ
■ PICの論理演算命令! ■
◆ ANDLW k 動作:(w) and k→(w)
 「ANDLW」は「AND命令」です。Wレジスタの内容と「K」で指定された値を論理積(AND)して「W」へ書き込みます。
 この命令はWのみでRAMは指定できません。
◆基本例題1
05H =15H and 0FH
W RAM_A RAM_B Z,D,C ◆基本例題2
00H =52H and 01H
W RAM_A RAM_B Z,D,C
15H -- -- x,x,x 52H -- -- x,x,x
ADDLW 0FH 05H -- -- 0,0,0 ADDLW 01H 00H -- -- Z,0,0
◆応用例題1 W RAM_A RAM_B フラグ 解 説(「(RAM_A=RAM_A and 25H」の場合)
-- 3AH -- x,x,x 初期状態
MOVF RAM_A,W 3AH 3AH -- 0,-,- RAM_Aの内容をWに格納
ADDLW 25H 20H 3AH -- 0,0,0 Wの内容と25Hを論理積しWに格納
MOVWF RAM_A 20H 20H -- -,-,- Wの内容をRAM_Aに格納
◆ ANDWF f、d 動作:(w) and (f)→(destination)
 「ANDWF」は「論理積(AND)命令」です。wレジスタの内容と「f」のRAMアドレスの内容を論理積(AND)して「d」へ書き込みます。
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
◆基本例題1
35H=15H and 0FH(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題2
35H=15H and 0FH(Fの時)
W RAM_A RAM_B Z,D,C
15H 0FH -- x,x,x 15H 0FH -- x,x,x
ANDWF RAM_A,W 05H 0FH -- 0,-,- ANDWF RAM_A,F 15H 05H -- 0,-,-
◆基本例題3
00H=5AH and 01H(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題4
01H=5BH and 01H(Wの時)
W RAM_A RAM_B Z,D,C
5AH 01H -- x,x,x 5BH 01H -- x,x,x
ANDWF RAM_A,W 00H 00H -- Z,0,0 ANDWF RAM_A,W 01H 01H -- 0,-,-
◆応用例題1 W RAM_A RAM_B Z,D,C 解 説(「(RAM_A=RAM_A and RAM_B」の場合)
-- 25H 0FH x,x,x 初期状態
MOVF RAM_A,W 25H 25H 0FH 0,-,- RAM_Aの内容をwに格納
ANDWF RAM_B,W 05H 25H 0FH 0,-,- Wの内容とRAM_Bの内容を論理積しWに格納
MOVWF RAM_A 05H 05H 0FH 0,-,- Wの内容をRAM_Aに格納
◆応用例題2 W RAM_A RAM_B Z,D,C 解 説(上記「RAM_A=RAM_A and RAM_B」を一工夫、1命令減少)
-- 25H 0FH x,x,x 初期状態
MOVF RAM_B,W 0FH 25H 0FH 0,-,- RAM_Bの内容をWに格納
ANDWF RAM_A,F 0FH 05H 0FH 0,-,- W(RAM_B)の内容とRAM_Aの内容を論理積しRAM_Bに格納
◆応用例題3 W RAM_A RAM_B Z,D,C 解 説(上記のRAM_Aの値を変えて)
-- 20H 0FH x,x,x 初期状態(I/Oポートのマスクに使います)
MOVF RAM_B,W 0FH 20H 0FH 0,-,- RAM_Bの内容をWに格納
ANDWF RAM_A,F 0FH 00H 0FH Z,-,- W(RAM_B)とRAM_Aを論理積しRAM_Bへ、結果0の為ゼロフラグ1
◆ IORLW k 動作:(w) or k→(w)
 「IORLW」は「OR命令」です。Wレジスタの内容と「K」で指定された値を論理和(OR)して「W」へ書き込みます。
 この命令はWのみでRAMは指定できません。
◆基本例題1
1FH=15H or 0FH
W RAM_A RAM_B Z,D,C ◆基本例題2
53H=52H or 01H
W RAM_A RAM_B Z,D,C
15H -- -- x,x,x 52H -- -- x,x,x
IORLW 0FH 1FH -- -- 0,-,- IORLW 01H 53H -- -- 0,-,-
◆応用例題1 W RAM_A RAM_B フラグ 解 説(「(RAM_A=RAM_A+25H」の場合)
-- 3AH -- x,x,x 初期状態
MOVF RAM_A,W 3AH 3AH -- 0,-,- RAM_Aの内容をWに格納
IORLW 25H 3FH 3AH -- 0,-,- Wの内容と25Hを論理和しWに格納
MOVWF RAM_A 3FH 3FH -- 0,-,- Wの内容をRAM_Aに格納
◆ IORWF f、d 動作:(w) or (f)→(destination)
 「IORWF」は「論理w和(OR)命令」です。wレジスタの内容と「f」のRAMアドレスの内容を論理和(OR)して「d」へ書き込みます。
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
◆基本例題1
1FH=15H or 0FH(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題2
1FH=15H or 0FH(Fの時)
W RAM_A RAM_B Z,D,C
15H 0FH -- x,x,x 15H 0FH -- x,x,x
IORWF RAM_A,W 1FH 0FH -- 0,-,- IORWF RAM_A,F 15H 1FH -- 0,-,-
◆基本例題3
5BH=5AH or 01H(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題4
5FH=5BH or 04H(Wの時)
W RAM_A RAM_B Z,D,C
5AH 01H -- x,x,x 5BH 04H -- x,x,x
IORWF RAM_A,W 5BH 00H -- 0,-,- IORWF RAM_A,W 5FH 04H -- 0,-,-
◆応用例題1 W RAM_A RAM_B Z,D,C 解 説(「(RAM_A=RAM_A and RAM_B」の場合)
-- 25H 0FH x,x,x 初期状態
MOVF RAM_A,W 25H 25H 0FH 0,-,- RAM_Aの内容をwに格納
IORWF RAM_B,W 2FH 25H 0FH 0,-,- Wの内容とRAM_Bの内容を加算しWに格納
MOVWF RAM_A 2FH 2FH 0FH -,-,- Wの内容をRAM_Aに格納
◆応用例題2 W RAM_A RAM_B Z,D,C 解 説(上記「RAM_A=RAM_A and RAM_B」を一工夫、1命令減少)
-- 25H 0FH x,x,x 初期状態
MOVF RAM_B,W 0FH 25H 0FH 0,-,- RAM_Bの内容をWに格納
IORWF RAM_A,F 0FH 2FH 0FH 0,-,- W(RAM_B)の内容とRAM_Aの内容を加算しRAM_Bに格納
◆ XORLW k 動作:(w) xor k→(w)
 「XORLW」は「XOR命令」です。Wレジスタの内容と「K」で指定された値を排他的論理和(XOR)して「W」へ書き込みます。
排他的論理和って!:これはお互いのビットが違う時だけ「1」となり同じ時は「0」となります。
 この命令はWのみでRAMは指定できません。
◆基本例題1
1FH=15H xor 0FH
W RAM_A RAM_B Z,D,C ◆基本例題2
53H=52H xor 01H
W RAM_A RAM_B Z,D,C
15H -- -- x,x,x 52H -- -- x,x,x
XORLW 0FH 1AH -- -- 0,-,- XORLW 0FFH ADH -- -- 0,-,-
◆応用例題1 W RAM_A RAM_B フラグ 解 説(「(RAM_A=RAM_A xor 25H」の場合)
-- 3AH -- x,x,x 初期状態
MOVF RAM_A,W 25H 3AH -- 0,-,- RAM_Aの内容をWに格納
XORLW 25H 3FH 3AH -- 0,-,- Wの内容と25Hを排他的論理和しWに格納
MOVWF RAM_A 3FH 3FH -- 0,-,- Wの内容をRAM_Aに格納
◆ XORWF f、d 動作:(w) xor (f)→(destination)
 「XORWF」は「排他的論理和(XOR)命令」です。wレジスタの内容と「f」のRAMアドレスの内容を排他的論理和(XOR)して「d」へ書き込みます。
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
◆基本例題1
1AH=15H xor 0FH(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題2
1AH=15H xor 0FH(Fの時)
W RAM_A RAM_B Z,D,C
15H 0FH -- x,x,x 15H 0FH -- x,x,x
XORWF RAM_A,W 1AH 0FH -- 0,-,- XORWF RAM_A,F 15H 1AH -- 0,-,-
◆基本例題3
00H=FFH xor 0FFH(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題4
5FH=5BH xor 04H(Wの時)
W RAM_A RAM_B Z,D,C
FFH FFH -- x,x,x 5BH 04H -- x,x,x
XORWF RAM_A,W 00H 00H -- Z,-,- XORWF RAM_A,W 5FH 04H -- 0,-,-
◆応用例題1 W RAM_A RAM_B Z,D,C 解 説(「(RAM_A=RAM_A xor RAM_B」の場合)
-- 25H 0FH x,x,x 初期状態
MOVF RAM_A,W 25H 25H 0FH 0,-,- RAM_Aの内容をwに格納
XORWF RAM_B,W 2AH 25H 0FH 0,-,- Wの内容とRAM_Bの内容を加算しWに格納
MOVWF RAM_A 2AH 2AH 0FH -,-,- Wの内容をRAM_Aに格納
◆応用例題2 W RAM_A RAM_B Z,D,C 解 説(上記を一工夫、1命令減少)
-- 25H 0FH x,x,x 初期状態
MOVF RAM_B,W 0FH 25H 0FH 0,-,- RAM_Bの内容をWに格納
XORWF RAM_A,F 0FH 2AH 0FH 0,-,- W(RAM_B)の内容とRAM_Aの内容を加算しRAM_Bに格納
◆ COMF f、d 動作: invert (f)→(destination)
 「COMF」は「反転(invert)命令」です。「f」のRAMアドレスの内容を反転(invert)して「d」へ書き込みます。
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
 反転とはビットが1の時は0になりビットが0の時は1となる。(詳細は下記例題参照)
◆基本例題1
invert 15H→EAH(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題2
invert 15H→EAH(Fの時)
W RAM_A RAM_B Z,D,C
15H 15H -- x,x,x 15H 15H -- x,x,x
COMF RAM_A,W EAH 15H -- 0,-,- COMF RAM_A,F 15H EAH -- 0,-,-
◆基本例題3
invert FFH→EAH(Fの時)
W RAM_A RAM_B Z,D,C ◆基本例題4
invert 0FH→F0H(Fの時)
W RAM_A RAM_B Z,D,C
5AH FFH -- x,x,x 5BH 0FH -- x,x,x
COMF RAM_A,F 5AH 00H -- Z,-,- COMF RAM_A,F 5BH F0H -- 0,-,-
■ PICのシフト命令! ■
◆ RLF f、b 動作:f<n> → d<n+1>、f<7> → C、C → d<0>
 「RLF」は「左シフト命令」です。キャリを含めて「f」の内容を1ビット上位側にずらし「d」に格納する。ちょうど「RRF」の反対動作
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
◆基本例題1 W RAM_A RAM_B Z,D,C ◆基本例題2 W RAM_A RAM_B Z,D,C
-- 01H -- x,x,0 -- 01H -- x,x,0
RLF RAM_A,W 02H 01H -- -,-,0 RLF RAM_A,F -- 02H -- -,-,0
◆基本例題3 W RAM_A RAM_B Z,D,C ◆基本例題4 W RAM_A RAM_B Z,D,C
-- 01H -- x,x,C -- 81H -- x,x,C
RLF RAM_A,F -- 03H -- -,-,0 RLF RAM_A,F -- 03H -- -,-,C
◆基本例題5 W RAM_A RAM_B Z,D,C ◆基本例題6 W RAM_A RAM_B Z,D,C
-- 80H -- x,x,0 -- 55H -- x,x,0
RLF RAM_A,F -- 00H -- -,-,C RLF RAM_A,F -- AAH -- -,-,0
◆応用例題1 W RAM_A RAM_B Z,D,C 解 説(RAM_Aをキャリ含めずにグッルと2回シフト)
-- C5H -- x,x,0 初期状態
RLF RAM_A,W 8AH C5H -- -,-,C まずはキャリフラグを設定(7ビット→C)
RLF RAM_A,F 8AH 8BH -- -,-,C そしてキャリを含めてシフト(7ビット→1ビット目へ)
RLF RAM_A,W 17H 8BH -- -,-,C まずはキャリフラグを設定(7ビット→C)
RLF RAM_A,F 17H 17H -- -,-,C そのままシフト(C5Hを2回左シフトで17Hです)
◆応用例題2 W RAM_A RAM_B Z,D,C 解 説(RAM_Aを8倍)
-- 03H -- x,x,C 初期状態(03H)
BCF STATUS,C -- 03H -- -,-,0 まずはキャリフラグをクリア(上4ビットは立っていないと想定)
RLF RAM_A,F -- 06H -- -,-,0 そしてキャリを含めてシフト(X2倍)
RLF RAM_A,F -- 0CH -- -,-,C そしてキャリを含めてシフト(X4倍)
RLF RAM_A,F -- 18H -- -,-,C そしてキャリを含めてシフト(X8倍)3x8=24(18H)
◆ RRF f、b 動作:f<n> → d<n-1>、f<0> → C、C → d<7>
 「RRF」は「右シフト命令」です。キャリを含めて「f」の内容を1ビット下位側にずらし「d」に格納する。ちょうど「RLF」の反対動作
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
◆基本例題1 W RAM_A RAM_B Z,D,C ◆基本例題2 W RAM_A RAM_B Z,D,C
-- 80H -- x,x,0 -- 80H -- x,x,0
RRF RAM_A,W 40H 80H -- -,-,0 RRF RAM_A,F -- 40H -- -,-,0
◆基本例題3 W RAM_A RAM_B Z,D,C ◆基本例題4 W RAM_A RAM_B Z,D,C
-- 80H -- x,x,C -- 81H -- x,x,C
RRF RAM_A,F -- C0H -- -,-,0 RRF RAM_A,F -- C0H -- -,-,C
◆基本例題5 W RAM_A RAM_B Z,D,C ◆基本例題6 W RAM_A RAM_B Z,D,C
-- 01H -- x,x,0 -- AAH -- x,x,0
RRF RAM_A,F -- 00H -- -,-,C RRF RAM_A,F -- 55H -- -,-,0
◆応用例題1 W RAM_A RAM_B Z,D,C 解 説(RAM_Aをキャリ含めずにグッルと2回シフト)
-- C5H -- x,x,0 初期状態
RRF RAM_A,W 62H C5H -- -,-,C まずはキャリフラグを設定(0ビット→C)
RRF RAM_A,F 62H E2H -- -,-,C そしてキャリを含めてシフト(0ビット→7ビット目へ)
RRF RAM_A,W F1H E2H -- -,-,0 まずはキャリフラグを設定(0ビット→C)
RRF RAM_A,F F1H 71H -- -,-,0 そのままシフト(C5Hを2回右シフトで71Hです)
■ PICのビット命令! ■
◆ BCF f、b 動作:0 →(f <b>)
 「BCF」は「ビットクリア命令」です。fで指定されたRAMアドレスのbビット目をクリアする。BSFの反対動作です。
 この命令はPICのRAM内であればどこでも対応できる便利な命令だよ!
◆基本例題1
RAM_A ビット4 クリア
W RAM_A RAM_B Z,D,C ◆基本例題2
RAM_B ビット0 クリア
W RAM_A RAM_B Z,D,C
-- FF -- x,x,x -- -- 05 x,x,x
BCF RAM_A,4 -- EF -- -,-,- BCF RAM_B,0 -- -- 04 -,-,-
◆応用例題1 W RAM_A RAM_B Z,D,C 解 説(STATUSのキャリーをクリアしてみましょう)
-- 3AH -- x,x,x 初期状態
BCF STATUS,C 25H 3AH -- -,-,0 キャリーフラグをクリア
◆ BSF f、b 動作:0 →(f <b>)
 「BSF」は「ビットセット命令」です。fで指定されたRAMアドレスのbビット目をセットする。BCFの反対動作です。
 この命令はPICのRAM内であればどこでも対応できる便利な命令だよ!
◆基本例題1
RAM_A ビット4 クリア
W RAM_A RAM_B Z,D,C ◆基本例題2
RAM_B ビット0 クリア
W RAM_A RAM_B Z,D,C
-- EF -- x,x,x -- -- 04 x,x,x
BSF RAM_A,4 -- FF -- -,-,- BSF RAM_B,0 -- -- 05 -,-,-
◆応用例題1 W RAM_A RAM_B Z,D,C 解 説(STATUSのキャリーをセットしてみましょう)
-- 3AH -- x,x,x 初期状態
BCF STATUS,C 25H 3AH -- -,-,C キャリーフラグをセット
■ PICの条件・無条件分岐命令! ■
◆ BTFSC f、b 動作:skip if(f <b>)=0
 「BTFSC」は「条件ジャンプ命令」です。fで指定されたRAMアドレスのbビット目が「1」であれば次の命令を実行する。
 また「0」の時は次の次の命令を実行する。(つまり「0」の時は次の命令をスキップするという事です)
 この命令はPICのRAM内であればどこでも対応でき、しかも唯一の条件命令だよ!
◆応用例題1 W RAM_A RAM_B Z,D,C 解 説(実際のキャリフラグで分岐を見てみましょう)
-- 01H -- x,x,C 初期状態(キャリーフラグが「1」となっていると想定)
BTFSC STATUS,C -- 01H -- -,-,- キャリーフラグを調べて「1」なので次の命令を実行
GOTO LOOP -- 01H -- -,-,- 「LOOP」へジャンプする。
CLRF RAM_A -- -- -- -,-,- RAM_Aを0クリアする。(今回は上でジャンプ下ので動作せず)
◆応用例題2 W RAM_A RAM_B Z,D,C 解 説(実際のキャリフラグで分岐を見てみましょう)
-- 01H -- x,x,0 初期状態(キャリーフラグが「0」となっていると想定)
BTFSC STATUS,C -- 01H -- -,-,- キャリーフラグを調べて「0」なので次の命令をスキップ
GOTO LOOP -- 01H -- -,-,- 「LOOP」へジャンプする。(今回はこの命令はスキップする)
CLRF RAM_A -- 00H -- -,-,- RAM_Aを0クリアする。
◆ BTFSS f、b 動作:skip if(f <b>)=1
 「BTFSS」は「条件ジャンプ命令」です。fで指定されたRAMアドレスのbビット目が「0」であれば次の命令を実行する。
 また「1」の時は次の次の命令を実行する。(つまり「1」の時は次の命令をスキップするという事です)
 この命令はPICのRAM内であればどこでも対応でき、しかも唯一の条件命令だよ!
◆応用例題1 W RAM_A RAM_B Z,D,C 解 説(実際のゼロフラグで分岐を見てみましょう)
-- 01H -- Z,x,x 初期状態(ゼロフラグが「1」となっていると想定)
BTFSS STATUS,Z -- 01H -- Z,-,- ゼロフラグを調べて「1」なので次の命令をスキップ
GOTO LOOP -- -- -- -,-,- 「LOOP」へジャンプする。(今回はこの命令はスキップする)
CLRF RAM_A -- 00H -- Z,-,- RAM_Aを0クリアする。
◆応用例題2 W RAM_A RAM_B Z,D,C 解 説(実際のゼロフラグで分岐を見てみましょう)
-- 01H -- 0,x,x 初期状態(ゼロフラグが「0」となっていると想定)
BTFSS STATUS,Z -- 01H -- 0,-,- ゼロフラグを調べて「0」なので次の命令を実行
GOTO LOOP -- 01H -- 0,-,- 「LOOP」へジャンプする。
CLRF RAM_A -- -- -- -,-,- RAM_Aを0クリアする。(今回は上でジャンプ下ので動作せず)
◆ INCFSZ f、d 動作:(f) +1 →(destination) + skip if (f)=0
 「DECF」は「1つ減算(Decrement)命令」です。「f」のRAMアドレスの内容を1つ減算して「d」へ書き込みます。
 その結果減算した値が「0」になった時のみ次の命令をスキップする。それ以外はスキップしない。そのため値が「0」になるまで繰り返すようなプログラムにはちょうど良い命令です。(上記「DECF」に「BTFSC STATUS、Z」がドッキングした命令だよ
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
◆基本例題1
16H=15H +1(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題2
10H=0FH  +1(Fの時)
W RAM_A RAM_B Z,D,C
0FH 15H -- x,x,x 15H 0FH -- x,x,x
INCFSZ RAM_A,W 16H 15H -- -,-,- INCFSZ RAM_A,F 15H 10H -- -,-,-
GOTO LOOP 16H 15H -- -,-,- GOTO LOOP 15H 10H -- -,-,-
◆基本例題3
00H=FFH +01H(Fの時)
W RAM_A RAM_B Z,D,C ◆基本例題4
60H =5FH +01H(Fの時)
W RAM_A RAM_B Z,D,C
5AH FFH -- x,x,x 01H 5FH -- x,x,x
INCFSZ RAM_A,F 5AH 00H -- -,-,- INCFSZ RAM_A,F 01H 60H -- -,-,-
GOTO LOOP -- -- -- -,-,- GOTO LOOP 01H 60H -- -,-,-
◆ DECFSZ f、d 動作:(f) −1 →(destination) + skip if (f)=0
 「DECF」は「1つ減算(Decrement)命令」です。「f」のRAMアドレスの内容を1つ減算して「d」へ書き込みます。
 その結果減算した値が「0」になった時のみ次の命令をスキップする。それ以外はスキップしない。そのため値が「0」になるまで繰り返すようなプログラムにはちょうど良い命令です。(上記「DECF」に「BTFSC STATUS、Z」がドッキングした命令だよ
 「d」は格納場所を指定しますが「0(w)」でWに格納し「1(f)」であればRAMに格納します。
◆基本例題1
15H -1=14H(Wの時)
W RAM_A RAM_B Z,D,C ◆基本例題2
0FH -1=0EH(Fの時)
W RAM_A RAM_B Z,D,C
0FH 15H -- x,x,x 15H 0FH -- x,x,x
DECFSZ RAM_A,W 14H 15H -- -,-,- DECFSZ RAM_A,F 15H 0EH -- -,-,-
GOTO LOOP 14H 15H -- -,-,- GOTO LOOP 15H 0EH -- -,-,-
◆基本例題3
00H=01H -01H(Fの時)
W RAM_A RAM_B Z,D,C ◆基本例題4
5FH =60H -01H(Fの時)
W RAM_A RAM_B Z,D,C
5AH 01H -- x,x,x 01H 60H -- x,x,x
DECFSZ RAM_A,F 5AH 00H -- -,-,- DECFSZ RAM_A,F 01H 5FH -- -,-,-
GOTO LOOP -- -- -- -,-,- GOTO LOOP 01H 5FH -- -,-,-
例題:上のDECFの10回ループに比べて1行少なくなるのでループ・プログラムに最適です。ループ数は2行目の「10」を変えることでループ数を変えることが出来、ループ数字の後に「H」を付けていないので10進数として扱われます。「10」の場合は16進では0AH
 また「NOP」の行とそれ以降に新たにプルグラムを組むことが出来ます。(現在はタイマープログラムですかね)
◆応用例題1 W RAM_A RAM_B Z,D,C 解 説(10回ループを作る、1回目)
xx xx -- x,x,x 初期状態
MOVLW 10 0AH xx -- -,-,- Wに10(10進数)を設定する
MOVWF RAM_A 0AH 0AH -- -,-,- Wの内容をRAM_Aに格納
LOOP: NOP -- 0AH -- -,-,- ラベルを「LOOP」とする。NOPは何もせず1サイクル消費
DECFSZ RAM_A,F 0AH 09H -- 0,-,- RAM_Aの値を−1してRAM_Aへ(1回目は9で0になるまで繰り返す)
GOTO LOOP 0AH -- -- -,-,- RAM_Aが「0」になるまでLOOPにジャンプ
◆応用例題2 W RAM_A RAM_B Z,D,C 解 説(10回ループを作る、最後の1回)
LOOP: NOP -- 01H -- -,-,- ラベルを「LOOP」とする。NOPは何もせず1サイクル消費
DECFSZ RAM_A,F 0AH 00H -- Z,-,- RAM_Aの値を−1してRAM_Aへ(10回目は0で終了)
GOTO LOOP 0AH -- -- -,-,- RAM_Aが「0」になったのでこの命令はスキップで次の行へ
◆ GOTO k 動作:GOTO k  (K=000H〜1FFH)
 「GOTO」は「ジャンプ命令」です。条件がない無条件ジャンプです、プログラムの終了時や「BTFSC、BTFSS、DECFSZ」命令の後にこのGOTO文を使うことで条件ジャンプにも変化します。。
 GOTO文の多用はプログラムを解りにくくするので最低限に留めましょう。
 飛び先番地ですが「K」には範囲があります。000H〜1FFHの範囲であればそのままジャンプ出来ますがそれ以上に飛ばす場合はバンク切り替えをしてからCALL命令を実行しることになるでしょう。12ビット長のPICでは、あまり大きいプログラムは作らない方がよいでしょう。でも範囲を超えた場合は対策が必要ですので要注意!
◆基本例題1 W RAM_A RAM_B Z,D,C 解 説(CALLについて)
xx 02H -- x,x,x 初期状態
MOVWF RAM_A 02H 02H -- -,-,- Wの内容をRAM_Aに格納
SUBLW 01H 01H 02H -- -,-,- ラベルを「LOOP」とする。NOPは何もせず1サイクル消費
DECFSZ RAM_A,F 0AH 02H -- 0,-,- RAM_Aの値を−1してRAM_Aへ(1回目は9で0になるまで繰り返す)
CALL LEDOUT -- -- -- -,-,- LEDOUTと言うサブルーチンをコールする
GOTO LOOP 0AH -- -- -,-,- RAM_Aが「0」になるまでLOOPにジャンプ
-- -- -- -,-,- メインプログラムがここに入る。(省略)
LEDOUT: -- -- -- -,-,- 呼び出されるサブルーチンのスタート
-- -- -- -,-,- ここからサブルーチンのプログラムが入る。
RETURN -- -- -- -,-,- サブルーチンが終了したら元に戻る。(この例では2行目NOPへ)
■ PICのサブルーチン命令! ■
◆ CALL k 動作:CALL k  (K=000H〜0FFH)
 「CALL」は「サブルーチン・コール命令」です。同じプログラムを何回も使う時やプログラムを見やすくするためプルグラムを小分けして必要な時に呼び出すための使われます。
 GOTO命令と違いCALL命令はサブルーチンを呼び出しスタックポインタに戻り番地を記憶してサブルーチンへジャンプします。その後サブルーチン側の最後で「RETURN」命令を使い先ほどスタックポインタに記憶した戻り番地を読み込み今コールした次の行に戻ると言う特徴があります。但し、CALL命令実行時にスタックポインタに戻り番地を1段使用し「RETURN」で1段戻ると言うしくみになっていますし、その段数は8段(PICにより違う)まで可能です。
 PIC16F84ではスタックポインタが8段まで使用可能ですので注意して下さい。これはサブルーチンの中にサブルーチンを呼ぶのに8回まで使えます。ちなみに割り込みを使用せずに9回サブルーチンを重ねて呼び込むと戻り値は解らず動作が保証されませんのであまり段数を増やさないように作りましょう。但し割り込みもこのスタックポインタに戻り番地を収納しますのでここも注意しましょう。
 飛び先番地ですが「K」には範囲があります。「GOTO」文は000H〜1FFHの範囲ですが「CALL」文は000H〜0FFHまでとさらに範囲が狭まっているので、それ以上に飛ばす場合はバンク切り替えをしてからCALL命令を実行しることになるでしょう。通常サブルーチンを最初の方にまとめておくのも楽でしょう。12ビット長のPICでは、あまり大きいプログラムは作らない方がよいでしょう。でも範囲を超えた場合は対策が必要ですので要注意!

実際に実行する順番は次のようになるよ!
 CALL LEDOUT(1行目) → LEDOUT(4行目) ・・・(5行目)→ RETURN(6行目) → NOP(2行目) と進みます。 
◆基本例題1 W RAM_A RAM_B Z,D,C 解 説(CALLについて)
CALL LEDOUT -- -- -- -,-,- LEDOUTと言うサブルーチンをコールする(LEDOUTへ)
NOP -- -- -- -,-,- キャリーフラグを調べて「1」なので次の命令をスキップ
-- -- -- -,-,- メインプログラムがここに入る。(省略)
LEDOUT: -- -- -- -,-,- 呼び出されるサブルーチンのスタート
-- -- -- -,-,- ここからサブルーチンのプログラムが入る。
RETURN -- -- -- -,-,- サブルーチンが終了したら元に戻る。(この例では2行目NOPへ)
◆ RETURN 動作:RETURN
12ビット長ではこの命令はありません。「RETLW 0」で代用して下さい。
◆ RETFIE 動作:RETFIE
12ビット長ではこの命令はありません。
◆ RETLW k 動作:RETLW k
 「RETLW」は「リターン定数命令」です。サブルーチンを呼び出されて元の場所へ戻る命令では「RETURN」と同じですがチョット違った使い方が出来ます。実際には例題を見て下さい。簡単に説明するとリターンする時にWレジスタに応じた値を戻り値として返すのでテーブル参照に便利な命令です。
◆基本例題1 W RAM_A RAM_B Z,D,C 解 説(CALLについて)
MOVLW 02H 02H -- -- -,-,- Wに02Hを格納
CALL TABLE 43H -- -- -,-,- TABLEサブルーチンをコール。'C'のアスキーコード43HがWに格納
NOP 43H -- -- -,-,-
-- -- -- -,-,- メインプログラムがここに入る。(省略)
GOTO LOOP -- -- -- -,-,-
TABLE: ADDWF PC -- -- -- -,-,- サブルーチン開始、goto PC+W
RETLW 'A' -- -- -- -,-,- W=0の時に来る。リターンする前にWに'A'を入れてリターンする
RETLW 'B' -- -- -- -,-,- W=1の時に来る。リターンする前にWに'B'を入れてリターンする
RETLW 'C' -- -- -- -,-,- W=2の時に来る。リターンする前にWに'C'を入れてリターンする
RETLW 'D' -- -- -- -,-,- W=3の時に来る。リターンする前にWに'D'を入れてリターンする
RETLW 'E' -- -- -- -,-,- W=4の時に来る。リターンする前にWに'E'を入れてリターンする
■ 12ビット長PIC 専用命令! ■
◆ OPTION  動作:W → 「OPTION」
 「OPTION」は「OPTIONset命令」です。これはWの内容を「OPTION」レジスタ書き込む専用命令です。12ビット長のPICにだけある命令です。「OPTION」レジスタは書込専用レジスタです。
◆ TRIS f  動作:W → 「TRIS」
 「TRIS」は「TRISset命令」です。これはWの内容を「TRIS GPIO」レジスタ書き込む専用命令です。12ビット長のPICにだけある命令です。「TRIS GPIO」レジスタは書込専用レジスタです。PICにもよりますが通常「f」は「6(GPIO)」でI/Oの入出力をコントロールします。
■ PICのその他の命令! ■
◆ NOP  動作:No operation
 「NOP」は「ノップ命令」です。これは何もしない命令ですが、それならこんな命令はいらないのではと思います。でもこの命令にも便利な機能があり1命令で1サイクルの時間を消費するのでタイマーのプログラムなどに含まれる場合が有ります。
◆基本例題1 W RAM_A RAM_B Z,D,C 解 説(NOPについて)
25H 35H 68H 0,0,C 初期値がそれぞれ左の値であるとき
NOP 25H 35H 68H 0,0,C NOPは何もしないのでどれも変化無し、1サイクルのみ消費
NOP 25H 35H 68H 0,0,C NOPは何もしないのでどれも変化無し、1サイクルのみ消費
◆ SLEEP  動作:Sleep
 「SLEEP」は「スリープ命令」です。スリープ命令と言うぐらいですからPICがお休みする命令です。この命令を実行するとPIC自体はスリープモードに入り省電力モードとなります。
●スリープモードでは下記の状態になります。
・ウォッチドックタイマがクリアされる
・STATUSレジスタ内のPD=0にTO=1に設定されます。
・オシレータが停止します。(オシレータが動作すると電気が流れ省電力にならないようです)
●スリープからの復帰方法
・MCLRピンからのリセット
・ウォッチドッグタイマが作動
・割り込みがかかった場合(INTピン、ポートBの変化、TMR1割り込み、CCP、SSP、USART、A/D、EEPROMなどの要素がある)
◆基本例題1 W TO PD Z,D,C 解 説(SLEEPについて)
25H -- -- 0,0,C 初期値がそれぞれ左の値であるとき
SLEEP 25H 1 0 0,0,C SLEEPでここでスリープモードにはいる(お休み中)
NOP 25H 1 0 0,0,C 割り込みなどの原因で復帰する(この行から始まる)
◆ CLRWDT  動作:00H → WDT
 「CLRWDT」は「クリア命令」です。但しウォッチドッグタイマーをクリアする命令です。
 PICにはウォッチドックタイマーを内蔵している物があり、その機能を作動させた時ある一定時間以内に、このクリア命令を発効しなければリセットするしくみです。暴走などでの保護用です。
 この命令でSTATUSレジスタ内のPDTOの2種類がセットされます。それぞれの意味は次のようになっています。
PD →パワーダウン・ビット 1=電源ON後、CLRWDT命令実行後/0=SLEEP命令実行時
TO →タイムアウト・ビット 1=電源ON後、CLRWDT命令かSLEEP命令実行後/0=WDT タイムアウト発生した場合 
◆基本例題1 W TO PD Z,D,C 解 説(CLRWDTについて)
25H -- -- 0,0,C 初期値がそれぞれ左の値であるとき
CLRWDT 25H 1 1 0,0,C ウォッチドッグタイマをクリアする。
NOP 25H 1 0 0,0,C 通常の値は何も変化がない
■ PICのサンプル命令集 ■
 ここでは、よく使うプログラムのサンプルを集めてみました。現在製作中で少ないですが参考まで!
このサンプル集はPIC16F628を使って作っています。
001-初期設定
002-LEDを点灯1
◆ 001-初期設定 最低必要なプログラム
 LEDを点灯させてみよう。
◆初期セット W RAMA RAMB フラグ 解 説
初期設定 -- -- -- x,x,x 初期状態
#include <P16F509.INC> -- -- -- x,x,x P16F509を読み込みます。(最低必要な定義文を読み込み)
-- -- -- x,x,x
ORG 000H -- -- -- x,x,x 0番地よりスタート(リセット時)
GOTO MAIN -- -- -- x,x,x MAINへジャンプ
ORG 004H -- -- -- x,x,x 4番地よりスタート(割り込み時)
RETFIE -- -- -- x,x,x 割り込み処理(無いのでリターン)
MAIN: BCF STATUS,PR0 -- -- -- x,x,x バンク−0に設定
BCF STATUS,PR1 -- -- -- x,x,x
CLRF INTCON -- -- -- x,x,x 割り込み関係をクリア
MOVLW B'00000000' -- -- -- x,x,x PORTAのポートを全てLo(0)にする
MOVWF PORTA -- -- -- x,x,x
MOVLW B'11111111' -- -- -- x,x,x PORTBの全てHi(1)にする
MOVWF PORTB -- -- -- x,x,x
BSF STATUS,PR0 -- -- -- x,x,x バンク−1に設定
MOVLW B'11111111' -- -- -- x,x,x PORTAを全て入力ポートに設定する。
MOVWF TRIASA -- -- -- x,x,x 「0」=出力、「1」=入力
MOVLW B'00000000' -- -- -- x,x,x PORTBを全て出力ポートに設定する
MOVWF TRIASB -- -- -- x,x,x
MOVLW B'00000000' -- -- -- x,x,x 各種設定(必要に応じて設定する)
MOVWF _OPTION -- -- -- x,x,x
BCF STATUS,PR0 -- -- -- x,x,x バンク−0に設定
LOOP: -- -- -- x,x,x ここよりプログラム開始
◆ 002-LEDを点灯 PB0を点灯
 LEDを点灯させてみよう。
例1:ポートBの全てを一度に設定します。
例2:ポートBのビット0のみを0に設定します。
◆応用例題1 W RAMA RAMB フラグ 解 説
初期設定省略 -- -- -- x,x,x 初期設定省略(1.初期設定を参照)
LOOP: -- -- -- -,-,-
◆応用例題2 W RAMA RAMB フラグ 解 説
初期設定省略 -- -- -- x,x,x 初期設定省略(1.初期設定を参照)
LOOP: -- -- -- -,-,-
空き部屋  空き部屋
■ 空き部屋 ■











著作権について、FreeLabトップへ