找答案的高端用户(找答案钻石及双钻级别的用户)将尽可能从此问题下的所有回
答中,为您推荐最佳答案。届时您可以根据推荐数采纳答案。
如果自提问时间起7天内您仍无法选出最佳答案,您可以选择“无满意答案”关闭此问题。
L P##buffer ///读取指针基址,父程序调用时,buffer=DB2.DBX0.0
LAR2 ///装入AR2
L W [AR2,P#0.0] ///这时读取是到底是什么?一直没有搞清楚,仿真读的是2,2是DB块号,但不知道为什么是2?我曾经有两种理解,一种理解是:在前述DB2中,读取以指针(基址+偏移)寻找到的字,就是在DB2中第0个字,似乎不对。另一种理解是:以指针(基址+偏移)作为一个双字数据,读取它的一个低字,这个低字包含DB号信息,但这个理解也说不通。两种理解似乎都不能与西门子的说法相符?西门子说pointer类型是6字节,而AR是4字节,6字节对4字节?
T #DB_ID ///作为DB号
OPN DI [#DB_ID] ///将这个DB作为背景数据块打开
L D [AR2,P#2.0] ///此处也有同样的疑问?还有偏移量(+P#2.0)是以字节为单位加的,还是以前面数据宽度(比如双字D)为单位加的?
LAR2 ///装入AR2
以问题上希望前辈们解释一下,看过很多网上的解释和西门子的说法一直没搞清楚,头大了!
小程序查看
手机扫码追踪该问题
手机扫码追踪该问题,
觉得实用,立即去分享!
点击复制链接
1:首先需要了解 POINTER 的结构 POINTER是一个类似于C语言中指向指针的指针
见图1
POINTER 类型占用 6个字节,0-1字节是存放实参的DB号,2-5字节是存放 地址指针。
L P##buffer ///读取指针基址,父程序调用时,buffer=DB2.DBX0.0
LAR2 ///装入AR2
L W [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区中)。在子程序中,L buffer 这句 就是取出 POINTER在 L区中地址。LAR2就是把首地址 存放到AR2中。
L W[AR2,P#0.0] 可以理解成 L LW[AR2,P#0.0],至于AR2 指向L0.0还是L20.0 这个是由PLC自己管理的,你不需要担心(假设系统在实参到形参的赋值用到了 L20.0开始的6个字节)。实参DB2.DBX0.0 中到BUFFER赋值的过程中就会按照POINTER 的结构 把相关的DB号信息和地址指针DBX0.0的值 赋值到 LB20-LB25中。
L BUFFER 累加器中地址指针值为 160(20*8)
LAR2 AR2值为160
L W{AR2,P#0.0] 就是 L LW[AR2,P#0.0] ,AR2中的地址指针是 20*8=160,所以相当于 L LW20 LW20中的值为2,为实参的DB号
OPN DI [#DB_ID] ///将这个DB作为背景数据块打开 打开DB2
L D[AR2,P#2.0] 相当于 L LD22, LD22 中存放 实参的DB2.DBX0.0 的偏移地址 DBX0.0
LAR2 //注意这个时候 AR2的值 不在指向 L20.0 了,指向DBX0.0 。
如果下面 再有 L W[AR2,P#2.0] 就相当于 L DB2.DBW2了 ,不在指向LW22了。
首次回答问题,获得
双倍西币积分!
立即成为技术知识分享的一员!
找答案微信小程序
提问
搜索
欢迎您访问支持中心!
丰富的视频,全方位的文档,大量的网友交流精华……
为了更好的完善这些内容,我们诚邀您在浏览结束后,花20秒左右的时间,完成一个用户在线调查!
感谢您的支持!
更简单的 变量类型 比如 L P#M5.0 L P#DBX0.0 L P##L0.0
关于P##ABC我之前的理解是:P#(#ABC),#ABC是局部符号变量,前面P#是把后面的变量指针化,不知对否?)
可以这么理解。对 于 形参注意有个参数传递的过程是用到L区(实际上是V区,一种特殊的L区)
如果 对 FB STAT变量 进行 P##XXX,实际上就是取出XXX的偏移地址。