Сами попросили.
Код:
FUNCTION SendPlcCmd : BOOL
VAR_INPUT
Cmd: SCommand;
Arg0, Arg1: WORD;
END_VAR
IF CMD_CTRL.cmdCount < 51 THEN
CMD_CTRL.cmdQueue[CMD_CTRL.cmdCount][0] := Cmd;
CMD_CTRL.cmdQueue[CMD_CTRL.cmdCount][1] := Arg0;
CMD_CTRL.cmdQueue[CMD_CTRL.cmdCount][2] := Arg1;
CMD_CTRL.cmdCount := CMD_CTRL.cmdCount + 1;
END_IF
Код:
PROGRAM CMD_CTRL (* Sends commands to the PLC *)
VAR_INPUT
Cmd, Arg0, Arg1: WORD;
cmdQueue: ARRAY[0..50] OF ARRAY [0..2] OF WORD;
cmdCount: INT;
END_VAR
VAR
Checksum: WORD;
Pulse: TON := (PT := T#300MS);
tx: BOOL;
cmdIdx: INT;
edge: R_TRIG;
END_VAR
(* Command conveyor, up to 50 commands in queue *)
tx := FALSE;
edge(CLK := cmdCount > 0);
Pulse(IN := NOT Pulse.Q AND cmdCount > 0);
IF (Pulse.Q OR edge.Q) AND cmdIdx < cmdCount THEN
Cmd := cmdQueue[cmdIdx][0];
Arg0 := cmdQueue[cmdIdx][1];
Arg1 := cmdQueue[cmdIdx][2];
Checksum := Cmd + Arg0 + Arg1;
tx := TRUE;
cmdIdx := cmdIdx + 1;
ELSIF Pulse.Q THEN
Cmd := 0;
cmdIdx := cmdCount := 0;
END_IF
mbus_cmdctrl.png
Это уже на ПЛК110, к которому подключены две СПК:
Код:
PROGRAM CMD_CTRL
VAR_INPUT
awaitingStop1, awaitingStop2, timeEditable1, timeEditable2: BOOL;
timeLim1, timeLim2: TIME;
auto: BOOL;
END_VAR
VAR
cmdCount: INT;
pOut: POINTER TO BOOL;
dummy: BOOL;
cmdStat: ARRAY [Idle..LastCmd] OF INT;
b3online, b4online, b6online, b7online, b8online, uf1online: BOOL;
END_VAR
VAR_OUTPUT
resetNeeded: BOOL;
END_VAR
resetNeeded := FALSE;
IF SACmd <> Idle THEN
IF SACmd + SAArg0 + SAArg1 <> SACmdChecksum THEN
SACmd := Idle;
END_IF
cmdCount := cmdCount + 1;
END_IF
(* Select corresponding output *)
pOut := MUX(SAArg0,
ADR(k1), ADR(k2), ADR(k3), ADR(k4),
ADR(k5), ADR(k6), ADR(k7), ADR(k8),
ADR(k9), ADR(k10), ADR(k11), ADR(k12),
ADR(k13), ADR(kdv), ADR(npp1), ADR(npp2),
ADR(npp3), ADR(kez4), ADR(k14), ADR(k15),
ADR(k16), ADR(k17), ADR(k18), ADR(k19),
ADR(k20), ADR(k21), ADR(k22), ADR(k23),
ADR(k24), ADR(k25), ADR(k26), ADR(k27),
ADR(k28), ADR(npp4), ADR(ni1), ADR(ni2),
ADR(chiller2), ADR(usnd_start), ADR(kdv2),
ADR(chiller), ADR(k29), ADR(k30), ADR(k31)
);
(* Îòêëþ÷èòü ðó÷íîå óïðàâëåíèå â àâòîìàòè÷åñêîì ðåæèìå *)
IF auto THEN
pOut := ADR(dummy);
END_IF
IF NOT auto THEN
CASE SACmd OF
Open:
pOut^ := TRUE;
Close:
pOut^ := FALSE;
Toggle:
pOut^ := NOT pOut^;
SetATG:
IF SAArg1 = 0 THEN
PLC_PRG.ATG_SP := SAArg0;
ELSE
AUTO1.atgtemp := SAArg0;
END_IF
SetGPL:
IF SAArg1 = 0 THEN
INVControl.1 := SAArg0 > 0;
INVFreq := SAArg0 * 100;
ELSE
AUTO1.gplfreq := SAArg0;
END_IF
END_CASE
END_IF
CASE SACmd OF
SetTemp:
PLC_PRG.PID_SP := SAArg0;
SetTimers:
IF NOT SAArg0.0 THEN
AUTO1.time1 := WORD_TO_TIME(SAArg1 * 1000);
ELSE
AUTO2.time1 := WORD_TO_TIME(SAArg1 * 1000);
END_IF
StartAuto:
resetNeeded := NOT auto;
IF NOT SAArg1.0 AND AUTO1.step = 0 THEN
AUTO1.process := SAArg0;
ELSIF SAArg1.0 AND AUTO2.step = 0 THEN
AUTO2.process := SAArg0;
END_IF
StopAuto:
IF NOT SAArg1.0 THEN
AUTO1.stop := TRUE;
ELSE
AUTO2.stop := TRUE;
END_IF
AbortAuto:
IF NOT SAArg0.0 THEN
AUTO1.process := 0;
ELSE
AUTO2.process := 0;
END_IF
SetRegen:
PLC_PRG.RegenEnabled := SAArg0.0;
END_CASE
IF SACmd > 0 AND SACmd < SIZEOF(cmdStat) THEN
cmdStat[SACmd] := cmdStat[SACmd] + 1;
END_IF
SACmd := Idle;
Очень вероятно, что ничего этого в вашем случае не требуется, и можно обойтись телом первой функции, то есть сразу там исполнять команду.