SCL(Structured Control Language,結構化控制語言)是一種基于 PASCAL 的高級編程語言。這種語言基于標準 DIN EN 61131-3(國際標準為 IEC 1131-3)。
根據該標準,可對用于可編程邏輯控制器的編程語言進行標準化。SCL 編程語言實現了該標準中定義的 ST 語言 (結構化文本) 的 PLCopen 初級水平。
S7-1200從V2.2版本開始支持SCL語言。
語言元素
SCL 除了包含 PLC 的典型元素(例如,輸入、輸出、定時器或存儲器位)外,還包含高級編程語言。
表達式
賦值運算
運算符
程序控制語句
SCL 提供了簡便的指令進行程序控制。例如,創建程序分支、循環或跳轉。
應用
因此,SCL 尤其適用于下列應用領域:
數據管理
過程優化
配方管理
數學計算 / 統計任務
表達式
說明:表達式將在程序運行期間進行運算,然后返回一個值。一個表達式由操作數(如常數、變量或函數調用)和與之搭配的操作符(如 *、/、+ 或 -)組成。通過運算符可以將表達式連接在一起或相互嵌套。
運算順序
表達式將按照下面因素定義的特定順序進行運算:
相關運算符的優先級,優先級數越小越優先
同等優先級運算符的運算順序按照從左到右的順序
賦值運算的計算按照從右到左的順序進行
括號優先級最高
表達式類型
不同的運算符,分別可使用以下不同類型的表達式:
算術表達式
關系表達式
邏輯表達式
算數表達式
說明:算術表達式既可以是一個數字值,也可以是由帶有算術運算符的兩個值或表達式組合而成。
算術運算符可以處理當前 CPU 所支持的各種數據類型。如果在該運算中有 2 個操作數,那么可根據以下條件來確定結果的數據類型:
如果這 2 個操作數均為有符號的整數,但長度不同,那么結果將采用長度較長的那個整數數據類型(例如,Int + DInt = DInt)。
如果這 2 個操作數均為無符號整數,但長度不同,那么結果將采用長度較長的那個整數數據類型(例如,USInt + UDInt = UDInt)。
如果一個操作數為有符號整數,另一個為無符號整數,那么結果將采用另一個長度較大的有符號數據類型(其包含此無符號整數)(例如,SInt + USInt = Int)
如果一個操作數為整數,另一個為浮點數,那么結果將采用浮點數的數據類型(例如,Int + Real = Real)。
如果 2 個操作數均為浮點數,但長度不同,結果將采用長度較長的那個浮點數的數據類型(例如,Real + LReal = LReal)。
對于操作數為"Time"和"日期和時間"數據類型組,運算結果的數據類型請參見表1。
算術表達式的數據類型
表1列出了在算術表達式中可使用的數據類型:
運算 | 運算符 | 優先級 | 第一個操作數 | 第二個操作數 | 結果 |
---|---|---|---|---|---|
乘方 | ** | 2 | 整數/浮點數 | 整數/浮點數 | 浮點數 |
正號 | + | 3 | 整數/浮點數 | - | 整數/浮點數 |
Time | Time | ||||
負號 | - | 整數/浮點數 | - | 整數/浮點數 | |
Time | Time | ||||
乘法 | * | 4 | 整數/浮點數 | 整數/浮點數 | 整數/浮點數 |
Time | 整數 | Time | |||
除法 | / | 整數/浮點數 | 整數/浮點數(≠0) | 整數/浮點數 | |
Time | 整數 | Time | |||
取模 | MOD | 整數 | 整數 | 整數 | |
加法 | + | 5 | 整數/浮點數 | 整數/浮點數 | 整數/浮點數 |
Time | Time | Time | |||
Time | DInt | Time | |||
TOD | Time | TOD | |||
TOD | DInt | TOD | |||
Date | TOD | DTL | |||
DTL | Time | DTL | |||
減法 | - | 整數/浮點數 | 整數/浮點數 | 整數/浮點數 | |
Time | Time | Time | |||
Time | DInt | Time | |||
TOD | Time | TOD | |||
TOD | DInt | TOD | |||
TOD | TOD | Time | |||
Date | Date | Time | |||
DTL | Time | DTL | |||
DTL | DTL | Time |
示例
以下為一些算術表達式的示例:
"MyTag1":= "MyTag2" * "MyTag3";
關系表達式
說明:關系表達式將兩個操作數的值或數據類型進行比較,然后得到一個布爾值。如果比較結果為真,則結果為 TRUE,否則為 FALSE。
關系運算符可以處理當前 CPU 所支持的各種數據類型。結果的數據類型始終為 Bool。
編寫關系表達式時,請注意以下規則:
以下數據類型組中的所有變量都可以進行比較:
整數/浮點數
位、位序列
字符串
對于以下數據類型,只能比較相同類型的變量:
TIME
日期和時間
UDT
Array
Struct
Variant
String 比較是對以 Windows 字符集編碼的字符進行比較;而 WSting比較則是對 UTF-16 編碼的字符進行比較。在比較過程中,將比較變量的長度及各字符對應的數值。
Array 比較需要數組維度、數組元素數據類型與數量完全相同
UDT、Array、Struct、Variant等進行的比較只能使用S7-1200 V4.2及其以上的版本。
關系表達式的數據類型
表2列出了在關系表達式中可使用的數據類型/數據類型組:
運算 | 運算符 | 優先級 | 第一個操作數 | 第二個操作數 | 結果 |
---|---|---|---|---|---|
小于、小于等于、大于、大于等于 | <、<=、>、>= | 6 | 整數/浮點數 | 整數/浮點數 | Bool |
位序列 | 位序列 | Bool | |||
字符串 | 字符串 | Bool | |||
Time | Time | Bool | |||
日期和時間 | 日期和時間 | Bool | |||
等于、不等于 | ==、<> | 7 | 整數/浮點數 | 整數/浮點數 | Bool |
位序列 | 位序列 | Bool | |||
字符串 | 字符串 | Bool | |||
Time | Time | Bool | |||
日期和時間 | 日期和時間 | Bool | |||
Variant | 任意數據類型 | Bool | |||
UDT | UDT | Bool | |||
Array | Array | Bool | |||
Struct | Struct | Bool |
示例
以下舉例說明了一個關系表達式:
IF a > b THEN c:= a;
IF A > 20 AND B < 20 THEN C:= TRUE;
IF A<>(B AND C) THEN C:= FALSE;
邏輯表達式
說明:邏輯表達式由兩個操作數和邏輯運算符(AND、OR 或 XOR)或取反操作數 (NOT) 組成。
邏輯運算符可以處理當前 CPU 所支持的各種數據類型。如果兩個操作數都是 Bool 數據類型,則邏輯表達式的結果也為 Bool數據類型。如果兩個操作數中至少有一個是位序列,則結果也為位序列而且結果是由最高操作數的類型決定。例如,當邏輯表達式的兩個操作數分別是 Byte 類型和 Word 類型時,結果為 Word類型。
邏輯表達式中一個操作數為 Bool類型而另一個為位序列時,必須先將 Bool類型的操作數顯式轉換為位序列類型。
邏輯表達式的數據類型
下表列出了邏輯表達式中可使用的數據類型:
運算 | 運算符 | 優先級 | 第一個操作數 | 第二個操作數 | 結果 |
---|---|---|---|---|---|
取反 | NOT | 3 | Bool | - | Bool |
求反碼 | 位序列 | - | 位序列 | ||
與 | AND、& | 8 | Bool | Bool | Bool |
位序列 | 位序列 | 位序列 | |||
異或 | XOR | 9 | Bool | Bool | Bool |
位序列 | 位序列 | 位序列 | |||
或 | OR | 10 | Bool | Bool | Bool |
位序列 | 位序列 | 位序列 |
示例
以下為一個邏輯表達式的示例:
IF "MyTag1" AND NOT "MyTag2" THEN c := a;
MyTag := A OR B;
賦值運算
定義:通過賦值運算,可以將一個表達式的值分配給一個變量。賦值表達式的左側為變量,右側為表達式的值。
函數名稱也可以作為表達式。賦值運算將調用該函數,并返回其函數值,賦給左側的變量。
賦值運算的數據類型取決于左邊變量的數據類型。右邊表達式的數據類型必須與該數據類型一致。
賦值運算的計算按照從右到左的順序進行。
可通過以下方式編程賦值運算:
單賦值運算:執行單賦值運算時,僅將一個表達式或變量分配給單個變量:
示例:a := b;
多賦值運算:執行多賦值運算時,一個指令中可執行多個賦值運算。
示例:a := b := c;
此時,將執行以下操作:
b := c;
a := b;
組合賦值運算:執行組合賦值運算時,可在賦值運算中組合使用操作符"+"、"-"、"*"和"/":
示例:a += b;
此時,將執行以下操作:
a := a + b;
也可多次組合賦值運算:
a += b += c *= d;
此時,將按以下順序執行賦值運算:
c := c * d;
b := b + c;
a := a + b;
示例
下表舉例說明了單賦值運算的操作:
"MyTag1" := "MyTag2"; | (* 變量賦值 *) |
"MyTag1" := "MyTag2" * "MyTag3"; | (* 表達式賦值 *) |
"MyTag" := "MyFC"(); | (* 調用一個函數,并將函數值賦給 "MyTag" 變量 *) |
#MyStruct.MyStructElement := "MyTag"; | (* 將一個變量賦值給一個結構元素 *) |
#MyArray[2] := "MyTag"; | (* 將一個變量賦值給一個 ARRAY 元素 *) |
"MyTag" := #MyArray[1,4]; | (* 將一個 ARRAY 元素賦值給一個變量 *) |
#MyString[2] := #MyOtherString[5]; | (* 將一個 STRING 元素賦給另一個 STRING 元素 *) |
下表舉例說明了多賦值運算的操作:
"MyTag1" := "MyTag2" := "MyTag3"; | (* 變量賦值 *) |
"MyTag1" := "MyTag2" := "MyTag3" * "MyTag4"; | (* 表達式賦值 *) |
"MyTag1" := "MyTag2" := "MyTag3 := "MyFC"(); | (* 調用一個函數,并將函數值賦值給變量 "MyTag1"、"MyTag1" 和 "MyTag1" *) |
#MyStruct.MyStructElement1 := #MyStruct.MyStructElement2 := "MyTag"; | (* 將一個變量賦值給兩個結構元素 *) |
#MyArray[2] := #MyArray[32] := "MyTag"; | (* 將一個變量賦值給兩個數組元素 *) |
"MyTag1" := "MyTag2" := #MyArray[1,4]; | (* 將一個數組元素賦值給兩個變量 *) |
#MyString[2] := #MyString[3]:= #MyOtherString[5]; | (* 將一個 STRING 元素賦值給兩個 STRING 元素 *) |
?
?
下表舉例說明了組合賦值運算的操作:
"MyTag1" += "MyTag2"; | (* "MyTag1" 和 "MyTag2" 相加,并將相加的結果賦值給 "MyTag1"。*) |
"MyTag1" -= "MyTag2" += "MyTag3"; | (* "MyTag2" 和 "MyTag3" 相加。將相加的結果賦值給操作數"MyTag2",再從 "MyTag1" 中減去"MyTag2",計算結果將賦值給 "MyTag1"。*) |
#MyArray[2] += #MyArray[32] += "MyTag"; | (* 數組元素 "MyArray[32]" 加上 "MyTag"。計算結果將賦值給 "MyArray[32]"。之后這個數組元素 "MyArray[32]" 與數組中另一個元素"MyArray[2]"相加,然后將結果分配給數組元素 "MyArray[2]"。在該運算中,相應的數據類型必需兼容。*) |
#MyStruct.MyStructElement1 /= #MyStruct.MyStructElement2 *= "MyTag"; | (* 結構化元素 "MyStructElement2" 乘以 "MyTag"。計算結果將賦值給 "MyStructElement2"。之后,將結構化元素 "MyStructElement1" 除以 "MyStructElement2",并將計算結果賦值給 "MyStructElement1"。在該運算中,相應的數據類型必需兼容。*) |
尋址與調用
尋址
SCL尋址分為符號尋址與地址尋址。
符號尋址
DB塊變量:"DB塊名稱"(."變量名稱")
PLC變量:變量名稱
局部變量:#變量名稱
地址尋址
DB塊變量:%DB塊號(.變量地址),TIA PORTAL軟件會判斷該地址有沒有對應符號名稱,如果有則立即轉換為符號名稱,沒有則保留絕對地址
PLC變量:%變量地址,TIA PORTAL軟件會判斷該地址有沒有對應符號名稱,如果有則立即轉換為符號名稱,沒有則新建符號名稱
Temp變量:SCL不支持非優化FC/FB的Temp變量的地址尋址
舉例:
? | ? | 符號名 | 說明 |
---|---|---|---|
符號尋址 | DB塊變量 | "MyDB".Variable.Static_1 | ? |
"MyDB".Array[0] | 訪問數組元素 | ||
"MyDB" | DB塊名作為參數 | ||
PLC變量 | "Start" | ? | |
局部變量 | #Input_1 | ? | |
#Temp_1.x0 | 變量名片段訪問 | ||
地址尋址 | DB塊變量 | %DB2.DBB1 | ? |
%DB2 | DB塊名作為參數,會立刻轉換為DB塊名 | ||
PLC變量 | %M100.0 | 會立刻轉換為"符號名" | |
%Q1.0:P | 會立刻轉換為"符號名":P |
調用
程序調用分為以下幾類:
FC調用
FB調用
FB多重背景調用
調用可以從指令列表或者項目樹程序塊中拖拽入程序編輯區域,也可以直接輸入。
FC調用
FC調用的格式是
"FC塊名稱"(輸入形參:=實參,輸出形參=>實參,輸入輸出形參:=實參...)
返回值:=“FC塊名稱”(輸入形參:=實參,輸出形參=>實參,輸入輸出形參:=實參...)
FC調用需要確保所有形參都有對應實參。如果沒有參數的FC也需要有括號。
如圖所示的例子;
圖1 FC調用
FB調用
FB調用的格式是
"背景數據塊名稱"(輸入形參:=實參,輸出形參=>實參,輸入輸出形參:=實參...)
一般情況下,FB的簡單數據類型形參可以沒有對應實參,復雜數據類型的輸入、輸出也可以沒有對應實參,所以FB可以隱藏或不隱藏不出現的形參。如果沒有參數的FB也需要有括號。
如圖2所示,顯示了一些FB調用的例子。
圖2 FB調用
如圖3所示,當FB的參數全部顯示,在背景數據塊右鍵可以激活"僅顯示分配的參數";當FB的參數只顯示了分配的參數時,在背景數據塊右鍵可以激活"顯示所有參數"。
圖3 顯示分配/所有參數
FB多重背景調用
FB多重背景調用的格式是
#多重背景(輸入形參:=實參,輸出形參=>實參,輸入輸出形參:=實參...)
#多重背景[索引](輸入形參:=實參,輸出形參=>實參,輸入輸出形參:=實參...)
一般情況下,FB的簡單數據類型形參可以沒有對應實參,復雜數據類型的輸入、輸出也可以沒有對應實參,所以FB可以隱藏或不隱藏不出現的形參。如果只有Static的FB也需要有括號。
如圖4所示,顯示了一些FB多重背景調用的例子。
圖4 FB多重背景調用
注意:
對于定時器和計數器的SCL調用,有特殊的格式,請參考鏈接:定時器、計數器。
新建SCL
有兩種方式新建SCL:
第一種是在新建塊,選擇OB/FC/FB后,設置語言為SCL,如圖5所示。
第二種是在LAD、FBD中直接插入SCL語言段,這需要TIA PORTAL V14及其以上的版本,如圖6所示。
圖5 新建SCL塊
①在項目樹中,找到PLC,然后展開程序塊,點擊"添加新塊"
②在彈出對話框中,選擇塊類型,可以是OB/FB/FC,
③選擇語言為SCL
圖6 在LAD中插入SCL段
區域與注釋
和LAD/FBD不同,LAD/FBD在程序編輯器是一段一段的,編輯器可以插入新的網絡段,每一個網絡段可以有各自的注釋。而SCL是文本語言,不分網絡段(LAD/FBD語言內增加SCL除外),需要用其他的方法來解決。
區間
從TIA PORTAL V14以后,增加區間功能,使用指令:
REGION 區間名稱
程序文本
END_REGION
可以在指令中間增加需要編寫的程序還不影響程序邏輯,并且支持嵌套。此外還可以像網絡段一樣收折疊來,如圖7所示。
圖7 區域
其中左邊為區間總覽,可以看出整體的結構
①使得程序或總覽全部展開
②使得程序或總覽全部折疊
③全部展開/折疊是針對總覽與程序還是只針對總覽,圖中為針對總覽與程序
④獨立展開/折疊程序
注釋
編輯器的空行,或者調用塊的右側均可以增加注釋,如圖8所示有兩種方式注釋:
第一種是://注釋內容
第二種是:(/*注釋內容*/)
可以在工具欄中利用按鈕整段注釋或取消注釋。此外從TIA PORTAL V16開始支持多語言注釋,使用指令(*多語言注釋內容*),具體參考多語言文檔。
圖8 注釋
①注釋掉選中段落
②對注釋掉的段落取消注釋
編輯:黃飛
?
評論