結構式文件編程語言

結構式文件編程語言（Structured text）也稱為ST語言，是為可程式邏輯控制器（PLC）設計的程式語言，是相關的IEC 61131-3標準中支援幾種語言之一。結構式文件編程語言是支援塊狀結構（block structured）的高階語言，以Pascal為基礎，語法也類似Pascal。所有IEC 61131-3的語言都支援IEC61131通用元素（IEC61131 Common Elements）。其變數及函式呼叫是由IEC61131通用元素所定，因此同一個程式中可以使用IEC 61131-3中的不同語言。

結構式文件編程語言類似於PASCAL及C語言，因此可利用與微電腦及個人電腦相同的程式設計技術，進行階梯圖所難以執行的複雜計算，完成程式的建立。常用的程式及迴路可透過FB（功能區塊）的建立輕易地重複利用。

結構式文件編程語言支援複雜的敘述及巢狀指令：

- 迴圈（REPEAT-UNTIL; WHILE-DO）
- 條件式執行（IF-THEN-ELSE; CASE）
- 函數（SQRT, SIN）

## 範例

### 簡單的程式

```pascal
(* simple state machine *)
TxtState := STATES[StateMachine];

CASE StateMachine OF
   1: ClosingValve();
ELSE
    ;; BadCase();
END_CASE;
```

### 另外一個結構式文件的程式範例

```pascal
// PLC configuration
CONFIGURATION DefaultCfg
    VAR_GLOBAL
        b_Start_Stop  : BOOL;         // Global variable to represent a boolean.
        b_ON_OFF      : BOOL;         // Global variable to represent a boolean.
        Start_Stop AT %IX0.0:BOOL;    // Digital   input of the PLC (Address 0.0)
        ON_OFF     AT %QX0.0:BOOL;    // Digital output of the PLC (Address 0.0). (Coil)
    END_VAR

    // Schedule the main program to be executed every 20 ms
    TASK Tick(INTERVAL := t#20ms);

    PROGRAM Main WITH Tick : Monitor_Start_Stop;
END_CONFIGURATION

PROGRAM Monitor_Start_Stop          // Actual Program
    VAR_EXTERNAL
        Start_Stop  : BOOL;
        ON_OFF      : BOOL;
    END_VAR
    VAR                             // Temporary variables for logic handling
        ONS_Trig    : BOOL;
        Rising_ONS  : BOOL;
    END_VAR

    // Start of Logic
    // Catch the Rising Edge One Shot of the Start_Stop input
    ONS_Trig    := Start_Stop AND NOT Rising_ONS;
    
    // Main Logic for Run_Contact -- Toggle ON / Toggle OFF ---
    ON_OFF := (ONS_Trig AND NOT ON_OFF) OR (ON_OFF AND NOT ONS_Trig);        

    // Rising One Shot logic   
    Rising_ONS := Start_Stop;
END_PROGRAM
```

### 函式方塊範例

```pascal
//=======================================================================
// Function Block Timed Counter :  Incremental count of the timed interval
//=======================================================================
FUNCTION_BLOCK FB_Timed_Counter
    VAR_INPUT
        Execute         : BOOL := FALSE;        // Trigger signal to begin Timed Counting
        Time_Increment  : REAL := 1.25;         // Enter Cycle Time (Seconds) between counts
        Count_Cycles    : INT  := 20;           // Number of Desired Count Cycles
    END_VAR
    
    VAR_OUTPUT
        Timer_Done_Bit  : BOOL := FALSE;        // One Shot Bit indicating Timer Cycle Done
        Count_Complete  : BOOL := FALSE;        // Output Bit indicating the Count is complete            
        Current_Count   : INT  := 0;            // Accumulating Value of Counter
    END_VAR
    
    VAR
        CycleTimer      : TON;                  // Timer FB from Command Library
        CycleCounter    : CTU;                  // Counter FB from Command Library
        TimerPreset     : TIME;                 // Converted Time_Increment in Seconds to MS
    END_VAR
        
    // Start of Function Block programming
    TimerPreset := REAL_TO_TIME(in := Time_Increment) * 1000;  

    CycleTimer(
        in := Execute AND NOT CycleTimer.Q,
        pt := TimerPreset);

    Timer_Done_Bit := CycleTimer.Q;
    
    CycleCounter(
        cu := CycleTimer.Qa,
        r := NOT Execute,
        pv := Count_Cycles);     

    Current_Count := CycleCounter.cv;
    Count_Complete := CycleCounter.q;
    
END_FUNCTION_BLOCK
```