結構式文件編程語言 (Structured Text) 也稱為ST語言,是IEC 61131-3標準定義的語言之一,屬高階設計語言,可以執行多種操作,例如調用功能、功能塊、賦值、有條件的執行語句和重複任務等,因此ST適用於完成較複雜的運算。ST编程語言由各種元素組成,具體如下。
註解
註解多用於註記一些文字,以提高後續代碼的維護性。它並不占用任何容量與影響執行結果。撰寫註解的方式共區分單行、多行與區塊幾種方式。
單行註解
i := i + 1 // comment;
區塊註解
ADD(a (* comment *) , b);
多行註解
(* start comment ... end comment*) i := i + 1;
名詞解釋
操作符與表示式
ST語言內的操作符與許多高階語言皆十分相似,多用於數據的處理。而由操作數與操作符組合的結構我們稱之為「表示式」,它在計算之後即獲得返回值。下表表列ST所有可使用的操作符,並按其優先級進行排序(由高至低)。
操作符 | 含意 | 優先級 | 適用的操作數 | 範例 |
( ) | 最高優先級的括號 | 最高 | 表示式 | A := 1 + 2 * 3; // A = 7
B := (1 + 2) * 3; // B = 9 |
Function | 函式調用 | 運算式、變數或常數,其數據型態主要依據函式引述的定義。 | A := ADD(1,2) * 3; // A = 9 | |
– | 取反 | INT、DINT或REAL48 的表示式、變數或常數。 | A := 4;
B := – A; // B = -4 |
|
NOT | BOOL 的表示式、變數或常數。 | A := TRUE;
B := NOT A; // B = FALSE |
||
** | 冪 | [REAL48] ** [INT] | A := 2.0 ** 2; // A = 4.0 | |
* | 乘 | INT、DINT或REAL48 的表示式、變數或常數。 | A := 2 * 3; // A = 6 | |
/ | 除 | A := 6 / 3; // A = 2 | ||
MOD | 模除 | INT或DINT的表示式、變數或常數。 | A := 5 MOD 2; // A = 1 | |
+ | 加 | INT、DINT或REAL48 的表示式、變數或常數。 | A := 1 + 2; // A = 3 | |
– | 減 | A := 1 – 2; // A = -1 | ||
= | 等於比較 | BOOL、INT、DINT或REAL48 的表示式、變數或常數。 | A := 5 = 2; // A = FALSE | |
<> | 不等於比較 | A := 5 <> 2; // A = TRUE | ||
> | 大於比較 | A := 5 > 2; // A = TRUE | ||
< | 小於比較 | A := 5 < 2; // A = FALSE | ||
>= | 大於或等於比較 | A := 5 >= 2; // A = TRUE | ||
<= | 小於或等於比較 | A := 5 <= 2; // A = FALSE | ||
& | 邏輯與 | BOOL 的表示式、變數或常數。 | // A = FALSE
A := TRUE & FALSE; |
|
AND | // A = FALSE
A := TRUE AND FALSE; |
|||
XOR | 邏輯異或 | BOOL 的表示式、變數或常數。 | // A = TRUE
A := TRUE XOR FALSE; |
|
OR | 邏輯或 | 最低 | BOOL 的表示式、變數或常數。 | // A = TRUE
A := TRUE OR FALSE; |
語句
語句是構成ST程序的基本單位,每項語句的最末皆以分號符號「;」表示結束。因此,一個語句可以分成數行編寫,同時也可以將多個語句編寫在同一行,只需在語句結束用分號隔開即可。
:= 賦值語句
表示式在經運算後會獲得返回值,然而如何將其值指派給指定變數,我們可以採用賦值操作符與語句來達成這件事。賦值運算式的結構以賦值操作符 「:=」為主,左邊置放目標變數,然後右邊則為來源變數、常數或會含返回值的表示式。
賦值操作的目標與來源需屬同樣的數據型態。編譯器會於運行時檢查此規則並於錯誤時給予告警。
A := 10; B := A + 7; // B = 17 fA := INT_TO_R48(B); // "B" Data Type is INT, "fA" Data Type is REAL48
條件語句
條件語句的目的在於做決定,在ST語言中有兩種條件語句可以使用,分別為IF與CASE。
IF
IF語句的特性為根據布林表示式的回傳值(TRUE/FALSE)決定是否執行內部的語句組,是(TRUE)則執行,反之亦然。
IF [BOOL Expression] THEN <Statements>; END_IF ;
通常我們也會搭配ELSE來處理當布林條件式不成立(FALSE)時,執行ELSE內部的語句組。
IF [BOOL Expression] THEN <Statements>; ELSE <Statements>; END_IF ;
當有多個條件的需求時則可使用ELSIF,也就是說當條件不成立(FALSE)時會再判斷下個ELSIF內的布林表示式,一旦成立(TRUE)則執行對應的語句組,反之則再判斷下個ELSIF或是執行ELSE語句組。
IF [BOOL Expression] THEN <Statements>; ELSIF [BOOL Expression] THEN <Statements>; ELSE <Statements>; END_IF ;
如下範例,IF語句最終會將變數a設定為4。
i := 2 ; IF i = 0 THEN a := 1; // i = 0, a = 1 ELSIF i = 1 THEN a := 2; // i = 1, a = 2 ELSE a := 4; // other, a = 4 END_IF ;
CASE
條件語句的另一種選擇為CASE語句,但不同於IF語句,它的條件是採用數字表示式,因此很適用於某些用途。
CASE [numeric expression] OF [result1]: <Statements> [resultN]: <Statemtents> ELSE <Statements> END_CASE;
一個簡單的CASE語句範例如下:
STEP := 3; CASE STEP OF 1: a := a+1; 2: a := a+2; 3: a := a+3; ELSE a := 0; END_CASE;
循環語句
執行循環是編程過程中常見的方式,舉凡資料搬移、數值累加…等情境下都會運用到循環語句。
根據條件或計數,循環內的語句組將有機會重複運行直到條件或計數次數達指定條件
在ST語言裡分別提供 FOR、WHILE與REPEAT三種循環語句。當條件成立時FOR與WHILE將重複運行內部語句組,但與其相反的REPEAT則是一但條件成立即停止循環。
FOR
具體的指定預循環次數是FOR語句的特點。把一變數當計數使用,該計數當未達指定值時將持續執行內部的語句組。
FOR count := initial_value TO final_value BY increment DO <statement>; END_FOR;
initial_value : 計數變數的初始值。
final_value :計數終點值,當計數變數超出該值時則停止循環。
increment : 每次迭代時的累加值。 在省略 BY 關鍵字時,編譯器會自動將 increment 設為 1 , 也因此計數變數將在每次循環時累加1。
FOR i := 0 TO 10 DO sum := sum + i; END_FOR; // sum = 55
多數情境下,我們應避免於FOR語句內中串改計數變數的數值,以防止造成不可預期的的循環次數。
WHILE
當布林條件成立(TRUE)時WHILE語句將不斷的執行內部的語句組,直到條件不成立(FALSE)離開循環。
WHILE [boolean expression] DO <statement>; END_WHILE;
簡單的使用方式如下
i := 0; WHILE i <= 10 DO sum := sum + i; i := i + 1; END_WHILE;
REPEAT
REPEAT正好與WHILE相反,循環會一值持續到布林條件成立(TRUE)即停止。
REPEAT <statement>; UNTIL [boolean expression] END_REPEAT;
其他語句
EXIT
不管循環語句是否已滿足結束條件,EXIT語句可用於中斷循環過程。
如果 EXIT 坐落於於多層的循環語句内,則退出循環僅發生在第一個遇到的循環語句(向外尋找)。
FOR i := 1 TO 3 DO FOR j := 1 TO 5 DO IF FLAG THEN EXIT; END_IF; SUM := SUM + j; END_FOR; END_FOR;
RETURN
提供從函式、功能塊或程序的出口。如下範例,函式將在某條件成立時立即返回,因此在RETURN後的代碼將不再執行。
FOR i := 0 TO 360 DO IF FLAG THEN RETURN; END_IF; X := a * COS(i); Y := b * SIN(i); END_FOR;
以下內容屬ServoMotion擴充支援的部分,可能與IEC61131-3規格略有不同
調用 (Funtion/物件)
透過調用語句來呼叫函式或物件功能。
a. 函式支援命名空間
命名空間又稱函式庫名稱,在同個命名空間下不允許有重複的函式名稱,換言之,如果有想保留相同命名的函式需求,可將他們分別定義在不同的命名空間。
ASD:SET_MODE(X_AXIS, PATH); ASD:JOG(X_AXIS, 200, 200, 100000);
函式的調用需依指定規則撰寫 : [函式庫名稱]:[函式名稱](引述1,引述2, … ,引述n); ,但調用基本函式庫中的函式則是能省略庫名稱 ,如下:
a := BASIC:SIN(0); a := SIN(0);
b. 支援Multi-Output
填入函式引述時請注意,由於函式支援多個VAR_OUTPUT參數,調用上可以針對VAR_OUTPUT的參數選擇全填或全省略,而函式表示式本身的回傳值是第一個VAR_OUTPUT參數。
//DIV([input1],[inpout2],[output1],[output2]) DIV(5, 3, 商, 餘); //取得'商'與'餘' 商 := DIV(5, 3); //取得'商',忽略'餘' result := DIV(5, 3, 商, 餘); //取得'商'與'餘',且result = 商
填寫引述時由左至右的順序排列為 : VAR_INPUT → VAR_IN_OUT → VAR_OUTPUT,務必依照該順序方能正確傳入參數至函式。
使用 MSM語言
部分情境下也許是效能、習慣與功能支援度等考量,你可在高階語言(ST)中穿插低階的MSM語言,如下演示:
nINC := Var1 * 10000 + Var2; MSM(" SELECT X_AXIS"); //SELECT指令操作 MSM(" PINC nINC"); //PINC指令操作 MSM("LABEL1:"); //標籤LABEL1
依據MSM語言的規則,每行代碼的起頭若有含空白符號則表示為指令(Instruction),反之則為標籤(Label)。
2. 麻煩提供程式碼以及宣告的BOOL變數
3. 麻煩提供完整程式碼
1.MC_OPT是MSM基本指令,並非函式庫,剛測試一直都存在。
5.剛測試新增函式庫沒發現問題,要新增資料夾必須先將函式庫切換成編輯模式(若函式庫有密碼需先輸入密碼)
1.函式庫裡面找不到MC_OPT的指令
2.ST裡面如果我建立一個BOOL結構後,放在if 判斷式裡面編譯會錯誤
3.在ST裡面,打上 A := B AND (C = FALSE); 這樣編譯也不會過(我忘記C是不是結構了)
4.不能新增自訂的函示庫,不能新增自訂的函示庫,按右鍵”新增資料夾”是反白無法點選
剛測試:
1.MC_OPT是MSM基本指令,一直都存在。
4.新增函式庫測試正常,需切換成”編輯模式”(函式庫若有設定密碼需先輸入密碼)才可新增資料夾。