技术论坛

 关于S7的一些杂谈

返回主题列表
作者 主题
面条
游侠

经验值:351
发帖数:63
精华帖:2
楼主    2008-05-24 18:31:09
主题:关于S7的一些杂谈 精华帖 
关于S7的一些杂谈

临时数据区,OB,FB和FC里的临时数据区的功能是一样的,程序每次执行时,临时数据的数据是不确定的,他属于动态数据,是由操作系统从数据栈里分配给FB的,程序退出后,要把这些数据内存归还给操作系统。
OB的临时数据的前20个字节是操作系统在调用OB是分配给OB的特殊区域,相当于OB的入口参数,每次系统调用OB时就会把相应的数据写在这20个字节里,我们的用户程序会根据这20个字节的特定数据处理自己要处理的问题,这里我以是OB40(硬件中断)为例,OB40_MDL_ADDR是触发中断的模块的逻辑基址,OB40_POINT_ADDR,指出哪个通道已超出哪条限制等,我们就可以根据这些数据编写我们的硬件中断处理程序。
首先,我简单的说说FB和FC的区别,FB是具有存储功能的,FC没有存储功能,这是一般的理解;FB需要背景数据块,而FC是没有的;参数的传递方式不同,FB的输入输出对应着背景数据块地址,而FC的输入输出是没有实际地址对应的,只有的程序调用时,才会和实际的地址产生对应关系。FB参数传递的是数据,FC参数传递的是数据的地址。
FB(功能块)的处理方式是围绕着数据块处理数据,他的入口参数和出口参数都是数据块里的数据,以及STAT的数据都是数据块里,入口参数和出口参数、STAT可以认为是静态数据,这些数据不会因为函数消失而逝去,他会一直保存在数据块里。FB里的变量与他的背景数据块是一一对应的,而他的对应并不是一层不变的。更确切的说,FB里的变量在调用时将根据AR2的值当作偏移量与背景数据块是一一对应。如果一个FB功能块里没有入口参数、出口参数及STAT数据,他将不需要背景数据块,这时的FB和没有入口出口参数的FC就没有什么区别了,就只能使用临时变量和全局变量了。
用很多人认为,FB的背景数据块必须由FB生成、FB里的第一个变量对应着背景数据块的第一个变量,还有就是由FB生成的数据块只能作为FB的背景数据块使用。其实这些理解是错误的,FB的背景数据块不一定是通过FB生成的,可以像生成共享数据块一样生成FB的背景数据块,换句话说,普通的数据块也可以作为FB的背景数据块,不过这种做法是有一定前提的,就是这个数据块的字节数必须大于等于FB所需的字节数,如果小于FB所需的字节数时,FB访问到超出背景数据块的变量时就会找不到变量的地址,肯定会出错了。FB里的第一个变量对应可以对应数据块字节数减去FB所需背景数据块字节数里的任意位置的变量,我觉得这个比较好理解,在多重背景里不就是这样吗。谈到这里我得说点别的,好像这种情况下,FB里不可以有多重背景,在S7里,多重背景好像是不允许嵌套的,说道这里我马上在S7做了测试,证明我的想法是错误的,多重背景是可以嵌套的。话回正题,由FB生成的数据块也是可以像访问普通数据块一样通过共享数据块方式访问,不信,你可以自己试一试。说说如何使用普通的数据块作为FB的背景数据块,会不会有人现在就开始自己试了,怎么不行呢,一调用程序就程序红色,有错误啊。告诉你,使用CALL指令编写时SETP7会自动检查DB块和FB的关系,要是时间标记和大小不一致就会报错。在这里我们可以使用UC指令调用FB,UC指令是不传递参数的(对于这个说法,我不太认同,我将会在使用UC调用FC时是如何传递参数一节讲述),那么我们如何将参数传递给FB呢?又如何将FB的输出读出来呢?
我在前面说过,背景数据块是可以像访问普通数据块一样使用共享数据块访问,这就解决了我们参数传递的问题。下面我给出一个例子大家看看:

使用UC调用FB
L PIW 290
T "tDIPd".PV_PER //"tDIPd"是"TCONT_CP"的背景数据块,我们在这里使用共享数据块方式对数据块写入数据
L MD 4
T DBD 34
A M 8.0
A DBX 42.0
A M 8.1
= DBX 42.1
//以上的是参数输入部分
LAR2 P#0.0 //该语句指名了FB和背景数据块的对应关系,就是FB的第一个参数对应背景数据的地址
CDB //交换共享数据块和背景数据块,将当前的共享数据块变为背景数据块
UC "TCONT_CP" //使用UC调用FB,FB的背景数据块就是上面打开的数据块即"tDIPd"
CDB //交换共享数据块和背景数据块,将当前的背景数据块变为共享数据块
//以下是参数输出部分
A DBX 42.0
= M 8.0
A DBX 42.1
= M 8.1
L DBW 22
T PQW 306
L DBD 34
T MD 4
//从上面我们可以看出DBX42.0、DBX42.1和DBD34是输入输出行数据

下面这段程序是使用传统的方法CALL调用FB
CALL "TCONT_CP" , "tDIPd"
PV_IN :=
PV_PER :=PIW290
DISV :=
INT_HPOS:=
INT_HNEG:=
SELECT :=
PV :=
LMN :=
LMN_PER :=PQW306
QPULSE :=
QLMN_HLM:=
QLMN_LLM:=
QC_ACT :=
CYCLE :=
CYCLE_P :=
SP_INT :=MD4
MAN :=
COM_RST :=M8.0
MAN_ON :=M8.1

上面这两段程序的执行效果是一样的,但是他们的写法和思路是完全不一样的,使用UC调用时,FB的输入输出参数的附值很自由,可以在程序的任何地方书写,没有条条框框的限制,而CALL就不同了,他给出了书写参数的位置。当然使用CALL时也可以使用共享数据块方式传递参数,但是这样就乱了,也没有这个必要。从中我们可以得到一个结论,FB的数据参数传递是通过数据块来传递的,而且数据块是静态的,所以我们给FB传递参数时,可以在任何地方都可以给FB传递参数。UC和CALL的区别还有,UC可以通过AR2修改FB参数与背景数据块的对应关系。而CALL指令是不行的。通过改变AR2的值使得对应关系产生偏移。

FC(功能),他是没有存储能力的,这是一般的说法,给定入口参数,执行完了,从出口参数读出数据,FC的功能就消失,就像C语言里的函数。如果在FC里使用全局数据(M区数据,数据块数据),那就会是另外一种效果。
上面说过,FC里的参数是没有实际地址的,使形式参数,只有在调用时才会把实际参数的地址传递到FC的参数里。
下面,我使用一个例子可以证明FC的参数传递的不是数据,而是地址,
建立一个FC如下:
FUNCTION "FC_DEMO" : WORD
TITLE =
VERSION : 0.1
VAR_INPUT
IN0 : WORD ;
END_VAR
VAR_OUTPUT
OUT1 : BYTE ;
END_VAR
BEGIN
NETWORK
TITLE =

L P##IN0;
LAR1 ;
L P##OUT1;
LAR1 ;
L P##RET_VAL;
LAR1 ;
END_FUNCTION

在OB1里调用该FC

CALL "FC_DEMO"
IN0 :=DBW0
RET_VAL:=LW20
OUT1 :=MB0

把程序下载到PLC里,监视FC_DEMO里的程序,打开AR1的监视
第2行里的AR1值是 DBX 0.0
第4行里的AR1值是 M 0.0
第6行里的AR1值是 V 20.0
注:V 指的是VL区的地址,既是先前的局部变量,也就是说先前未完成块的局部变量,在本段程序里指的就是调用"FC_DEMO"的OB1的局部变量

从这个程序我们可以看出,IN0的地址是DBW0 ,OUT1 的地址是MB0 ,RET_VAL 的地址是VLB20 。由此我们可以看出,在OB1调用"FC_DEMO"时并没有把实际参数的数据传递给"FC_DEMO"的参数里,而是把地址传递过去了。这时,在"FC_DEMO"里IN0的实际地址就是DBW0 , OUT1的实际地址就是MB0 , RET_VAL 的实际地址就是VLB20 .一般的,程序调用FC时,参数的传递就是传递变量的地址。但是还是有特殊情况的,在有传递的参数是立即数、指针Pointer和指针ANY时,情况就大不一样,还有就是将指定数据块编号的数据,在这种情况下,会将数据先传给一个局部变量,然后再把该局部变量的地址传递给FC的参数里.
从这个例子我们可以看出FC的参数实际就是一个指针,我们在调用FC时就给FC的这些指针附值,而这些指针又是隐含着的,姑且我们可以这样理解.
说了那么多,我就说说如何利用UC指令调用FC,UC指令调用FC与调用FB有本质的区别,FB的输入输出参数有实际地址,只要在调用前打开FB的背景数据块就可以了,而FC则不同,FC的输入输出参数没有实际地址,上面说了,他只是一个指针,我们必须初始化这些指针才行,那么我们如何初始化他呢,因为我们根本就不知道这些指针的地址在那里.所以我们不能使用UC直接调用FC,那样就不知道FC执行会影响那些数据,这样,我们的另寻方法了。
上面我们说过,UC指令是不能传递参数的,但是并不代表UC指令不能传递地址(SETP7手册没有关于这方面的文档资料),在实际中发现UC调用FC时可以传递地址,语句的格式是: UC FCx{addr1,addr2,...,addrn}; 这种使用方法只能在STL文本状态下使用,在非文本模式下无法书写,但是可以显示,在非文本下显示的格式是:
UC FCx
addr1
addr2
.
.
.
addrn
有了UC调用FC的传递地址格式,我们还要知道地址和我们FC的参数对应方法: 输入参数 --> 返回参数 --> 输出参数 --> 输入输出参数 .
有了上面的方法,我们可以使用UC来调用带参数的FC了,我们还是以上面的程序为例,在OB1中使用UC调用"FC_DEMO" ,
. //其他程序代码
UC "FC_DEMO" {P#DBX 0.0,P#L 20.0,P#M 0.0};
. //其他程序代码
编译后,在非文本模式下看OB1的代码,
. //其他程序代码
UC "FC_DEMO"
P#DBX 0.0
P#L 20.0
P#M 0.0
. //其他程序代码
我们把程序下载到PLC去执行,他的效果和使用CALL指令的效果是一样的。

从上面的分析,我说说使用CALL指令时,FB和FC的区别。在使用CALL指令调用FB时,我们可以不给FB的参数附值,这很显然,FB的参数是有实际地址的,他的地址就是背景数据块的地址。FB在运行时就会根据背景数据块进行计算了。而FC不行,他的参数没有实际地址,只有在调用时给他附值,要不然程序就不知道如何执行了。

总结,FB和FC的区别不仅仅只在有没有背景数据块,他们调用时是有本质的区别。
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。