0

我在 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 main 中的代码:

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 这个函数。

提前致谢!

4

1 回答 1

4

函数没有记忆。因此,在 VAR 中声明的所有变量都是临时的,并且在每次新调用时都重置为默认值。

功能块/程序有内存。因此,在 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);
于 2018-03-01T20:47:10.370 回答