Main Content

Generated Code Structure for Stateflow Charts

The examples in this topic show generated code for the CODESYS Version 2.3 PLC IDE. Generated code for other IDE platforms looks different.

Stateflow Chart with Event Based Transitions

Generate code for the Stateflow® chart ControlModule in the model plcdemo_stateflow_controller. To open the model, enter:

openExample('plcdemo_stateflow_controller');
Here is the chart:

You can map the states and transitions in the chart to the generated code. For instance, the transition from the state Aborting to Aborted appears in the generated code as:

ControlModule_IN_Aborting: 
                    rtb_out := sABORTING;
                    (* During 'Aborting': '<S1>:11' *)
                    (* Graphical Function 'is_active': '<S1>:73' *)
                    (* Transition: '<S1>:75' *)
                    IF  NOT drive_state.Active THEN 
                        (* Transition: '<S1>:31' *)
                        is_c2_ControlModule := ControlModule_IN_Aborted;
                        (* Entry 'Aborted': '<S1>:12' *)
                        rtb_out := sABORTED;
                        (* Graphical Function 'stop_drive': '<S1>:88' *)
                        (* Transition: '<S1>:90' *)
                        driveOut.Start := FALSE;
                        driveOut.Stop := TRUE;
                        driveOut.Reset := FALSE;
                    END_IF;

For more information on the inlining of functions such as start_drive, stop_drive, and reset_drive in the generated code, see Control Code Partitions for MATLAB Functions in Stateflow Charts.

Stateflow Chart with Absolute Time Temporal Logic

Generate code for the Stateflow chart Temporal in the model plcdemo_sf_abs_time. To generate code, see Generate Structured Text Code for a Stateflow Chart That Uses Absolute-Time Temporal Logic. Here is the chart:

You can map states and transitions in the chart to the generated code. For instance, the transition from state B to C appears as:

 Temporal_IN_B: 
                    (* During 'B': '<S1>:2' *)
                    temporalCounter_i1(timerAction := 2, maxTime := 4000);
                    IF temporalCounter_i1.done THEN 
                        (* Transition: '<S1>:8' *)
                        is_c2_Temporal := Temporal_IN_C;
                        temporalCounter_i1(timerAction := 1, maxTime := 0);
                    ELSE 
                        (* Outport: '<Root>/pulse' *)
                        pulse := 2.0;
                    END_IF;

The variable temporalCounter_i1 is an instance of the function block PLC_CODER_TIMER defined as:

FUNCTION_BLOCK PLC_CODER_TIMER
VAR_INPUT
    timerAction: INT;
    maxTime: DINT;
END_VAR
VAR_OUTPUT
    done: BOOL;
END_VAR
VAR
    plcTimer: TON;
    plcTimerExpired: BOOL;
END_VAR
CASE timerAction OF
    1:
        (* RESET *)
        plcTimer(IN:=FALSE, PT:=T#0ms);
        plcTimerExpired := FALSE;
        done := FALSE;
    2:
        (* AFTER *)
        IF (NOT(plcTimerExpired)) THEN
            plcTimer(IN:=TRUE, PT:=DINT_TO_TIME(maxTime));
        END_IF;
        plcTimerExpired := plcTimer.Q;
        done := plcTimerExpired;
    3:
        (* BEFORE *)
        IF (NOT(plcTimerExpired)) THEN
            plcTimer(IN:=TRUE, PT:=DINT_TO_TIME(maxTime));
        END_IF;
        plcTimerExpired := plcTimer.Q;
        done := NOT(plcTimerExpired);
END_CASE;
END_FUNCTION_BLOCK