具体实施方式
在提供可编程逻辑控制器编程环境的软件系统中,将用户程序从LD程序转换为IL程序的实质,也就是将软件系统中表示LD程序的数据结构转换到表示IL程序的数据结构。因此在转换中存在的问题,一是确定表示LD和IL程序的合理数据结构;二是要找出一种将表示图形的数据结构转换为表示文本的数据结构的方法。
首先确定能够表示LD图形语言的数据结构LDDataStruct和IL文本语言的数据结构ILDataStruct,其次为了完成LDDataStruct和ILDataStruct两种数据结构间的转换,引入一种中间数据结构MidDataStruct,通过数据结构间的算法转换,MidDataStruct可以不丢失任何程序信息的表示LDDataStruct中的内容,也可以方便的转换为ILDataStruct数据结构。下面详细说明每种数据结构的内容和数据结构之间的转换方法。
1、数据结构
LD图形语言的数据结构-LDDataStruct
LD图形语言是由多个输入触点元件、输出触点元件和元件间的连接线组成,连接线也可以看作是一种元件,数据结构首先必须正确保存这些元件的类型和位置;其次,为了可以方便快速的识别元件间的逻辑关系,数据结构还应该保存元件之间的连接关系
根据上面对LD图形语言程序的保存需要,LD的数据结构由两个部分组成,一个是LD元件的集合,一个是元件之间连接点的集合,其中LD元件和连接点的数据结构表示如下:
LD程序的数据结构:
名称:LDDataStruct
成员:ArrayLDElem-LD元件集合,保存用户加入的所有LD元件
ArrayConnectPoint-LD元件间连接点集合,用户增删LD元件后,修改连接点的信息。
LD元件的数据结构:
名称:LDElemStruct
成员:nElemID-元件唯一ID号,整数型。
nType-LD元件类型(输入触点,输出触点,横线,竖线等),整数型。
strName-元件名称,如X0、Y0等,字符串型。
nRow-元件所在行,整数型。
nCol-元件所在列,整数型。
LeftConnectPoint-元件左边连接的连接点。
RightConnectPoint-元件右边连接的连接点。
bVisited-元件是否已经被处理。
连接点的数据结构:
名称:ConnectPointStruct
成员:ArrayLeftElems-连接点左边连接的LD元件集合,用数组保存,元件中不包含横线和竖线,连接线只起到延续连接点的作用。
ArrayRightElems-连接点右边连接的LD元件集合,用数组保存,元件中不包含横线和竖线,连接线只起到延续连接点的作用。
如图1所示,LD元件包括X0,X1,X2,Y0,竖线1,横线2,元件的连接点有A,A’,B,B’。A和A’通过竖线1连接,合并为一个连接点A,B和B’通过横线连接,合并为一个连接点B,因此只有两个实际的连接点A和B。
保存这个LD程序的数据结构LDDataStruct如下:
LDDataStruct:
ArrayLDElem={X0,X1,X2,Y0,竖线1,横线2}
ArrayConnectPoint={A,B}
其中各个LD元件的成员值为:
变量值 |
X0 |
X1 |
X2 |
Y0 |
竖线1 |
横线2 |
nType |
输入触点 |
输入触点 |
输入触点 |
输出线圈 |
竖线 |
横线 |
strName |
X0 |
X1 |
X2 |
Y0 |
无 |
无 |
nRow |
1 |
2 |
1 |
1 |
1 |
1 |
nCol |
1 |
1 |
2 |
4 |
2 |
3 |
LeftConnectPoint |
左母线 |
左母线 |
A |
B |
无 |
无 |
RightConnectPoint |
A |
A |
B |
无 |
无 |
无 |
各连接点的成员值为:
变量值 |
连接点A |
连接点B |
ArrayLeftElems |
X0,X1 |
X2 |
ArrayRightElems |
X2 |
Y0 |
2、IL文本语言的数据结构-ILDataStruct
IL语言是一种纯文本的编程方式,编写好的程序使用字符串就可以完全表示和保存了,因此IL语言的数据结构中仅包含一个字符串,如下:
名称:ILDataStruct
成员:strILProgText-IL程序文本,字符串型
如图1所示的LD程序用IL表示并且保存到数据结构中时,strILProgText的值为:
“LD X0
OR X1
AND X2
OUT Y0”
3、转换中的中间数据结构-MidDataStruct
LDDataStruct和ILDataStruct两种数据结构在用于表示图形编程语言和文本编程语言时具有简单直接的特点,但是两种数据结构相差太大,很难直接从LDDataStruct转换到ILDataStruct。为了完成转换,引入一种中间数据结构MidDataStruct作为中介。MidDataStruct是一个典型的二叉树结构,它适合表示LD图形程序中各个元件的连接和逻辑关系,所有的LD元件和元件之间的逻辑关系都可以在树的节点中表示。相连的LD元件可以用一棵树来表示,因此一个树的数组就可以表示一个完成的LD程序。通过遍历树的每个节点,可以方便的生成节点对应的IL代码,通过MidDataStruct,就可以将LD程序中的元件和逻辑关系同IL中的文本指令对应起来。
MidDataStruct是一种用二叉树表示的数据结构,它包含两个子数据结构,一个是树Tree,一个是树节点TreeNode,详细描述如下:
名称:MidDataStruct
成员:ArrayLDTree-用于表示LD程序的树的数组,Tree类型数组。
名称:Tree
成员:RootNode-树的根节点,TreeNode类型,通过对根节点的访问,可以遍历整个树的每个节点。
名称:TreeNode
成员:LeftChildNode-左子节点,TreeNode类型;
RightChildNode-右子节点,TreeNode类型;
nLogicType-左右子节点的逻辑类型(串联关系、并联关系、无关系),整数型;
LDElem-节点对应的LD元件结构,LDElemStruct类型;
LeftConnectPoint-节点左边连接的连接点;
RightConnectPoint-节点右边连接的连接点。
图1所示的LD程序用MidDataStruct中的树表示为图2所示,其中:+节点表示左右子节点为并联关系,*节点表示左右子节点为串联关系。
本发明的整个转换过程分为两步,首先是将用LDDataStruct表示的用户程序转换为MidDataStruct中的二叉树中,然后再将MidDataStruct中的二叉树转换为ILDataStruct中的文本,如图3所示。
下面详细说明两个转换过程的具体方法和步骤。
转换过程1,参阅图5A。
转换过程1的功能是将LDDataStruct中针对图形使用方式保存的程序数据,转换为MidDataStruct中使用二叉树针对LD元件逻辑关系保存的数据结构,它主要通过逐个读取LDDataStruct中的LD元件,分析该元件和其它元件的连接关系来生成元件对应的树节点和连接关系对应的树节点,整个分析过程也就是对LD图形逐级合并最简网络的过程,例如对图1所示的LD程序:
第一步读出X0元件。
第二步读出和X0相并联的元件X1,检查X1和前面元件的关系,X0和X1是一个最简网络,合并X0和X1,把它们并联的结果看成一个输入触点继续处理,如图4所示。
第三步读出合并后的触点“X0+X1”连接的X2,进一步合并,把和X2串联的结果看成是一个新的触点。
第四步读出合并后的触点“(X0+X1)*X2”连接的Y0,再次合并。
通过上面的逐级合并,可以把一个复杂的LD程序简化为一个最简的程序,从而达到处理整个LD程序的目的。
对LD程序的逐级合并和生成二叉树的操作详细说明如下:
在下面A~E的5个步骤中,A是一个大循环,每次找出一个LD网络的开始元件,循环完成A就是处理了所有的网络;D是一个小循环,每次找出和当前元件相连接的下一个元件,循环完D就是处理了当前的网络;步骤B和C用于将当前的元件和前面的元件在符合条件的情况下构成一个最简的并联或者串联网络。
A、判断是否有未处理的LD网络,如果是,则取出和左母线连接并且没有被处理的元件,创建包含该LD元件的树节点作为当前节点,进行步骤B,如果没有未处理LD网络,则整个处理完成,MidDataStruct的ArrayLDTree中包含了已经转换完成的所有树。
具体操作:
遍历LDDataStruct中的ArrayLDElem,取出LeftConnectPoint=左母线,bVisited=FALSE的LDDataStruct类型的LD元件,命名为NewLDElem;创建一个TreeNode型的节点CurTreeNode,其LDElem成员的值为NewLDElem,将LDElem的LeftConnectPoint和RightConnectPoint的值分别赋予CurTreeNode的LeftConnectPoint和RightConnectPoint。
B、如果当前节点和栈顶的节点是最简并联关系网络,则增加一个父节点,当前节点和栈顶的节点分别作为左右子节点,逻辑关系为并联关系,将父节点作为当前节点,重复B操作;如果不是则进行步骤C。
具体操作:
(1)如果当前节点CurTreeNode和栈顶节点PeekTreeNode的左右连接点LeftConnectPoint和RightConnectPoint相同,则两个节点中包含的LD元件是并联关系,不是并联关系则到步骤C。
(2)增加新的树节点NewTreeNode,弹出栈顶节点到PeekTreeNode,当前节点CurTreeNode和栈顶节点PeekTreeNode分别作为其左右子节点,NewTreeNode的nLogicType=并联关系。
(3)将CurTreeNode的LeftConnectPoint和RightConnectPoint的值分别赋予NewTreeNode的LeftConnectPoint和RightConnectPoint。
(4)将新的父节点NewTreeNode作为当前节点CurTreeNode,重复步骤B。
C、如果当前节点和栈顶的节点是最简串联关系网络,则增加一个父节点,当前节点和栈顶的节点分别作为左右子节点,逻辑关系为串联关系,将父节点作为当前节点,重复B操作,如不是则进行步骤D。
判断方法为:
(1)如果当前节点CurTreeNode的右连接点RightConnectPoint和栈顶节点的左连接点LeftConnectPoint相同,则两个节点中包含的LD元件是串联关系,继续步骤(2),如果不是串联关系则到步骤D。
(2)增加新的树节点NewTreeNode,弹出栈顶节点到PeekTreeNode,当前节点CurTreeNode和栈顶节点PeekTreeNode分别作为其左右子节点,NewTreeNode的nLogicType=串联关系。
(3)将CurTreeNode的左连接点LeftConnectPoint和PeekTreeNode的右连接点RightConnectPoint的值分别赋予NewTreeNode的LeftConnectPoint和RightConnectPoint。
(4)将新的父节点NewTreeNode作为当前节点CurTreeNode,重复步骤B。
D、将当前节点压栈,按照并联关系优先于串联关系的原则,取出和当前节点中的元件相连接未处理的LD元件,创建包含该LD元件的树节点作为当前节点,进行步骤B,如果LD元件都已经被处理则进行步骤E。具体处理过程如下:
(1)当前节点CurTreeNode压入栈中。
(2)遍历当前节点CurTreeNode的右连接点RightConnectPoint的ArrayLeftElems数组中每个LD元件,取出还没有被处理的LD元件,命名为NewLDElem,到下面的子步骤(4),此时的元件和栈中的元件是并联关系。如果ArrayLeftElems数组中的LD元件都已经被处理,到下面的步骤(3)。
(3)遍历当前节点CurTreeNode的右连接点RightConnectPoint的ArraRightElems数组中每个LD元件,取出还没有被处理的LD元件,命名为NewLDElem,到下面的步骤(4),此时的元件和栈中的元件是串联关系。如果ArrayLeftElems数组中的LD元件都已经被处理,当前LD网络程序已经处理完毕,到步骤E。
(4)创建一个TreeNode型的节点CurTreeNode,其LDElem成员的值为NewLDElem,将LDElem的LeftConnectPoint和RightConnectPoint的值分别赋予CurTreeNodeLeftConnectPoint和RightConnectPoint,到步骤B。
E、创建一个Tree类型的二叉树NewTree,其根节点为当前节点RootTreeNode=CurTreeNode,将NewTree加入到MidDataStruct的ArrayLDTree数组中;转到步骤A。
通过上面这些步骤地处理,已经将LDDataStruct数据结构中的LD图形程序,表示成了MidDataStruct数据结构中树的方式,下面进一步说明如何将MidDataStruct中保存为树的用户程序转换为ILDataStruct中的文本指令。
转换过程2,参阅图5B。
本转换的功能是将保存在MidDataStruct中的树转换为ILDataStruct中的文本指令,它主要通过遍历MidDataStruct中每棵树的每个树节点,根据节点中包含的LD元件的输入输出类型或者节点中包含的子节点的逻辑关系,生成相应的IL指令代码。
例如对图2所示的一棵树,遍历从根节点开始,采用左子节点->右子节点->父节点的遍历顺序,整个访问顺序如下:
X0→X1→+→X2→×→Y0→×
根据访问顺序,MidDataStruct中的树生成ILDataStruct中的文本的处理如下:
1、遍历MidDataStruct中ArrayLDTree的每棵树,如果没有未处理的树,则转换全部完成。
2、读取树的根节点作为被处理节点,进入步骤3处理该节点。
3、处理当前节点:
A、如果被处理节点有右子节点,递归调用步骤C处理右子节点。
B、如果被处理节点有左子节点,递归调用步骤C处理左子节点。
C、如果左右子节点不存在或者递归处理完毕,生成本节点的IL代码。
在不同的条件下生成IL代码的方法如下:
(1)如果节点没有子节点,是父节点的左子节点,包含的LD元件是输入触点,生成“LD元件名”指令;
(2)如果节点没有子节点,是父节点的右子节点,是输入触点,不生成指令;
(3)如果节点没有子节点,包含的LD元件是输出线圈,生成“OUT元件名”指令;
(4)如果节点有右子节点,右子节点包含的LD元件是输入触点,左右子节点的逻辑关系是“并联关系”,生成“OR元件名”指令。
(5)如果节点有右子节点,右子节点包含的LD元件是输入触点,左右子节点的逻辑关系是“串联关系”,生成“AND元件名”指令。
(6)如果节点有右子节点,右子节点没有包含LD元件,左右子节点的逻辑关系是“并联关系”,生成“ORB”块并联指令。
(7)如果节点有右子节点,右子节点没有包含LD元件,左右子节点的逻辑关系是“串联关系”,生成“ANB”块串联指令。
(8)如果节点有右子节点,包含的LD元件是输出线圈,不生成指令。
图2所示的树,按照遍历顺序,每个节点和生成的代码如下:
符合条件(1),生成“LD X0”;
符合条件(2),不生成指令;
符合条件(4),生成“OR X1”;
符合条件(2),不生成指令;
符合条件(5),生成“AND X2”;
符合条件(3),生成“OUT Y0”;
符合条件(8),不生成指令。
最终生成ILDataStruct中strILProgText的内容为:
“LD X0
OR X1
AND X2
OUT Y0”
到本转换过程完成,已经将一个LD图形程序对应的数据结构LDDataStruct,通过中间二叉树数据结构MidDataStruct,转换成为指令文本对应的数据结构ILDataStruct。LD图形程序用LDDataStruct保存,中间二叉树用MidDataStruct保存,IL指令文本用ILDataStruct保存。
根据上述的转换方法,本领域普通技术员据此不难得到一种将梯形图程序转换为指令列表程序的系统,该系统除包括一个用于处理数据的公知计算机装置外,还包括:第一装置,用于在计算装置中生成包含一个或多个网络的梯形图(LD)程序并保存到计算机的存储介质中。第二装置,用于生成LD程序中各网络内元件及其元件间连接关系的描述数据,形成各网络的LD元件集合和连接关系集合。第三装置,用于从各网络的LD元件集合中的一个元件开始,依据连接关系集合中描述的元件之间的连接关系遍历网络内的所有元件的描述数据,生成用节点的描述数据描述网络内元件之间的逻辑关系的二叉树。第四装置,用于从各二叉树的根节点开始遍历二叉树的所有节点,根据节点描述的逻辑关系生成各节点对应的指令列表(IL)程序命令,形成IL程序文本。
显然,本领域的技术人员可以对本发明进行各种改动和变型而不脱离本发明的精神和范围。这样,倘若对本发明的这些修改和变型属于本发明权利要求及其等同技术的范围之内,则本发明也意图包含这些改动和变型在内。