【GX Works3】CJ/CALL/FOR-NEXT命令の使い方|ジャンプ・サブルーチン・繰り返し・FEND/ENDまで総まとめ

概要

ラダープログラムは基本的に0ステップからENDまで、上から下へ毎スキャン順番に流れていきます。この「上から下へ、毎スキャン全部」という基本の流れを、必要に応じて曲げたいときに使うのがフロー制御命令です。条件によって特定のブロックを丸ごと飛ばしたい、複数の場所から同じ処理を呼び出したい、同じ計算を回数分だけまとめて繰り返したい——こうした「流れそのものをコントロールする」場面で登場します。まずはやりたいことと命令の対応から見ていきます。

やりたいこと使う命令
条件によって一部の処理をスキップしたいCJ(無条件ならJMP
同じ処理を何か所からも呼び出したい(共通化)CALL / RET(サブルーチン)
同じ処理を回数指定で繰り返したいFOR / NEXT(途中で抜けるならBREAK
メインルーチンとサブルーチンを区切るFEND(プログラム最終はEND=自動入力)

CJ / SCJ / JMP(ジャンプ)

書式

出典: MELSEC iQ-R プログラミングマニュアル(CPUユニット用命令/汎用FUN/汎用FB編)SH-081226 7.1 プログラム分岐命令 / ops/refs/instructions/09_flow-control.md より転記。

命令記号実行条件主なオペランド/データ型動作
CJ実行指令ON中(P) ジャンプ先ポインタ番号/POINTER実行指令がONの間、指定ポインタへジャンプ(間の回路をスキップ)。OFFなら次ステップへ
SCJOFF→ONの次スキャンから(P) 同上実行指令がOFF→ONに変化した次のスキャンからジャンプ(変化したスキャンは1回だけ間を実行)
JMP常時実行(P) 同上無条件に指定ポインタへジャンプ

ジャンプ先ポインタ(P)は同一プログラムファイル内のみ指定可・ラベル(P)は1ステップ占有。飛ばされた範囲のデバイスは変化しない(ON中のタイマを飛ばすと正常な計測ができなくなる)。ポインタ不在等はエラー3380H。

動作

X0がONのとき CJ P0 でP0ポインタまでスキップするラダー図(スキップ範囲がわかるよう複数ラングを含む構成)
図1:X0がON中、CJ P0でP0まで間の回路をスキップするラダー図です。X0がONしている間だけ、CJとP0に挟まれた回路がまるごと実行されなくなります。

動作のポイントはシンプルで、CJの実行条件がONの間はずっと、そのスキャンでP0までの区間が実行されません。OFFになれば、次のスキャンからはまた普通に上から下へ流れます。ここで誤解しやすいのが「スキップされた回路がOFFになる」という理解で、実際には出典にあるとおり飛ばされたデバイスは変化しません——つまりCJを実行する前の状態がそのまま維持されます。現場での使いどころとしては、手動モードと自動モードの切り替えのように「今は使わない側のブロックを丸ごと飛ばしたい」場面や、段取り替え中は生産系の判断処理を止めておきたい、といった場面が定番です。似た命令にSCJがありますが、こちらは実行条件がOFF→ONに変化した次のスキャンからジャンプが始まる点がCJと違います。切り替わった瞬間の1スキャンだけは通常どおり間の回路も実行される、という違いを押さえておくと使い分けに迷いません。

サンプルコード

手動モードのときだけ自動運転ブロックを飛ばす

[メインルーチン]
M100  CJ  P0
∙∙∙自動運転ブロック(コンベア起動・搬送タイマ 等)∙∙∙
P0
∙∙∙手動運転ブロック(手動ジョグ操作 等)∙∙∙

M100が手動モード選択リレーだとして、M100がONの間はCJ P0で自動運転ブロックを丸ごと飛ばし、P0以降の手動運転ブロックだけを実行します。ここで注意したいのは、自動運転ブロックの中にタイマや搬送カウンタが入っている場合です。自動運転中にONしていたタイマやカウンタの値は、CJで飛ばしている間もそのまま保持されるため、手動モードから自動モードへ戻したときに前回の値からカウントが再開されてしまいます。モード切替のたびにリセットが必要なデバイスがないか、飛ばす前に洗い出しておくことが大切です。

FEND / END(プログラムの区切りと終わり)

書式

出典: MELSEC iQ-R プログラミングマニュアル(CPUユニット用命令/汎用FUN/汎用FB編)SH-081226 5.7 終了命令(PDF pp.212-214)/ ops/refs/instructions/09_flow-control.md(2026-07-15追記・原本照合済み)より転記。

命令記号実行条件主なオペランド/データ型動作
FEND常時実行(オペランドなし)メインルーチンプログラムの終了。サブルーチン・割込みプログラムとの分割に使用
END常時実行(オペランドなし)プログラムの最終を示す(回路編集モードでは自動入力・編集不可)

FEND/ENDを実行するとCPUユニットは実行中のプログラムを終了する。FOR〜NEXT間で実行すると3340H・CALL後RET前で実行すると3381H・割込み中IRET前で実行すると33A1H。

動作

プログラム全体を俯瞰すると、次のような並びになっています。まず一番上に、毎スキャン実行されるメインルーチンプログラムがあります。そのメインルーチンの終わりにFENDを置いて区切ると、その下にポインタP**から始まるサブルーチンプログラム群を並べることができ、各サブルーチンはRETで締めくくります。さらにその下に、END命令でプログラム全体の最終を示します。ポイントは、FENDから下の領域は、CJやCALLでポインタを指定して呼び出さない限り、通常のスキャンでは実行されないということです。つまりFENDの下は、メインの流れとは別に置いておくサブルーチンの置き場であり、ここに書いた処理は毎スキャン勝手に流れるわけではありません。ENDは回路編集モードでは自動的に入力され、こちらで手を加えることはできませんが、FENDは自分でプログラムに書き込む必要があります。この「メインルーチン→FEND→サブルーチン群→END」という構造の地図が、この後説明するCALL/RETの前提になります。

CALL / RET(サブルーチン)

書式

出典: MELSEC iQ-R プログラミングマニュアル(CPUユニット用命令/汎用FUN/汎用FB編)SH-081226 7.3 構造化命令(PDF pp.584-588)/ ops/refs/instructions/09_flow-control.md(2026-07-15追記・原本照合済み)より転記。

命令記号実行条件主なオペランド/データ型動作
CALL / CALLP常時実行/立上り(P) サブルーチン先頭ポインタ番号(引数(s1)〜(s5)も指定可)指定ポインタのサブルーチンプログラムを実行
RET常時実行(オペランドなし)サブルーチンの終了。CALL(P)命令の次ステップへ戻る

ネスティングは16重まで(CALL/FCALL/ECALL/EFCALL/XCALLの合計)。サブルーチン内でONさせたデバイスは非実行でも保持される。ポインタ不在3380H・RET前にEND/FEND実行3381H・CALL前にRET実行3382H。

動作

メインルーチンで CALLP P10 → FENDの後にP10以降のサブルーチン処理 → RET の構成ラダー図
図2:メインルーチンのCALLP P10で、FENDの後に置いたP10のサブルーチンへ飛び、RETでCALLPの次のステップへ戻ってくる構成のラダー図です。サブルーチン本体はFENDより下=毎スキャンの流れの外に置くのがポイントです。

CALL(P)を実行すると、指定したポインタP**へ処理が飛び、そのサブルーチンプログラムが実行されます。サブルーチン内でRETに到達すると、CALL(P)を実行した次のステップへ戻ってきて、メインルーチンの続きが流れます。現場でCALL/RETがよく使われるのは、複数の場所から同じ処理を呼び出したいときです。たとえばアラームランプの点滅パターンや、複数の軸で共通する原点復帰の手順のように、内容は1つなのに呼び出したい場所が何か所もある処理を1か所にまとめておけば、修正のたびに全部の箇所を書き換える手間がなくなります。書き方で注意したいのが、RETを書き忘れたときの挙動です。サブルーチン内でRETに到達する前にFENDやENDへ突き当たってしまうと、エラー3381Hになります。サブルーチンは必ずRETで閉じる、という約束を崩さないようにしてください。もう一つ押さえておきたいのが、サブルーチン内でONにしたデバイスの扱いです。出典にあるとおり、サブルーチンプログラム内でONさせたデバイスは、そのサブルーチンが非実行の状態でもONのまま保持されます。呼ばれていない間も状態を消したくないなら好都合ですが、逆に呼ばれるたびにリセットしたいデバイスがある場合は、意図せず前回の状態を引きずってしまわないか確認が必要です(サブルーチン内でONにしたデバイスを明示的にOFFさせたい場合の選択肢としてFCALLという命令もあります)。

サンプルコード

2か所から共通処理を呼び出す

[メインルーチン]
X0  CALLP P10
∙∙∙
X5  CALLP P10
∙∙∙
FEND

P10
∙∙∙共通処理(アラームランプ点滅パターン 等)∙∙∙
RET

END

X0とX5、2つの異なる条件がどちらもCALLP P10で同じサブルーチンを呼び出しています。共通処理をP10に1回だけ書いておけば、呼び出し元が何か所に増えても中身は1つのまま管理できます。もし同じ処理をCALLを使わずにX0側とX5側それぞれに書いてしまうと、点滅の周期を変えたくなったときに片方だけ書き換え忘れるリスクが出てきます。

FOR / NEXT / BREAK(繰り返し)

書式

出典: MELSEC iQ-R プログラミングマニュアル(CPUユニット用命令/汎用FUN/汎用FB編)SH-081226 7.3 構造化命令(PDF pp.580-583)/ ops/refs/instructions/09_flow-control.md(2026-07-15追記・原本照合済み)より転記。

命令記号実行条件主なオペランド/データ型動作
FOR常時実行(n) 繰返し回数 1〜32767/ANY16FOR〜NEXT間の処理を(n)回実行してからNEXTの次ステップへ。-32768〜0指定はn=1と同一
NEXT常時実行(オペランドなし)繰り返し範囲の終端。FORとセットで使用
BREAK / BREAKP常時実行/立上り(d) 残数格納デバイス/(P) 分岐先ポインタ繰り返しを強制終了し(P)へ。(d)に残回数を格納(BREAK実行時の回数を含む)

ネスティングは16重まで(17重目は3361H)。FOR前にNEXTは3341H・FOR〜NEXT間にEND/FENDは3340H。BREAKはFOR〜NEXT間でのみ使用可(3342H)・1つのネスティングに対してのみ有効。実行したくないときはCJ/SCJで飛ばす。

動作

FOR K5 → 処理(例: D0へのINCP)→ NEXT の繰り返しラダー図
図3:FOR K5とNEXTで挟んだ処理を、1回のスキャンの中で5回実行するラダー図です。5回回りきってから、NEXTの次のステップへ進みます。

FOR(n)〜NEXTで挟んだ処理は、1回のスキャンの中で(n)回すべて回りきってから、NEXTの次のステップへ進みます。ここが誤解しやすいポイントで、スキャンをまたいで1回ずつ回っていくわけではありません。条件が成立した1回のスキャンの中で指定回数分がまとめて実行されます。当然ながら、回した分だけそのスキャンの処理時間は延びます。回数が数個程度ならほとんど影響はありませんが、FOR〜NEXTの中に処理を入れて回数を大きくすると、そのスキャンタイムがそのまま延びることになるので、回数の設定には気を配ってください。現場での使いどころとしては、同じ計算を連番のデバイスにまとめて適用したい場面が定番です。マニュアルの原文例でも、インデックス修飾Z0をFOR〜NEXTの中でINCさせながら回すことで、Z0を1ずつ増やしつつ連番デバイス(例:M0Z0、M100Z0)に同じ処理を適用する組み方が示されています。決まった回数の途中で処理を打ち切りたいときは、BREAKを使います。BREAKを実行すると、その時点でFOR〜NEXTを強制的に終了して指定したポインタへ移り、残っていた回数は(d)に格納されます(BREAKを実行したときの回もこの残数に含まれます)。

よくある誤解

①CJで飛ばした範囲はOFFになるのではなく「そのまま」

CJで飛ばした範囲は「OFFになる」のではなく「そのまま」です。出典にあるとおり、CJ・SCJ・JMPで飛ばされたデバイスは変化しません。飛ばす前にONしていた出力はONのまま残るため、モードを切り替える前に該当の出力を明示的に止める処理を入れておかないと、飛ばした瞬間に出力がONのまま固まってしまうことがあります。

②ON中のタイマをジャンプで飛ばすと計測が狂う

ON中のタイマをジャンプで飛ばすと、正常な計測ができなくなります。これはCJ・SCJ・JMPすべてに共通する注意事項として出典に明記されています。タイマのコイルをONさせた後にその範囲をジャンプで飛ばしてしまう設計は避け、タイマを含む処理はジャンプ範囲の外に出すか、そもそもジャンプさせない構成にしておくのが安全です。

③FOR/NEXTは「1スキャンに1回ずつ回る」のではない

FOR/NEXTは、条件が成立するたびに1回ずつ回るのではなく、1回のスキャンの中で指定回数をすべて回りきります。回数を大きく設定すると、その分だけそのスキャンの処理時間がそのまま延びることを忘れないでください。

④プログラム構造の順序を崩すとエラーで止まる

プログラムの構造の順序を崩すと、エラーで止まります。サブルーチン内でRETに到達する前にFENDやENDに突き当たると3381H、FOR〜NEXTの間でNEXTに到達する前にFENDへ突き当たると3340Hになります。「メインルーチン→FEND→サブルーチン群→END」という並びを崩さないことが、フロー制御命令をエラーなく使う基本です。

関連命令

関連記事