当前位置: 主页 > PLC控制

关于STEP7 Pointer指针的问题

////////////////////////////////buffer声明为pointer输入变量,DB_ID声明为word临时变量

LP##buffer///读取指针基址,父程序调用时,buffer=DB2.DBX0.0
LAR2///装入AR2
LW[AR2,P#0.0]///这时读取是到底是什么?一直没有搞清楚,仿真读是2,2是DB块号,但不知道为什么是2?我曾经有两种理解,一种理解是:在前述DB2中,读取以指针(基址+偏移)寻找到的字,就是在DB2中第0个字,似乎不对。另一种理解是:以指针(基址+偏移)作为一个双字数据,读取它的一个低字,这个低字包含DB号信息,但这个理解也说不通。两种理解似乎都不能与西门子的说法相符?西门子说pointer类型是6字节,而AR是4字节,6字节对4字节?
T#DB_ID///作为DB号
OPNDI[#DB_ID]///将这个DB作为背景数据块打开
LD[AR2,P#2.0]///此处也有同样的疑问?还有偏移量(+P#2.0)是以字节为单位加的,还是以前面数据宽度(比如双字D)为单位加的?
LAR2///装入AR2

以问题上希望前辈们解释一下,看过很多网上的解释和西门子的说法一直没搞清楚,头大了!

最佳答案

1:首先需要了解POINTER的结构POINTER是一个类似于C语言中指向指针的指针
见图1
POINTER类型占用6个字节,0-1字节是存放实参的DB号,2-5字节是存放地址指针。
LP##buffer///读取指针基址,父程序调用时,buffer=DB2.DBX0.0
LAR2///装入AR2
LW[AR2,P#0.0]//根据图中所示,0-1字节就是指向DB块号码(如果不是DB区,那么就是0)
//所以W[AR2,P#0.0]值是2,根据你的描述,你错误理解了POINTER的用法,POINTER不直接指向DB2里面的数据(所以叫它指向指针的指针)在系统调用子程序的时候有一个实参到形参的赋值过程。在你的程序里BUFFER就是形参,DB2.BDX0.0就是实参,父程序在调用子程序时,在实参到形参的参数赋值过程中会用到L堆栈(根据POINTER结构,把数据存放到L区中)。在子程序中,Lbuffer这句就是取出POINTER在L区中地址。LAR2就是把首地址存放到AR2中。
LW[AR2,P#0.0]可以理解成LLW[AR2,P#0.0],至于AR2指向L0.0还是L20.0这个是由PLC自己管理的,你不需要担心(假设系统在实参到形参的赋值用到了L20.0开始的6个字节)。实参DB2.DBX0.0中到BUFFER赋值的过程中就会按照POINTER的结构把相关的DB号信息和地址指针DBX0.0的值赋值到LB20-LB25中。
LBUFFER累加器中地址指针值为160(20*8)
LAR2AR2值为160
LW{AR2,P#0.0]就是LLW[AR2,P#0.0],AR2中的地址指针是20*8=160,所以相当于LLW20LW20中的值为2,为实参的DB号
OPNDI[#DB_ID]///将这个DB作为背景数据块打开打开DB2
LD[AR2,P#2.0]相当于LLD22,LD22中存放实参的DB2.DBX0.0的偏移地址DBX0.0
LAR2//注意这个时候AR2的值不在指向L20.0了,指向DBX0.0。

如果下面再有LW[AR2,P#2.0]就相当于LDB2.DBW2了,不在指向LW22了。

图片说明:

8d7dc7861b6b268e7fb59f304036e608关于STEP7 Pointer指针的问题

提问者对于答案的评价:
谢谢热心回答,明白了

补充一个问题:
LP##ABC
ABC除了声明为POINTER外,还能声明为其它类型吗?若有请举例回答。
(关于P##ABC我之前的理解是:P#(#ABC),#ABC是局部符号变量,前面P#是把后面的变量指针化,不知对否?)

专家置评

已阅,最佳答案正确。好需要了解变量的直接寻址和间接寻址、存储器间接寻址和寄存器间接寻址、寄存器内部区域间接寻址和交叉区域间接寻址等知识点。

  • 关注微信

猜你喜欢

微信公众号