技术论坛

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

返回主题列表
作者 主题
空果仁
侠圣

经验值: 4925
发帖数: 210
精华帖: 47
楼主    2020-03-19 13:49:17
主题:【6】pointer 和ANY——从S7-300_400到S7-1500看变址寻址的改变系列故事之六 精华帖 

3 参数类型指针-POINTER与ANY

        所谓参数类型指针就是专用于函数FC及函数块FB接口参数的传递,例如可以在IN、OUT、IN/OUT中声明这些变量,也可以在TEMP区(OB也可以)中声明作为一个变量赋值给调用FC/FB的接口参数。

3.1 POINTER指针的数据格式

        POINTER指针占用48位地址空间,数据格式如图16所示。

 


         POINTER指针前16位的数值表示数据块DB或DI的块号,如果指针没有指向一个DB块,则数值为0,POINTER指针可以指向的数据区参考下表:


        与区域交叉指针相比,POINTER类型指针可以直接指向一个数据块中的变量,例如P#DB1.DBX0.0,所以 POINTER(6个字节)=DB块号(2个字节)+32位指针(4个字节,带有数据区的寄存器和存储器指针)。如果不是指向DB块,就是带有数据区的寄存器和存储器指针,例如P#M2.0。

        调用FB、FC时,对POINTER指针数据类型的形参进行赋值时可以选择指针格式直接赋值,例如:

            P# DB2.DBX12.0        //指向DB2.DBX12.0。

            P#M12.1                  //指向M12.1。

        也可以选择使用地址声明或符号名(不使用符号P#)的方式进行赋值,例如:

            DB2.DBX12.0           //指向DB2.DBX12.0。

            M12.1                     //指向M12.1。


3.2 ANY指针的数据格式

        ANY数据类型指针中包括数据类型、重复系数、DB块号、存储器数据开始地址,占用80位地址空间,数据格式如图17所示。

 

        ANY指针使用的数据类型(存储区)参考下表

        ANY指针使用的数据类型(数据区)

        ANY指针使用的数据类型(参数类型)参考下表

        ANY指针使用的数据类型(参数类型)

 

        ANY指针中的数据长度表示指向一个数据区域,例如指向整个数组、结构体等;如果ANY指针没有指向一个DB块,DB块号将为0;ANY指针的数据区与POINTER指针数据区定义相同。

        与POINTER指针相比,ANY类型指针可以表示一段数据区域,例如P#DB1.DBX0.0 BYTE 10,表示指向DB1.DBB0~DB1.DBB9。调用FB、FC时,对ANY指针数据类型的形参进行赋值时可以选择直接使用指针格式赋值,例如:

        以P#开头用于存储区数据类型

        P# DB2.DBX12.0 WORD 22       //指向从DB2.DBW12开始22个字。

        P#M12.1 BOOL 10                   //指向从M12.1开始10个位信号。

 

        以L#开头用于参数数据类型

        L#2 BLOCK_FC  4                    //指向从FC2开始4个FC。

        L#4 TIMER 5                          //指向从T4~T8。

 

        也可以选择使用地址声明或符号名(不使用符号P#)的方式进行赋值,例如:

        DB2.DBW12                  //指向DB2.DBW12一个字,数据长度为1。

        M12.1                          //指向M12.1一个位信号,数据长度为1。

        FC2                            //指向FC2。


3.3 POINTER与ANY指针的拆分

        32位地址指针可以直接装载到存储器或地址寄存器中,从而可以直接在程序块中使用,进行间接寻址,大家知道,S7-300/400可以直接引用的变量最大为4个字节,POINTER和ANY参数类型指针作为一个整体并大于4个字节而不能装载到存储器或寄存器中,所以不能在程序块中直接使用,必须进行拆分使用。拆分的指令只能使用STL完成,指令格式为:

        P##  <POINTER与ANY的符号名称>

        表示指向POINTER与ANY指针的首地址,就是装载POINTER与ANY指针变量的开始地址。为了便于理解,假设FC接口中的一个ANY变量V_ANY开始地址为0(如果是临时变量区则为L0),那么指令:

        L  P##V_ANY  //指向指针V_ANY的开始地址即L0。

        如果将开始地址存储于存储器中,例如

        T  MD20      //将开始地址存储于MD20中,存储P#L0.0

        如果要读出赋值ANY变量的数据类型就必须地址偏移一个字节即:

        L     MD    20

        L     P#1.0

        +D    

        T     MD    24    //数据类型开始地址存储于MD24中即P#L1.0


        但是后面的问题来了,怎么样读出这个地址中的值?下面这样编写语法错误:

        L    B[MD24]      //语法错误

        只能使用交叉区域指针的方式,我在上一篇已经介绍了,

        LAR1  MD    24      //将MD24中地址存储于地址寄存器AR1中

        L     B [AR1,P#0.0]   //装载ANY指针的数据类型

        T     MB200         //存储于MB200中。

        所以所有的拆分程序都必须使用寄存器交叉区域指针编写(不能使用存储器指针),这样就变成了固定格式,以ANY指针类型为例介绍拆分指令:

        L  P##V_ANY  //指向指针V_ANY的开始地址即L0。并装载到地址寄存器AR1中。

        LAR1       

        L B[AR1,P#1.0]   //存储ANY指针的数据类型即LB1

        L W[AR1,P#2.0]   //存储ANY指针的数据长度即LW2

        L W[AR1,P#4.0]   //存储ANY指针的数据块号即LW4

        L D[AR1,P#6.0]   //存储ANY指针的开始地址区即LD6

        IN、OUT、IN/OUT接口区不能显示绝对地址,所以必须使用拆分指令。


        为了让大家更好地理解POINTER和ANY指针的应用,介绍一个编程应用。


3.4  ANY指针编程应用

        编写一个计算功能的函数FC13,输入参数“In_Data”为一个数组变量,如果数组元素为浮点数,输出所有元素的平均值“OUT_VAL”,如果数组元素为其它数据类型,不执行计算功能。OB1中调用函数FC13的程序如下:

        CALL  FC     13                                // 调用函数13。   

        In_Data:=P#DB1.DBX0.0 REAL 8     //输入数据区从DB1.DBD0开始8个浮点值。

        OUT_VAL:=MD20                          //计算结果。

 

        完成的计算功能相当于MD20:=(DB1.DBD0+..+..+DB1.DBD28)/8。在函数FC13的接口参数中定义输入、输出变量及临时变量参考下表:

FC13接口参数

FC13中的示例程序如下:


3.5  使用ANY指针变量赋值

        上面的示例程序在调用FC13时赋值的ANY数据类型为常数,如果使用变量则数据区、长度都可以变化,下面的应用示例使用ANY变量赋值SFC20(块复制)的接口参数,即将P#DB1.DBX0.0 INT 10复制到P#DB1.DBX20.0 INT 10中,函数接口声明参考图18。

        在IN、OUT、IN_OUT区声明ANY变量没有绝对地址,所以必须使用拆分指令,在临时变量中声明ANY类型指针带有绝对地址,所以可以不用拆分指令直接赋值,示例程序如下:

        数据块、地址区、开始地址和长度都可以作为变量,从而增加了程序的灵活性。


3.6  S7-1500处理参数类型指针的方式

        1:如果习惯了S7-300/400的编程方式,可以直接使用AT指令在接口参数中进行拆分,这样使用LAD也可以编程,参考图19。

        2:除此之外,还可以使用可变数组替代ANY类型指针,在S7-1500中可以非常方便地实现3.4章节的应用示例。在FC的接口参数中可以声明一个可变数组类型变量IN_DATA,数组元素为real(这个不可以变,在Variant中可以实现,后续章节介绍),输出所有元素的平均值“OUT_VAL”函数接口声明参考图20。

 

        示例程序参考图21,比起Any的拆分,有股脱离苦海的感觉,并且没有编程语言的限制。

        3:使用Variant,在后续章节中介绍。

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

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

下一篇:【7】Variant数据类型指针——从S7-300_400到S7-1500看变址寻址的改变系列故事之七

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


来自西门工业子技术支持 高级专家
黑猫警长W
至圣

经验值: 18274
发帖数: 2391
精华帖: 1
1楼    2020-03-19 15:16:09
主题:回复:从S7-300_400到S7-1500看变址寻址的改变-6

看专家的就是精彩

holdkcsxyz
至圣

经验值: 12948
发帖数: 1802
精华帖: 22
2楼    2020-03-19 19:19:32
主题:回复:从S7-300_400到S7-1500看变址寻址的改变-6

再好好学习一遍

CoolCool的猪
至圣

经验值: 16692
发帖数: 1307
精华帖: 2
3楼    2020-03-19 19:49:25
主题:回复:从S7-300_400到S7-1500看变址寻址的改变-6

专家研究的都是细节啊 

同一个问题ID下,已经先回答此问题的人,如再参考我答案而修改自己答案的,就是王八蛋!
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。