西门子STL间接寻址常问问题集
西门子 STL 间接寻址常问问题集 文献 涉及产品 1.1 如何获得指针或者间接寻址有关的信息 指针的类型包括 16 位指针、32 位指针、Pointer(6Byte)和 Any(10Byte)。16 位指针用于定时器、计数器、程序块的寻址;32 位指针用于 I/Q/M/L/数据块等 存储器中位、字节、字以及双字的寻址,其中第 02 位表示位地址(07)、第 318 位为字节地址, 其余位未定义; Pointer 和 Any 一般应用在复杂数据类型 (比 如 Date_and_Time /Array/String 等)在 FB、FC 之间的传递。而 Any 可以看做是 对 Pointer 的延伸,因为由 10Byte 组成的 Any 中 Byte4Byte9 就是一个 Pointer。 了解指针的格式十分重要,为正确使用指针,应阅读如下内容 1、 “SIMATIC Programming with STEP 7 V5.5“ 05/2010 第 27.3.4 章 参数类型 2、文档1008 用于 S7-300 和 S7-400 的语句表STL编程 3、文档F0215,S7-300 和 S7-400 寻址 1.2 为什么语句 LAR1 PPointer 在一个函数FC中是无效的,然而, 同样的 语句在一个功能块FB中是有效的 在 FC 被调用时,复杂数据类型例如指针是被复制到调用者的临时变量区中,在 FC 内部对此 V 区地址直接取址放入到地址寄存器 AR1 或 AR2 是不被编译器规 则接受的(导致 MC7 寄存器信息过长),也就是说在 FC 内部通过 P进行地址 寄存器取址仅能支持 Temp 临时变量。因此如果需要在 FC 中操作指针等复杂输 入输出变量地址需要使用累加器进行中转。 考虑到程序的一致性、遵守编译器规则和 STL 手册中 LAR1 指令说明,建议用 户使用如下指令操作 L PPointer LAR1 1.3 STEP 7 中哪些操作会覆盖 DB/DI 寄存器或者地址寄存器 AR1/AR2 的内容 下面说明了可能引起 DB/DI寄存器或者地址寄存器 AR1/AR2 内容改变的一些操 作 DB 寄存器和 AR1 受到影响的操作 1. 使用完整的 DB 路径(如 L DB20.Val)或者调用 FC/FB 时使用 DB 块完整地 址作为其参数,则 DB 寄存器内容被覆盖。 例如在 OB1 中调用 FC1 后,DB 寄存器变成 20。 OPN DB1 Call FC1 bitDB20.DBX0.2 因此在编程的时候, OPN 指令打开数据块, 通过 DBX x.y 的方式访问其中内容, 但是如果在打开数据块后 DB 寄存器的内容被修改了, 则 DBX x.y 的方式访问变 量则 会访问到错误的地址。可以通过使用符号寻址的方式或者使用完整路径编 程避免,当 然重新使用 OPN 指令也是可以的。 2. 调用 FC 时使用 string, array, structure ,UDT 作为其形参或者调用 FB 时使用 string, array, structure 或者 UDT 作为其 in out 形参, 在 FC/FB 程序中访问这些地 址则 AR1 寄存器内容被覆盖,因此当使用 AR1 进行间接寻址时需要注意 AR1 内容的正确性。 AR2 地址寄存器和 DI 寄存器在 FB 中作为参数和静态变量的基址寻址使 用。AR2 和 DI 如果被修改,会影响 FB 的参数访问,如果希望在 FB 中使用 DI 寄存器或者地址寄存器 AR2,必须预先保存它们中的内容,并在使用后恢复它 们,例如 TAR2 AR2_SAVE; //AR2 寄存器状态保存到AR2_SAVE LDINO; TDB2_SAVE; //DI 寄存器状态保存到DB2_SAVE User Program LAR2AR2_SAVE; //AR2 寄存器恢复到使用前状态 OPNDI [DB2_SAVE]; //DI 寄存器恢复到使用前状态 1.4 如何得到多重背景 FB 中的变量在背景 DB 里的绝对偏移量呢 可以用下面的方法处理 TAR2 得到多重背景 FB 在背景 DB 里的偏移地址 AD DW1600FFFFFF 屏蔽掉存储区 ID,可参考 32 位指针格式 L PVariable 得到变量在多重背景 FB 里的地址 D 多重背景 FB 的偏移地址与变量在多重背景 FB 里地址相加,即得到实际绝 对偏移量 LAR1 上述语句就是就得到了变量在背景 DB 中的绝对偏移量,从而供后续程序处理。 1.5 如何在程序中使用 ANY 型指针 简要说明如下 LP//指向存储地址指针 首地址 //这个参数是一个 Any 类型,P 指向参数 的值所在地址,这就是指 针的指针 LAR1//装载到地址寄存器 AR1 中。 LW [AR1,P4.0]//打开 DB 块 // 由 Any 类型结构知道 Any 类型的 Byte4、Byte5 存放的数据块号 TBLOCK_NO OPNDB [BLOCK_NO]//如果是 DB 块,打开指定的 DB 块。 LW [AR1,P2.0] //判断 ANY 指针中数据长度 // Any 类型的 Byte2、Byte3 是重复系数,如 PDB1.DBX0.0 Byte 8 后面的 Byte 8 _001TDATA_LEN//通常此处做 loop 循环 LD [AR1,P6.0]//找出需要计算数据区的开始地址 // Any 类型 Byte6Byte9 是 32 位区域地址 理解 Pointer、Any 的类型的数据结构,对于正确使用指针有很大帮助。 为正确使用指针,应仔细阅读如下内容 “SIMATIC Programming with STEP 7 V5.5“ 05/2010 第 27.3.4 章 参数类型 如下的程序实现了 SFC20 的部分功能,可以作为 Any 使用的参考。 FUNCTION FC 1 VOID TITLE VERSION 0.1 VAR_ SRCBLK ANY ; END_VAR VAR_OUTPUT RETVAL INT ; DSTBLK ANY ; END_VAR VAR_TEMP LOOP INT ; BLOCK_NO_DB WORD ; BLOCK_NO_DI WORD ; SRC_ADD DWORD ; DST_ADD DWORD ; END_VAR BEGIN NETWORK TITLE L PSRCBLK; //读取输入 any 的首地址 LAR1 ; //装载到 ar1 L PDSTBLK; //读取输出 any 的首地址 LAR2 ; //装载到 ar2 L W [AR1,P4.0]; //打开 DB 块 T BLOCK_NO_DB; L W [AR2,P4.0]; //打开 DI