UM4003


UM4003 指令描述文件规范
   PDF格式完整版本下载

概述

在GUTTA平台中,每个PLC类型都有其对应的指令系统。在满足指令描述文件规范的前提下,每个PLC类型的指令系统可以完全相同,也可以相似,也可以完全不同。由于每种PLC类型对应的硬件不同、对应的应用场合不同,往往指令系统也不同。GUTTA编程软件并不关心每条指令的具体功能(具体功能由PLC固件实现),GUTTA编程软件关心的是每条指令的指令名称、形状(开关、线圈、功能块)、操作数的个数以及对每个操作数的限制、参与梯形图和指令表转换的规则等。因此,对于任何一个PLC系统,开发者必须提供一个指令描述文件。这个文件可以被GUTTA编程软件识别并记忆。不论是在PLC程序的编辑阶段,还是在PLC程序的编译阶段,GUTTA编程软件都是以这个指令系统为基础来工作的。

指令表指令

指令表指令的格式相对简单,它只有一种:

指令由指令名和若干操作数构成。对于某些不需要操作数的指令,操作数为空。

梯形图指令

开关形式

开关指令由指令名和若干操作数构成。由于开关图形的限制操作数的个数最多为2个。

线圈形式

线圈指令由指令名和若干操作数构成。由于线圈图形的限制操作数的个数最多为2个。

功能块形式

功能块指令由指令名、输入能流、入口操作数、出口操作数构成。输入能流的个数没有限制。对于某些不需要操作数的指令,操作数为空。

开关形式、线圈形式、功能块形式只是外在的表现,并不影响梯形图和指令表之间的转换。操作数的个数需要和PLC固件中的指令的参数个数保持一致,但也不参与梯形图和指令表之间的转换。在转换系统中,能流是转换的重要依据。根据能流的不同,转换系统认为有以下几种指令:

目前梯形图和指令表的转换系统不支持多能流输出的情况。需要特别注意的是,Input和MutiInput类型的线圈顾名思义,都是输入指令。输入指令意味着指令所有的操作数都只能用做输入变量。输入指令除了改变数据栈和辅助栈的值外,对PLC其它变量域不应有副作用。这是因为GUTTA梯形图和指令表的转换系统在进行转换时,只能保证Output和MutiOutput类型指令输入能流等于运行到当前指令的数据栈栈顶值,而不能保证Input和MutiInput类型指令栈顶值的正确性。这个时候如果输入指令具有副作用,结果将不可预测。(在CPU-EC20中,目前存在-|P|-和-|N|-这两种输入指令的例外。正跳变和负跳变开关都需要将前端能流的值保存到操作数中,即产生了副作用,这种行为需要用户在梯形图编程的时候注意,GUTTA转换不能确保其正确性)

操作数限制字符串

操作数限制字符串用来描述指令中某个操作数的可能正确输入。通过操作数限制字符串,GUTTA编程软件就可以知道当前的操作数的字符串是否合法,并在编辑或者编译的时候给出相应的提示。

操作数限制字符串的格式如下:

SectionWidth:[+/-:SecionRegion:SecionRegion:SecionRegion: ...]

方括号中的内容为可选。“+/-:”表示可能为“+:”和“-:”中的一种。“SectionWidth:”必须在最前面。“+/-:”后面的“SecionRegion:”可以重复出现多次。一旦“SectionWidth:”的后面有“+/-:”,那么后面至少紧跟一个“SecionRegion:”。

“SectionWidth:”段

“SectionWidth:”的格式如下:

W[c][a][v][p]:

W表示操作数的宽度,“T”表示宽度为位(1bit);“B”表示宽度为字节(8bit);“W”表示宽度为字(16bit);“D”表示宽度为双字(32bit)。

[c][a][v][p]都是可选的后缀,“c”表示可以为常数用法;“a”表示可以为地址用法;“v”表示可以为变量用法;“p”表示可以为指针用法。

例如“Bcv”表示这个操作数必须是一个长度为字节的值。这个值可以是一个立即常数(例如16#AF),也可以是一个字节变量(例如SMB20)。

例如“Davp”表示这个操作数必须是一个长度为双字的值。这个值可以是一个变量地址(例如&SMB20);也可以是一个变量(例如SMD30);也可以是一个指针(例如*MD100)。

“+/-:”段

“+/-:”要么为“+:”;要么为“-:”

“+:”表示后面的“SecionRegion:”是可能的区域用法。“-:”表示后面的“SecionRegion:”是必须排除的用法。

“SectionRegion:”段

“SectionRegion:”的格式如下:

R[c][a][v][p]:

R表示需要特别对待的区域名。可选的后缀[c][a][v][p]含义和SectionWidth:中一致。

例如“Bcv:+:Mv:” 表示这个操作数必须是一个长度为字节的值。这个值可以是一个立即常数(例如16#AF),也可以是一个字节变量。若为字节变量,这个变量必须在M区域内。(例如MB20合法,SMB20非法)。

例如“Wv:Tv”表示这个操作数必须是一个长度为字的值。这个值必须是一个变量,而且这个变量只能在T区域内(定时器区域)。

例如“Tcv:-:Iv:”表示这个操作数必须是一个长度为位的值。这个值可以是一个立即常数(0或1),也可以是一个位变量。若为位变量,这个变量不能在I区域内。(例如M10.0合法,I10.0非法)。

典型的指令描述文件一览

指令描述文件以XML(Extensible Markup Language)格式保存,一般保存在GUTTA Ladder软件安装文件夹中。在软件的安装文件夹中,有一个名为GuttaLad的子文件夹。在GuttaLad子文件夹中,又存在若干子文件夹,其中每一个子文件夹代表一种CPU配置。每个CPU配置下面分别有ManagerEnu和ManagerChs这两个子文件夹。这两个文件夹中的文件内容基本一致。只不过对应的语言选项不同。ManagerEnu对应的语言选项为英文,ManagerChs对应的语言选项为中文。如果不考虑多语言的支持,PLC的构建者可以让两个文件夹中的文件保持一致(直接拷贝)。软件GUTTA Ladder在启动时根据当前的语言选项,载入这两个文件夹中的其中一个。

指令描述文件就在这两个目录中,文件名为ManagerFun.xml。一个最简单的ManagerFun.xml看起来应该是这个样子的:

<ManagerFun>
 <!-- Bit Logic -->
 <FunOrg>
   <!-- S -->
   <Unit Name="S" Comment="" Parent="" Type="Output" Node="1">
     <Operand>
       <FunOperand Name="" Capacity="Tv:" Const="Bit"/>
     </Operand>
   </Unit>
 </FunOrg>
 <FunStl>
   <!-- S -->
   <Unit Name="S" Comment="Set" Parent="Bit Logic" Slot="15">
     <Operand>
       <FunOperand Name="BIT" Capacity="Tv:" Const="Bit"/>
     </Operand>
   </Unit>
 </FunStl>
 <FunLad>
   <!-- S "-(S)" -->
   <Unit Name="S" Comment="Set Coil" Parent="Bit Logic" Look="Coil" Keyword="S">
     <PowerIn>
       <FunPower Name=""/>
     </PowerIn>
     <OperandOut>
       <FunOperand Name="" Capacity="Tv:" Const="Bit"/>
     </OperandOut>
   </Unit>
 </FunLad>
 <ConvertStl>
   <Unit>
     <Left>
       <Item Name="S" Key="1"/>
     </Left>
     <Right>
       <Item Name="S" Key="1"/>
     </Right>
   </Unit>
 </ConvertStl>
 <ConvertLad>
   <Unit>
     <Left>
       <Item Name="S" Key="1"/>
     </Left>
     <Right>
       <Item Name="S" Key="1"/>
     </Right>
   </Unit>
 </ConvertLad>
</ManagerFun>

在这个XML文件中,根节点为ManagerFun,这个节点必须包含FunOrg、FunStl、FunLad、ConvertStl、ConvertLad这五种节点。FunOrg节点描述中间指令;FunStl节点描述指令表指令;FunLad节点描述梯形图指令。ConvertStl和ConvertLad用于描述指令表指令到中间指令和梯形图指令到中间指令的转换规则。上面的描述大致意思如下:

指令描述文件节点属性说明

<ManagerFun>节点

ManagerFun是指令描述文件的根节点。同时每个指令描述文件的根节点必须是ManagerFun。

<ManagerFun><FunOrg>节点

一个ManagerFun根节点应该包含至少一个FunOrg节点。FunOrg节点是当前PLC指令系统中中间指令的一个描述子集。ManagerFun也可以包含多个FunOrg节点。GUTTA编程软件最终会将这些子集中的中间指令描述合并在一个集合内。

<ManagerFun><FunOrg><Unit>节点

一个FunOrg节点应该包含至少一个Unit节点。每一个Unit节点代表一条中间指令的描述。

<ManagerFun><FunOrg><Unit>:Name属性

数据类型为STRING,长度不限。

Unit的Name属性定义当前中间指令的名称。由于中间指令不用于实际的编辑和表达,这个名称只在匹配转换时有效(指令表与中间指令的相互转换、梯形图与中间指令的相互转换)。需要注意的是,在所有的FunOrg中,不同的指令的Name不能相同。

<ManagerFun><FunOrg><Unit>:Comment属性

数据类型为STRING,长度不限。

Unit的Comment属性是对当前指令的一个描述。对读者来说是一个注释,以方便理解本指令的作用。简单的处理可以直接设为空字符串。设置时需要考虑当前变量描述文件所属的语言。

<ManagerFun><FunOrg><Unit>:Parent属性

数据类型为STRING,长度不限。

Unit的Parent属性是对当前指令所属子集的一个描述。

<ManagerFun><FunOrg><Unit>:Type属性

数据类型为STRING,可能的值有:“Input”、“MutiInput”、“Output”、“MutiOutput”、“Sys”。

Unit的Type属性定义当前指令的类型。

<ManagerFun><FunOrg><Unit>:Node属性

数据类型为INT。

Unit的Node属性定义当前指令的输入能流的数量。

<ManagerFun><FunOrg><Unit><Operand>节点

一个Unit节点可以包含一个Operand节点。每一个Operand节点代表当前指令的一组操作数。

<ManagerFun><FunOrg><Unit><Operand><FunOperand>节点

一个Operand节点可以包含若干个FunOperand节点。每一个FunOperand节点代表当前指令的一个操作数。

<ManagerFun><FunOrg><Unit><Operand><FunOperand>:Name属性

数据类型为STRING,长度不限。

Operand的Name属性定义当前操作数的名称。

(本属性定义对文件中的所有FunOperand节点适用。)

<ManagerFun><FunOrg><Unit><Operand><FunOperand>:Capacity属性

数据类型为STRING。

Operand的Capacity属性定义了当前操作数的操作数限制字符串(具体格式参考章节“操作数限制字符串”)。

(本属性定义对文件中的所有FunOperand节点适用。)

<ManagerFun><FunOrg><Unit><Operand><FunOperand>:Const属性

数据类型为STRING,可能的值有:“Bit”、“Byte”、“Word”、“Dword”、“Sint”、“Int”、“Dint”、“Usint”、“Uint”、“Udint”。

Operand的Const属性定义了当前指令以何种数据类型来操作变量的值。具体体现在在线调试时,操作数的二进制值通过通讯获得后,以何种数据类型来表达。

(本属性对文件中的所有FunOperand节点适用。)

<ManagerFun><FunStl>节点

一个ManagerFun根节点应该包含至少一个FunStl节点。FunStl节点是当前PLC指令系统中指令表指令的一个描述子集。ManagerFun也可以包含多个FunStl节点。GUTTA编程软件最终会将这些子集中的指令表指令描述合并在一个集合内。

<ManagerFun><FunStl><Unit>节点

一个FunStl节点应该包含至少一个Unit节点。每一个Unit节点代表一条指令表指令的描述。

<ManagerFun><FunStl><Unit>:Name属性

数据类型为STRING,长度不限。

Unit的Name属性定义当前指令表指令的名称。这个名称不但是指令表编辑时的指令名,也参与匹配转换(指令表与中间指令的相互转换)。需要注意的是,在所有的FunStl中,不同的Unit的Name不能相同。

<ManagerFun><FunStl><Unit>:Comment属性

数据类型为STRING,长度不限。

Unit的Comment属性是对当前指令的一个描述。对读者来说是一个注释,以方便理解本指令的作用。简单的处理可以直接设为空字符串。设置时需要考虑当前变量描述文件所属的语言。

<ManagerFun><FunStl><Unit>:Parent属性

数据类型为STRING,长度不限。

Unit的Parent属性是对当前指令所属子集的一个描述。

<ManagerFun><FunStl><Unit>:Slot属性

数据类型为INT。

Unit的Slot属性定义当前指令在PLC固件的识别码。

<ManagerFun><FunStl><Unit><Operand>节点

一个Unit节点可以包含一个Operand节点。每一个Operand代表当前指令的一组操作数。

<ManagerFun><FunStl><Unit><Operand><FunOperand>节点

一个Operand节点可以包含若干个FunOperand节点。每一个FunOperand节点代表当前指令的一个操作数。

<ManagerFun><FunLad>节点

一个ManagerFun根节点应该包含至少一个FunLad节点。FunLad节点是当前PLC指令系统中梯形图指令的一个描述子集。ManagerFun也可以包含多个FunLad节点。GUTTA编程软件最终会将这些子集中的梯形图指令描述合并在一个集合内。

<ManagerFun><FunLad><Unit>节点

一个FunLad节点应该包含至少一个Unit节点。每一个Unit节点代表一条梯形图指令的描述。

<ManagerFun><FunLad><Unit>:Name属性

数据类型为STRING,长度不限。

Unit的Name属性定义当前梯形图指令的名称。这个名称只在匹配转换时有效(梯形图与中间指令的相互转换)。需要注意的是,在所有的FunLad中,不同的指令的Name不能相同。

<ManagerFun>< FunLad ><Unit>:Comment属性

数据类型为STRING,长度不限。

Unit的Comment属性是对当前指令的一个描述。对读者来说是一个注释,以方便理解本指令的作用。简单的处理可以直接设为空字符串。设置时需要考虑当前变量描述文件所属的语言。

<ManagerFun><FunOrg><Unit>:Parent属性

数据类型为STRING,长度不限。

Unit的Parent属性是对当前指令所属子集的一个描述。

<ManagerFun><FunOrg><Unit>:Look属性

数据类型为STRING,可能的值有:“Cont”、“Coil”、“Block”。

Unit的Look属性定义当前指令的形状。

<ManagerFun><FunOrg><Unit>:Keyword属性

数据类型为STRING,长度不限。

Unit的Keyword属性定义当前指令的指令名(用于显示)。若指令为开关形状,指令名显示在开关中央。若指令为线圈形状,指令名显示在线圈中央。若指令为功能块形状,指令名显示在功能块的正上方。由于梯形图编辑时使用指令名加形状确定指令,故同一种形状下的不同指令,Keyword必须不同。

<ManagerFun><FunLad><Unit><PowerIn>节点

一个Unit节点可以包含一个PowerIn节点。每一个PowerIn节点代表当前指令的一组能流输入。

<ManagerFun><FunLad><Unit><PowerIn><FunPower>节点

一个PowerIn可以包含若干个FunPower节点。每一个FunPower节点代表当前指令的一个能流输入。

<ManagerFun><FunLad><Unit><PowerIn><FunPower>:Name属性

数据类型为STRING,长度不限。

FunPower的Name属性定义了当前输入能流的名称。若当前指令的形状是开关或线圈,Name不显示;若当前指令的形状是功能块,Name会显示在输入能流线的右侧。

<ManagerFun><FunLad><Unit><PowerOut>节点

一个Unit节点可以包含一个PowerOut节点。每一个PowerOut节点代表当前指令的一组能流输出。

<ManagerFun><FunLad><Unit><PowerOut><FunPower>节点

一个PowerOut可以包含若干个FunPower节点。每一个FunPower节点代表当前指令的一个能流输出。

<ManagerFun><FunLad><Unit><PowerOut ><FunPower>:Name属性

数据类型为STRING,长度不限。

FunPower的Name属性定义了当前输出能流的名称。若当前指令的形状是开关或线圈,Name不显示;若当前指令的形状是功能块,Name会显示在输出能流线的左侧。

<ManagerFun><FunLad><Unit><OperandId>节点

一个Unit节点可以包含一个OperandId节点。每一个OperandId节点代表当前指令的一组标识操作数。

<ManagerFun><FunLad><Unit><OperandId><FunOperand>节点

一个OperandId节点可以包含最多一个FunOperand节点。每一个FunOperand节点代表当前指令的一个标识操作数。

<ManagerFun><FunLad><Unit><OperandIn>节点

一个Unit节点可以包含一个OperandIn节点。每一个OperandIn节点代表当前指令的一组输入操作数。

<ManagerFun><FunLad><Unit><OperandIn><FunOperand>节点

一个OperandIn节点可以包含若干FunOperand节点。每一个FunOperand节点代表当前指令的一个输入操作数。

<ManagerFun><FunLad><Unit><OperandOut>节点

一个Unit节点可以包含一个OperandOut节点。每一个OperandOut节点代表当前指令的一组输出操作数。

<ManagerFun><FunLad><Unit><OperandOut ><FunOperand>节点

一个OperandOut节点可以包含若干FunOperand节点。每一个FunOperand节点代表当前指令的一个输出操作数。

<ManagerFun><ConvertStl>节点

一个ManagerFun根节点应该包含至少一个ConvertStl节点。ConvertStl节点定义了指令表指令(FunStl)到中间指令(FunOrg)的转换规则。

<ManagerFun><ConvertStl><Unit>节点

一个ConvertStl节点应该包含至少一个Unit节点。每一个Unit节点代表一种可能的转换(指令表指令与中间指令的互相转化)。每个Unit代表的转化都是对称可逆的(从Left节点到Right节点或从Right节点到Left节点)。

<ManagerFun><ConvertStl><Unit><Left>节点

一个Unit节点必须包含最多一个Left节点。Left节点代表可以被转化的指令表指令的一种组合。

<ManagerFun><ConvertStl><Unit><Left><Item>节点

一个Left节点应该包含最至少一个Item节点。Item节点代表可以被转化的指令表指令的一种组合中的一条指令。

<ManagerFun><ConvertStl><Unit><Left><Item>:Name属性

数据类型为STRING。

指令表指令的名称。

<ManagerFun><ConvertStl><Unit><Left><Item>:Key属性

数据类型为STRING,长度必须等于指令表指令操作数的个数。

指令表指令操作数的转换顺序。

<ManagerFun><ConvertStl><Unit><Right>节点

一个Unit节点必须包含最多一个Right节点。Right节点代表可以被转化的中间指令的一种组合。

<ManagerFun><ConvertStl><Unit><Right><Item>节点

一个Right节点应该包含最至少一个Item节点。Item节点代表可以被转化的中间指令的一种组合中的一条指令。

<ManagerFun><ConvertStl><Unit><Right><Item>:Name属性

数据类型为STRING。

中间指令的名称。

<ManagerFun><ConvertStl><Unit><Right><Item>:Key属性

数据类型为STRING,长度必须必须等于中间指令操作数的个数。

中间指令指令操作数的转换顺序。

<ManagerFun><ConvertLad>节点

一个ManagerFun根节点应该包含至少一个ConverLad节点。ConverLad节点定义了梯形图指令(FunLad)到中间指令(FunOrg)的转换规则。

<ManagerFun><ConvertLad><Unit>节点

一个ConvertLad节点应该包含至少一个Unit节点。每一个Unit节点代表一种可能的转换(梯形图指令与中间指令的相互转化)。每个Unit代表的转化都是对称可逆的(从Left节点到Right节点或从Right节点到Left节点)。

<ManagerFun><ConvertStl><Unit><Left>节点

一个Unit节点必须包含最多一个Left节点。Left节点代表可以被转化的梯形图指令的一种组合。

<ManagerFun><ConvertStl><Unit><Left><Item>节点

一个Left节点应该包含最至少一个Item节点。Item节点代表可以被转化的梯形图指令的一种组合中的一条指令。

<ManagerFun><ConvertStl><Unit><Left><Item>:Name属性

数据类型为STRING。

梯形图指令的名称。

<ManagerFun><ConvertStl><Unit><Left><Item>:Key属性

数据类型为STRING,长度必须等于梯形图指令操作数的个数。

梯形图指令操作数的转换顺序。

<ManagerFun><ConvertStl><Unit><Right>节点

一个Unit节点必须包含最多一个Right节点。Right节点代表可以被转化的中间指令的一种组合。

<ManagerFun><ConvertStl><Unit><Right><Item>节点

一个Right节点应该包含最至少一个Item节点。Item节点代表可以被转化的中间指令的一种组合中的一条指令。

<ManagerFun><ConvertStl><Unit><Right><Item>:Name属性

数据类型为STRING。

中间指令的名称。

<ManagerFun><ConvertStl><Unit><Right><Item>:Key属性

数据类型为STRING,长度必须必须等于中间指令操作数的个数。

中间指令指令操作数的转换顺序。

梯形图和指令表的相互转换

在GUTTA编程软件中,存在两种程序编辑模式。一种是指令表编程模式,一种是梯形图编程模式。软件在进行两种编程模式的相互转化时,还需要一种中间模式。指令表编程模式中的指令我们称之为指令表指令。梯形图编程模式中的指令我们称之为梯形图指令。中间模式下的指令我们称之为中间指令。转换流程如下图所示:

在进行转换的时候,会涉及到一些指令的合并与分解(例如一条指令表指令等效于多条中间指令、一条梯形图指令等效与多条中间指令等等)。在进行指令的合并与分解时,需要注意参数的顺序。

例如CPU-EC20中的加法梯形图指令:

就被分解成:
MOVW MW0, MW4
+I MW2, MW4

参考节点ConvertStl中的ADD_I定义:

   <Unit>
     <Left>
       <Item Name="MOVW" Key="13"/>
       <Item Name="+I" Key="23"/>
     </Left>
     <Right>
       <Item Name="ADD_I" Key="123"/>
     </Right>
   </Unit>

参考节点ConvertLad中的ADD_I定义:

   <Unit>
     <Left>
       <Item Name="ADD_D" Key="123"/>
     </Left>
     <Right>
       <Item Name="ADD_D" Key="123"/>
     </Right>
   </Unit>

可以知道,从梯形图指令“ADD_I”到中间指令时,没有被分解,且操作数是一一对应的(“123”等于“123”)。中间指令“ADD_I”到指令表指令“+I”时,发生了指令的分解(“123”被拆分成了“13”和“23”),对应的指令表指令为“MOVW”和“+I”。

附录

系统中间指令固定格式

<ManagerFun>
 <FunOrg>
   <!-- AND -->
   <Unit Name="AND" Comment="" Parent="" Type="Sys" Node="2">
     <Operand>
     </Operand>
   </Unit>
   <!-- OR -->
   <Unit Name="OR" Comment="" Parent="" Type="Sys" Node="2">
     <Operand>
     </Operand>
   </Unit>
   <!-- LPS -->
   <Unit Name="LPS" Comment="" Parent="" Type="Sys" Node="0">
     <Operand>
     </Operand>
   </Unit>
   <!-- LRD -->
   <Unit Name="LRD" Comment="" Parent="" Type="Sys" Node="1">
     <Operand>
     </Operand>
   </Unit>
   <!-- LPP -->
   <Unit Name="LPP" Comment="" Parent="" Type="Sys" Node="1">
     <Operand>
     </Operand>
   </Unit>
 </FunOrg>
</ManagerFun>