我在Codesys V3.5 SP9 Patch 5中遇到了结构化文本的问题。我想要做的是能够在我创建的函数中使用计时器,这在POU中调用。我通过将计时器直接放入POU而不使用功能完成了同样的工作。
我的功能声明:
FUNCTION AssignDOORStatus : USINT
VAR_INPUT
DDUC_ComSta_Dcux_x: BOOL; //No communication
DDUC_DCUxEmHdler_x: BOOL; //Emergency handler
END_VAR
VAR
Timer: TP; //Timer to do intermittence between current doors status and emergency handler
CurrentDoorStatus: USINT;
TONProcessTime: TIME := T#1S; //TONProcesTime
END_VAR
我的功能代码:
IF DDUC_ComSta_Dcux_x THEN
CurrentDoorStatus := 0;
ELSE
CurrentDoorStatus := 1;
END_IF
IF DDUC_DCUxEmHdler_x THEN
Timer(IN := NOT Timer.Q, PT := TONProcessTime); //Timer starts
Timer();
IF Timer.Q THEN //When TONProcessTime has gone by
IF AssignDOORStatus <> CurrentDoorStatus THEN
AssignDOORStatus := CurrentDoorStatus;
ELSE AssignDOORStatus := 10;
END_IF
END_IF
ELSE
AssignDOORStatus := CurrentDoorStatus;
END_IF
我的代码在POU主要:
testdoor := AssignDOORStatus(DDUC_ComSta_Dcu1_S1_T,DDUC_DCU1EmHdler_S1_T);
此代码用于根据变量“DDUC_ComSta_Dcux_x”分配给“AssignDOORStatus”0或1,然后,当“DDUC_DCUxEmHdler_x”为真时,它使用定时器将“AssignDOORStatus”值从“0或1”翻转为10。
我必须多次调用POU这个函数。
提前致谢!
功能没有记忆。因此,在VAR中声明的所有变量都是临时的,并且会为每个新调用重置为其默认值。
FunctionBlocks / Programs有内存。因此,VAR中声明的所有变量在每次调用之间都保持其值。
这就是为什么你不应该使用一个函数,它将忘记MAIN每次调用之间的所有事情。例如,计时器将从之前的呼叫重置。
相反,你应该编写一个功能块(或FB),它可以重复用于你想要处理的几个门。功能块内部将是一组变量(尤其是计时器),这些变量对于每个实例都是唯一的,并且还可以从调用到被调用来记住。
以上是一个非常简短的描述,因此您应该在编译器帮助文件中查找功能块以获得正确的解释,例如:用于输入/输出参数。 以下是我对一个程序的建议,该程序对三个不同的门实例使用相同的FB:
(The FB, first the declaration and then it's code)
FUNCTION_BLOCK FB_AssignDOORStatus
VAR_INPUT
DDUC_ComSta_Dcux_x: BOOL; //No communication
DDUC_DCUxEmHdler_x: BOOL; //Emergency handler
END_VAR
VAR_OUTPUT
AssignDoorStatus: USINT;
END_VAR
VAR
Timer: TP; //Timer to do intermittence between current doors status and emergency handler
CurrentDoorStatus: USINT;
TONProcessTime: TIME := T#1S; //TONProcesTime
END_VAR
----------
IF DDUC_ComSta_Dcux_x THEN
CurrentDoorStatus := 0;
ELSE
CurrentDoorStatus := 1;
END_IF
IF DDUC_DCUxEmHdler_x THEN
Timer(IN := NOT Timer.Q, PT := TONProcessTime); //Timer starts
Timer();
IF Timer.Q THEN //When TONProcessTime has gone by
IF AssignDOORStatus <> CurrentDoorStatus THEN
AssignDOORStatus := CurrentDoorStatus;
ELSE
AssignDOORStatus := 10;
END_IF
END_IF
ELSE
AssignDOORStatus := CurrentDoorStatus;
END_IF
(MAIN, first the declaration and then it's code)
PROGRAM MAIN
VAR
// You must make an instance of your function block(s). This instance will live from call to call.
fbAssignDOORStatus_1: FB_AssignDOORStatus;
fbAssignDOORStatus_2: FB_AssignDOORStatus;
fbAssignDOORStatus_3: FB_AssignDOORStatus;
// ...
// Better to use an array to hold the many FB instances needed...
// You could use a for loop in the MAIN program to call all the instances.
// Test variables to hand to the fb's during runtime.
ComSta: BOOL;
EmHdler: BOOL;
TestDoor1, TestDoor2, TestDoor3: USINT;
// Here you could also use an array or re-use some common variable...
END_VAR
----------
fbAssignDOORStatus_1(
DDUC_ComSta_Dcux_x := ComSta,
DDUC_DCUxEmHdler_x := FALSE,
AssignDoorStatus => TestDoor1);
fbAssignDOORStatus_2(
DDUC_ComSta_Dcux_x := TRUE,
DDUC_DCUxEmHdler_x := EmHdler,
AssignDoorStatus => TestDoor2);
fbAssignDOORStatus_3(
DDUC_ComSta_Dcux_x := ComSta,
DDUC_DCUxEmHdler_x := EmHdler,
AssignDoorStatus => TestDoor3);