我们在移植老的程序的时候经常会发现老的程序经常会用到寄存器间接寻址的寻址方式,比如下面这段程序:
这段代码是西门子 S7-300/400 系列 PLC 的 STL(语句表)语言,作用是把一个“任意类型”的输入变量 #IN 拆成 5 个分量(Temp_1、DATA_LEN、DB_NO、MEM_TYPE、DATA_ADDR),再原封不动地拼回一个 ANY 指针 #ANY_IN,最后调用系统块 BLKMOV 把这段内存拷贝到目标区 #STS。
简单理解:它就是在“解析 ANY 指针 → 再重建 ANY 指针 → 做内存复制”
那么为什么这种写法在S7-300/400的时代这么受到青睐呢?为什么现在的1500PLC里面几乎看不到这种写法呢?
1.硬件架构变了
S7-300/400 有 AR1/AR2 两个专属地址寄存器,CPU 原生支持 L W[AR1,P#x.x] 这种“硬件级”间接寻址,速度又快,指令集也丰富 。
S7-1500 为了提升流水线性能,把 AR 寄存器弱化,很多底层操作被挪到内部“微码”完成,用户层不再直接操作 AR,于是传统 [ARx, P#] 语法失去硬件优势,甚至被标记为“非最优”。
2.出现了“标准化”替代品
TIA Portal 给 S7-1500 新增了 PEEK/POKE 指令(SCL 里还有 AT、片段访问、Array[*] 等),一条指令就能完成“读/写任意地址”,不需要手工拼 10 字节 ANY 头,也不需要会 STL。
例如读一个 Word:
PEEK(area:=16#84, dbNumber:=MyDB, byteOffset:=Index)
编译器自动检查边界,出错直接红波浪线,调试效率远高于“夜里数指针”。
3.ANY→VARIANT 语法升级
S7-1500 的
块接口可以直接声明 Input{Variant},系统自动把实参包装成“安全描述符”,既继承了 ANY 的“万能”又多了类型检查;用户再也用不着 L P##Param + LAR1 去拆 10 字节。
4.编译器策略不同
S7-300 时代为了省内存,鼓励“绝对地址 + 指针”做动态复用;
S7-1500 内存翻倍、符号表全局有效,官方推荐“符号化 + 数组/结构”静态访问,既便编译器做优化,也便在线监控、HMI 自动绑定。
5.安全与可追溯性
间接指针一旦跑飞,300 时代只能“看诊断缓存”;1500 的 PEEK/POKE 会在 CPU 诊断缓冲区记录“非法区域访问”,且能在程序中捕捉 ENO,符合 IEC-61131 安全模型。
6.移植与维护成本
传统 [AR1,P#] 代码在 1500 里虽然仍被 STL 接受,但混合项目(SCL/LAD/FBD)交叉引用时无法解析地址,移植工具会提示“手动检查”;而新指令是跨语言通用块,可直接拖拽,维护工作量直线下降。