技术频道

西门子300 编程多个问题解答之七(131-150)

131:S7-300/400 PLC支持哪些寻址方式?

1)直接寻址

1.直接地址:例如I0.0,Q1.7,PIW256,PQW512,MD20,T15,C16,DB1.DBB10,L10.0等

2.符号寻址:例如qq,ww.aa等

2)间接寻址

1.存储器间接寻址:16位指针,例如OPN DB[MW2] 32位指针,例如A I[MD0]

2.寄存器间接寻址:32位指针,例如A I[AR1,P#0.0],A [AR1,P#0.0]

132:如何使用指针?

指针用来指向一个地址。使用这种寻址方式的优点在于可以在程序运行过程中实现变址。指针用于存储器间接寻址

程序中用于存储器间接寻址的语句包含一个指令、一个地址标识符、以及一个偏移量(偏移量必须在方括号内给出)。

下面给出一个双字格式的指针的例子:

L P#8.7 把指针值装载到累加器1

T I[MD2] 把指针值传送到MD2

A I[MD2] 查询I8.7的信号状态

= Q[MD2] 给输出位Q8.7赋值

存储区域内部寻址及交叉寻址:程序中采用这些寻址方式的语句包含一个指令以及下列内容:地址标识符、地址寄存器标识符、偏移量。地址

寄存器(AR1、AR2)及偏移量必须写在方括号内。

存储区域内部寻址例程:指针不包含指示存储区域的信息:

L P#8.7 把指针值装载到累加器1

LAR1 把指针从累加器1装载到AR1

A I[AR1,P#0.0] 查询I8.7的信号状态

= Q[AR1,P#1.1] 给输出位Q10.0赋值

偏移量0.0不起作用。输出Q10.0 等于8.7 (AR1) 加偏移量1.1。结果是10.0 ,而不是9.8。

存储区域交叉寻址例程:在存储区域交叉寻址中,指针中包含指示存储区域的信息(例子中为 I 和 Q)。

L P#I8.7 把指针值及存储区域标识装载到累加器1

LAR1 把存储区域I 和地址8.7装载到AR1

L P#Q8.7 把指针值和地址标识符装载到累加器1

LAR2 把存储区域Q和地址8.7装载到AR2

A [AR1,P#0.0] 查询输入位I8.7的信号状态

= [AR2,P#1.1] 给输出位Q10.0赋值

偏移量0.0不起作用。输出Q10.0 等于8.7 (AR2) 加偏移量1.1。结果是10.0 ,而不是9.8,

133.如何用一个变量作索引实现在一个域中读一个元素或写一个元素?

一个域(数据类型为ARRAY)是几个相同数据元素的连接。在源代码中一个单空间域的声明执行如下:

My_Array: ARRAY[4..11] OF INT;

它标识了一个数据类型为“INTEGER”的8(=11-4+1)元素单空间域。

为了访问域中的一个元素,输入域名并在方括号中输入希望访问的元素的号码,比如:My_Array[6]。

在S7-SCL (结构化控制语言- 符合IEC 1131-3 的结构化文本)可以使用变量做索引:

i:INT:=46

My_Array[i]:=0

在FBD/LAD/STL中,索引必须是个常量,因此限制了可使用的域的范围。

134:怎样访问复合数据类型数组单元的变量?

复合数据类型数组单元中的变量只有通过单独的函数才能访问。作为传送参数这个函数拥有期望的数组数量并以数组[0]作为起始地址。对此函数的要求是数组置于一个数据块中并且数组[0]不被当前数据使用。这就决定了从参数传送来的地址并将指定的数组拷贝到作为处理区的数组[0]。接下来可对数组进行符号处理。然后它被拷贝回原始的数组号。

首先用这些参数定义并计算数组[0]的地址和要处理的数组数量。将这些值保存在函数的临时变量内。

L P##Field_Start // 输入地址域[0]

LAR1

L D [AR1,P#0.0] // 把这些地址保存在类型为ANY的临时变量中

T LD 0 // temp 'firststruc' = LD 0-9

T LD 10 // temp 'sourcestruc' = LD 10-19

L D [AR1,P#4.0]

T LD 4

T LD 14

L W [AR1,P#8.0]

T LW 8

T LW 18

L LD 16 // 定义期望数组的地址

LAR1

L #Indices

L LW 12

*I

SLD 3

+AR1

TAR1 LD 16

然后用SFC20 (BLKMOV)将要处理的数组拷贝到数组[0]。就可以根据应用需求,对索引数组通过符号访问。然后用SFC20 (BLKMOV)将数组[0]拷贝回原始区域。

135:能否在STEP 7中使用间接寻址编写循环程序?

可以,间接寻址允许寻址地址在程序运行期间才可以确定的操作数。这意味着,程序的一部分可以重复执行。在每个运行周期内,循环编程为所使用的操作数分配不同的地址。

136:ANY指针类型的参数如何被传送出块边界?

下面的例子解释了系统功能块SFC50“RD_LGADR”(读模块逻辑地址)内参数的确定。例如,为功能块FB1编程可分为下面几个步骤:

?声明一个IN变量“test”和一个TEMP变量“test2”,类型都为ANY(图1)。

?将SFC50的参数“PEADDR”传送到变量“test2”。

?通过为ANY指针“test”赋值,将数据传送到临时变量“test2”中。

语句L P##test首先将地址装载到Accu1,然后通过LAR1语句装载到地址寄存器AR1中(可能是LAR1 P##test的简化格式)。通过寄存器间接寻址将ANY指针(10 字节长)中的地址信息读出:

代码注释

0 L W[AR1,P#0.0] 读出当前Accu1中参数数据类型的代码。

2 L W[AR1,P#2.0] 读出Accu1中的重复因数。重复因数表明通过参数类型ANY传递的数据类型的大小。

4 L W[AR1,P#4.0] 读数据块的号或者从ANY指针中读出“0”(这个对应于ANY指针的第 4 到第 5 字节)。

6 L D[AR1, P#6.0] 将区域指针读入Accu1。

每次读地址寄存器AR1之后,数据被保存或者缓存(如T LW 0)在临时变量“test2”中(ANY指针)。按照Network 1中的语句顺序,传送到功能块FB1 的ANY指针被复制到临时变量“test2”中。

137:怎样通过交叉区域寄存器间接寻址访问功能块的本地数据或者功能?

这里必须预先定义本地数据。您可以使用下列语句访问FB或FC的本地数据:

对于存储器间接指针寻址,本地变量必须声明为临时变量(temp):

L P##Lokalvariable

LAR1

L W[AR1,P#X.x]

此处不能使用变量类型“Input”、“Output”和“In_Out”,将被语法检查视为非法。

138:怎样编程间接访问一个ARRAY类型变量的元素?

一个位、字节或者字符域的尺寸是按照字节限制排列的——在所有其它情况下是按照字对齐的。表T6-1中给出了一个域的存储示例。操作系统计算域中单个元素末端位置的位地址。域被分配到从下一个字地址(或字节地址)。下一个数据类型从下一个整字开始(或者整字节).

声明部分:

在声明部分,必须定义一个与将被间接寻址的ARRAY有着同一结构的ARRAY。不一定非要将ARRAY声明为IN-OUT变量;也可以声明为TEMP、IN或OUT变量。

网络:

域宽度(OFFSET)在网络中定义。ARRAY中的单个元素的最小常规数据宽度是一个字节;即使在两个变量之间定义一个BOOL。有必要确定相关的域的宽度和确定下一个期望域的起始地址。可使用下面的算法:

地址(指数):b = 元素长度*(指数 - 1)

创建具有不同数据类型的结构时,必须注意,在特定的环境下可能会自动插入填充字节。

保存ARRAY数据类型:

示例:ARRAY [1..2,1..3] OF 整数将生成下列域:

多维域是按照顺序保存的。在本例中整数 [1,1]后面是整数 [1,2],整数 [1,3]后面是整数[2,1]。

139:STEP 7 以哪种格式存储POINTER参数类型?

STEP 7以 6 个字节保存POINTER参数。表4-1显示了用于保存POINTER参数类型的内存区域以及每个字节中保存的数据。i POINTER参数类型保存了下列信息:

DB号(如果DB中没有保存任何数据时为0)。

CPU中的内存区域(表格中列出了不同内存区域的十六进制代码)。

数据的地址(按照Byte.Bit格式)。

如果将形式参数声明为POINTER参数类型,则只需要指定内存区域和地址。STEP 7自动将输入项目的格式转换为指针格式。

140:如何间接访问I/O地址区域?

下面演示了一个间接访问PA区域的例子。您具有对输出模块只写访问和对输入模块只读访问的权利

FUNCTION_BLOCK FB 2

TITLE =

VERSION : 0.1

VAR_INPUT

TargetAddress : DWORD := DW#16#FF; //Target address by PA address range

OutputValue : DWORD ; //Output value

P_Typ : BOOL ; //1=PE range, 0=PA range

END_VAR

VAR_OUTPUT

InputValue : DWORD ; //Input value

END_VAR

VAR_TEMP

TargetTmp : DWORD ;

END_VAR

BEGIN

NETWORK

TITLE =

U #P_Typ;

SPB PEA;

L #TargetAddress;

T #TargetTmp; //Load target address in the tempor鋜e store

SLD 3; //Calculate the formate of pointer Byte.Bit

T #TargetTmp; //Initialisation of temp variable with target address in L-Stack

L #OutputValue; //Load output value

T PAD [#TargetTmp]; //Transfere output value to target address

SPA End;

PEA: L #TargetAddress;

T #TargetTmp; //Load target address in the tempor鋜e store

SLD 3; //Calculate the formate of pointer Byte.Bit

T #TargetTmp; //Initialisation of temp variable with target address in L-Stack

L PED [#TargetTmp]; //Load output value

T #OutputValue; //Transfere output value to target address

End: CLR ;

END_FUNCTION_BLOCK

141:应用软件冗余当一个长度错误出现导致CPU处于STOP模式应该作些什么?

当在OB100中设置软件冗余功能块FC100时,必须注意下列情况:参数IEC_NO 的背景数据块必须至少有两个字的长度,同样应用于冗余用户程序的参数DB_NO的数据块也必须时这样。

142:在S7程序中,有许多FC、FB块, 我怎样对其中的一些块进行保护, 而其它的块可以是开放的呢?

1) Step7中, 可以先任意打开一块如OB1, 在"file"中选择"Generate Source"或快捷方式"Ctrl+T",弹出一个画面,填写"object name"如"tt",然后按OK确认,就会再弹出另一个画面,左边是你的程序中所有的块,如果你需要保护哪些块, 就把这些块移到右边,如FB1、FB2等等, 然后退出所有的程序块,再进入SIMATIC Manager中。

2) 在S7 Program Sources找到文件tt,双击tt打开,在第四行中加入"Know_How_Protect", 然后编译, 无错后存盘。这样FB1、FB2就被保护住,如想去掉保护,在tt中去掉"Know_How_Protect"编译存盘即可。

注意: 千万不要丢失或删除源文件(如tt), 否则程序被保护, 用户可以另存到其它目录中,或Export Source到硬盘中,再删除源文件,这样别人只能看到未保护的块。

143:SFB41,SFB42,SFB43和FB41,FB42,FB43的区别?

SFB41(CONT_C),SFB42(CONT_S),SFB43(PULSEGEN)块和FB41(CONT_C),FB42(CONT_S),FB43(PULSEGEN)的区别:SFB41,42,43与FB41,42,43的参数设置是一样的。SFB41,42,43只能用于CPU314IFM;FB41,42,43可用于CPU313以上的CPU(除CPU314IFM),因为SFB41,42,43集成于CPU314IFM中,而在普通CPU中没有这些块。

144:如何在多例兼容功能块中找到变量地址?

在多例兼容功能块中,为块参数和静态本地数据加载与地址寄存器AR2有关的绝对地址。如果要在情景数据块中找到变量的绝对地址,则必须把域内指针(只是AR2的地址)加载到变量地址。

样例:

TAR2 //将地址寄存器加载到累加器AC1(偏移量)

UD DW#16#00FF_FFFF // 关闭区域ID

L P##variable //加载变量地址

+D // 增加偏移量和变量地址

LAR1 // 保存地址寄存器AR1中的结果

这样可在AR1中获得绝对地址以进行进一步处理。

当功能块作为本地实例调用时,总要使用该方法。比如,在一个功能块中创建可做为类型“FB”的静态变量的功能块。这样所调用的情景数据块的数据偏移量就存储到情景数据块中。单个实例的偏移量在AR2中。如果不调用作为本地实例的功能块,则可以结束计算。值‘0’就在地址寄存器中。

注意事项:如果改变程序中的地址寄存器AR2,那么也改变了变量的偏移量地址。因此就不能保证再对变量进行正确访问。在这种情况下,必须预先保存AR2,并在对程序动作完之后将其复位为初始状态。

样例:

TAR2 // 在累加器中加载偏移量地址

T #save // 比如,静态本地数据域 0中的变量

L DID 0 // 地址绝对是由DI加载的beds<Y

L AR2 // 核对

145:怎样才能访问上一函数的本地数据?

如要访问以前的本地数据(“V-e > L”数据),可以传送一自创建ANY指针或绝对地址到被调用的FC。如果传送的是自创建ANY指针,区域指针会指向其本地数据,而这是无意义的。> 因此“V”区域码必须置于ANY指针中。此码必须准确传送。当指定绝对地址时可由编译器完成此工作。

常规程序结构:

以ANY指针或绝对(地址)方式传送:

LAR1 P##target //本地定义的ANY变量初始地址

L W#16#87 //为“V”区域载入码

T LB[AR1,P#6.0] //传送到ANY变量

CALL FCxy

source1: = #target //传送自创建的ANY指针

source2: = P#L 0.0 BYTE 8 //传送完全L数据区

绝对寻址与通过ANY指针寻址的区别:

下图显示了绝对寻址与通过自创建ANY指针寻址间的区别。在这种情况下“87”码不传送,因此ANY指针指向其本地区域。

146:怎样在DB内进行间接寻址?

请参照:

在DB内进行间接寻址例子

147:下面是一个在STEP7软件中实现简单指针寻址的例子程序,您可以参考它的结构实现您的指针寻址功能?

siemens指针寻址例子_cpu315

148:绝对地址和符号寻址的定义和区别是什么?

在STEP 7程序中要用到I/O信号、位寄存器、计数器、定时器、数据块及功能块。在程序中可以采用直接地址,或者更便于读程序的符号寻址,例如Motor_A_On,或采用你的公司或行业常用的代码。这样在你的用户程序中就可以通过符号来寻址。

绝对地址:绝对地址由地址标识符和存储器的位置组成,例如Q1.0,I1.1,M2.0, FB21等。

符号地址:如果为绝对地址指定一个符号名,程序会更便于阅读和查错。

STEP 7 可以自动将符号名翻译成所需的绝对地址。如果要用符号名存取ARRAY、STRUCT、数据块、局部数据、逻辑块、以及用户自定义数据类型,必须首先为绝对地址指定一个符号名。

例如,可以为Q0.0 指定一个符号名MOTOR_ON,然后在程序中将MOTOR_ON作为一个地址使用。使用符号地址更容易将您的过程控制项目中的元件与程序中的元件相对应。

注意:在符号名中不允许使用两个连续的下划线,例如MOTOR__ON。

编程支持:LAD、FBD、STL中地址、参数、块名可用绝对地址或符号表示。

用菜单命令View > Display > Symbolic Representation,可以切换绝对地址和符号地址

为了使用符号地址编程更加容易,可以同时显示绝对地址和符号名。使用菜单命令 View > Display > Symbol Information来激活。这就意味着STL语句的注释包含了更多的信息。不能在该界面下进行修改,只能在符号表(symbol table)或变量声明表(variable declaration table)中进行修改。

149:S7-300/400系统存储区域共有多少种?

S7 CPU的系统存储区域分为下表中列出的地址区域。在程序中可以根据相应的地址直接读取数据。

150:如何把一个DATE_AND_TIME变量转换为STRING变量?

为了以日期/时间字符串(STRING)形式显示DATE_AND_TIME变量,必须DATE_AND_TIME 变量的专用字节转换为相应的CHAR字符。

读取DATE_AND_TIME 变量的专用字节并从这两位数所在ASCII码中创建专用位。将确定了的CHAR字符存储在字符串的期望位置。

示例:

L 字节年

SLD 12

SRW 4

SRD 8

L W#16#3030

+ I

T 数字字符年

也可以用相反顺序将一个STRING格式的日期/时间字符串转换为一个DATE_AND_TIME变量

文章版权归西部工控xbgk所有,未经许可不得转载。