作者 | 主题 |
---|---|
空果仁 侠圣 经验值: 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下,已经先回答此问题的人,如再参考我答案而修改自己答案的,就是王八蛋!
|