故事作者:空果仁

最近创作

看看TA的故事

【5】寄存器间接寻址——从S7-300_400到S7-1500看变址寻址的改变系列故事之五

已锁定

空果仁

官方工程师 西门子1847工业学习平台

  • 帖子

    210
  • 精华

    47
  • 被关注

    326

论坛等级:侠圣

注册时间:2011-07-11

普通 普通 如何晋级?

【5】寄存器间接寻址——从S7-300_400到S7-1500看变址寻址的改变系列故事之五

13258

6

2020-03-17 20:27:05

star star star star

2 寄存器间接寻址

       与存储器间接寻址不同,寄存器间接寻址使用CPU内部集成的两个32位地址寄存器AR1、AR2存储地址指针。寄存器间接寻址分为32位内部区域指针和32位交叉区域指针。

2.1  访问地址寄存器AR1、AR2的指令

       寄存器的访问需要使用特殊的指令。指令如下所示:

       LAR1     : 将ACCU1存储的地址指针写入AR1。

       LAR1 <D> : 将指明的地址指针写入AR1,例如LAR1 P#20.0或LAR1 MD20。

       LAR1 AR2 : 将AR2的内容写入AR1。

       LAR2     : 将ACCU1存储的地址指针写入AR2。

       LAR2 <D> : 将指明的地址指针写入AR2,与LAR1 <D>方式相同。

       TAR1     :  将AR1存储的地址指针传输给ACCU1。

       TAR1<D>  :  将AR1存储的地址指针传输给指明的变量中。

       TAR1 AR2 :  将AR1存储的地址指针传输给ACCU2。

       TAR2     :  将AR2存储的地址指针传输给ACCU1。

       TAR2 <D> :  将AR1存储的地址指针传输给指明的变量中。

       CAR      :  交换AR1和AR2的内容。

2.2  使用地址寄存器AR1、AR2的限制

       都是32位指针,为什么不使用存储器替代CPU内部的地址寄存器呢?使用方法上完全可以,除此之外,CPU还利用AR1、AR2做了一些系统内部的工作,如果没有AR1、AR2将造成程序的混乱(这节内容是引深介绍,不感兴趣可以跳过)。同样系统和用户都可以使用AR1、AR2,用户使用时需要考虑是否系统也在使用,否则也将造成程序的混乱,同时也不能改写。所以用户使用时会有限制,例如接口参数的传递中,STEP7使用地址寄存器AR1访问函数FC接口及函数块FB“INOUT”接口中定义的复合类型参数,如ARRAY、STRUCT、DATE_AND_TIME等,AR1和DB块寄存器中的内容将被覆盖,例如在FC1中“IN”接口中定义一个数组变量,在OB1中调用,使用OB1的L区域数据进行赋值,调用关系如图12所示。


图12

       如果在FC1中访问数组变量的元素如ARR_TEST[1],地址寄存器AR1及DB块寄存器会发生变化,示例程序如图13所示。


图13

       图13示例程序中前两条语句中打开DB1并将P#20.0装载到AR1中,在第三条语句访问数组的一个元素后AR1存储的地址指针变为P# V20.0(指向OB1中实参ARR_TEST的地址,参考图13),程序下传到CPU后将出现故障报警。将程序的执行次序进行修改,CPU即可运行,修改后的程序如下:

                     L     #ARR_TEST[1]      //装载形参变量ARR_TEST[1]到累加器1中。

                     OPN   DB     1          //打开DB1

                     LAR1  P#20.0            //将P#20.0装载到地址寄存器AR1中。

                     T     DBW [AR1,P#0.0]   //将累加器1中的值传送到DB1.DBW20中。

      AR2和DI寄存器分别包含FB背景数据块的块号及在背景数据在背景数据块中偏移地址(多重背景数据块),在FB中使用AR2和DI寄存器将会覆盖系统存储的内容。如果必须在FB中使用AR2和DI寄存器,建议使用下面的方法处理AR2和DI寄存器,首先保存AR2和DI寄存器中的数据,程序如下:

 

                     TAR2  MD   100         //将AR2的数据存储于MD100中。

                     L     DINO             //将背景DB块块号存储于MW104中。

                     T     MW   104

       ///////用户程序///////////////      

       然后编写用户程序,可以对AR2和DI寄存器进行操作,但是在程序中不能访问FB参数或静态变量。使用完成后恢复AR2和DI寄存器的系统值,程序如下:

 

                     LAR2  MD   100         //将MD100中存储的地址指针装载到AR2中。

                     OPN   DI [MW 104]      //打开DI数据块。

2.3   寄存器32位内部区域指针

       寄存器32位内部区域指针用于I、Q、M、L、数据块等存储器中位、字节、字及双字的寻址,与32位存储器指针使用相同,不同之处只是指针存储的位置不同(几乎没有区别,就是表示格式不同)。32位内部区域地址指针的格式如图14所示。


图14

       第0位~第2位作为寻址操作的位地址,第3位~第18位作为寻址操作的字节地址,第19位~第30位没有定义,第31为内部区域与交叉区域指针标识,0表示内部区域指针,1表示交叉区域指针。

       32位内部区域指针地址寻址表示格式为:地址存储器标识符[地址寄存器,地址偏移常量],例如装载M存储器一个字节表示为:


       AR1/2 :AR1或者AR2。注意使用限制。

       指针指向地址= 地址寄存器存储地址 + 地址偏移常量,如果AR1装载的地址为P#8.0,实际装载的地址为MB18。32位内部区域指针的使用方法参考下面的示例程序:

                     OPN   DB     1            //打开DB1。

                     LAR1  P#10.0              //将指针P#10.0 装载到地址寄存器1中。

                     L     DBW [AR1,P#12.0]    //将DBW22装载到累加器1中。

                     LAR1  MD    20            //将存储于MD20中的指针装载到地址寄存器1 中。

                     L     DBW [AR1,P#0.0]     //将DBW装载到累加器1中,地址存储于MD20中。

                     +I                                                      

                     LAR2  P#40.0              //将指针P#40.0 装载到地址寄存器2中。

                     T     DBW [AR2,P#0.0]     //运算结果传送到DBW40中。

 

2.4  寄存器32位交叉区域指针

   32位交叉区域指针与32位内部指针相比,地址指针中带有存储区域如I、Q、M等, 32位交叉区域地址指针的格式如图15所示。


图 15

       第0位~第2位作为寻址操作的位地址,第3位~第18位作为寻址操作的字节地址,第24位~第26位为地址标识符,表示的地址区域如下:

       000表示没有地址区,例如P#12.0;

       001表示输入地址区I,例如P#I12.0;

       010表示输出地址区Q,例如P#Q12.0;

       011表示标志位地址区M,例如P#M12.0;

       100表示数据块(DB)中的数据,例如P#DBX12.0

       101表示数据块(DI)中的数据,例如P#DIX12.0

       110表示区域地址区L,例如P#L12.0;

       111表示调用程序块的区域地址区V,例如P#V12.0;

       第31为内部区域与交叉区域指针标识,0表示内部区域指针,1表示交叉区域指针。使用交叉区域指针的表示方法(例如装载M存储器一个字节)为:

 

                     LAR1/2     P#M 20.0       //装载地址指针P#M20.0到AR1或AR2。


       指针指向地址 = 地址寄存器存储地址 + 地址偏移常量,上例中实际装载的地址为MB30。如果访问一个位信号则没有访问宽度。32位交叉区域指针的使用方法参考下面的示例程序:

                     LAR1  P#M 20.0            //将指针P#M20.0 装载到地址寄存器1中。

                     A      [AR1,P#1.1]        //M21.1“与”操作。

                     =     Q      1.2          //如果M21.1为1,输出1.2为1。

                     L     P#I 40.0            //将指针P#I40.0 装载到累加器1中。

                     LAR2                      //将累加器1中存储的地址指针装载到地址寄存器2中。

                     L     W [AR2,P#0.0]       //装载IW40.0到累加器1中。

                     T     MW    60            //将累加器1中存储的数值传送到MW60中。

2.5  使用寄存器间接寻址的思考

       估计大家读完了寄存器间接寻址后,肯定有一些问题:

1:什么时候用地址寄存器间接寻址?

在我来看,地址寄存器是寄存器,利用寄存器间接寻址是使用寄存器存储指针,这两个要搞明白。地址寄存器是系统的,主要是系统处理内部的地址偏移和引用的问题,例如在FB块的开始写入指令T AR2,是指出在背景数据块数据开始的偏移地址(例如FB1调用多个FB块时,在OB1中调用FB1后生成一个多重背景DB块,其中包含各个调用FB块的数据区,如果没有编写上述的指令,那么调用FB块的数据区在背景数据块中将重叠),所有地址寄存器是不可或缺的!利用寄存器间接寻址使用最多的是拆分POINTER和ANY指针使用的(后续再介绍),其它使用的地方很少,还看个人的编程习惯吧。S7-1500没有绝对地址,所以也没有什么地址偏移的问题(即使有也不需要用户考虑),地址寄存器在S7-1500中是虚拟的,主要就是为了S7-300/400程序的移植,所以移植完成后还要测试一下程序,看看是否达到了原来的控制功能。

 2:谁会使用地址寄存器?

很显然,地址寄存器还有数据块寄存器通常是程序块的开发人员使用,否则编程的程序块在有的调用方法上会出问题,主要是程序不完善造成的,程序块的使用者掌握存储器间接寻址就可以了,除非是特殊应用,例如使用指针变量(ANY 或者POINTER)赋值ANY 或者POINTER接口参数。

 3:32位的存储器指针与32位的寄存器指针(交叉和内部)有什么区别?

我想应该是一样的,参考下面的一条指令:

       LAR1  MD    20           //将存储于MD20中的指针装载到地址寄存器1 中。

                                

   指针可以相互传达,说明是一样的,所以指令也可以这样写:

       LAR1  P#M10.0             //将指针P#M10.0装载到地址寄存器1 中。

 

       L     P#M10.0             //将指针P#M10.0装载到累加器1 中。



       T     MD 20              //传递到MD20中


 

指针类型虽然比较多,前面说了不好再归纳,因为再归纳反而不容易入门学习(划分),如果理解深刻了在你的头脑中就会形成自己的知识体系,便于记忆和使用,感觉就跟网络小说里面的“炼化”一样。

----------------------------------------------------------------------------------------------------------

上一篇:【4】存储器32位地址指针——从S7-300_400到S7-1500看变址寻址的改变系列故事之四

下一篇:【6】pointer 和ANY——从S7-300_400到S7-1500看变址寻址的改变系列故事之六

汇总帖:技术Π活动故事、视频与案例分享汇总

 

 


【5】寄存器间接寻址——从S7-300_400到S7-1500看变址寻址的改变系列故事之五 已锁定
编辑推荐: 关闭

请填写推广理由:

本版热门话题

西家技术派

共有64条技术帖

相关推荐

热门标签

相关帖子推荐

guzhang

恭喜,你发布的帖子

评为精华帖!

快扫描右侧二维码晒一晒吧!

再发帖或跟帖交流2条,就能晋升VIP啦!开启更多专属权限!

top
X 图片
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。