在 S7‑1500 里,MOVE_BLK、MOVE_BLK_VARIANT、BLKMOV 是三种最常用的块移动指令,但定位、用法、限制完全不同。
一、定位
- MOVE_BLK :简单数组复制(固定类型、固定数组、编译时确定)
- MOVE_BLK_VARIANT :灵活 / 动态数组复制(支持 Variant、结构体数组、单变量、运行时索引)
- BLKMOV :底层内存字节复制(跨存储区、按字节、非优化 DB、兼容旧指令风格)
| 特性 | MOVE_BLK | MOVE_BLK_VARIANT | BLKMOV |
|---|---|---|---|
| 核心定位 | 标准数组块移动 | 变体 / 动态数组块移动西门子工业支持中心 | 底层内存字节移动 |
| 数据类型 | 仅基本类型数组(INT/REAL/BYTE) | 支持Variant、结构体、UDT、数组、单变量 | 按字节复制,无视类型 |
| 源 / 目标 | 必须是数组元素(如 DB1.Data [0]) | 可:数组、单变量、Variant 指针 | 按区域 + DB 号 + 偏移(底层寻址) |
| 偏移方式 | 直接写数组下标(编译时固定) | SRC_INDEX / DEST_INDEX(变量动态偏移)西门子工业支持中心 | byteOffset(字节偏移) |
| 存储区 | 仅限DB 数组 | DB、M、I、Q、全局变量均可 | 任意区(I/Q/M/DB/PI/PQ) |
| DB 优化块 | ✅ 支持(优化 / 非优化均可) | ✅ 支持 | ❌ 仅非优化 DB |
| 返回值 | 无(ENO) | 有 RET_VAL(错误码)西门子工业支持中心 | 无(ENO) |
二、语法与示例(SCL)
1. MOVE_BLK
- 只能传同类型基本数组
- IN/OUT数组元素的含义是移动的块的起点索引
- COUNT = 元素个数
scl:
// 复制 DB1.Data[5] 开始的 10 个 INT → DB2.Data[0]
MOVE_BLK(
IN := DB1.Data[5], // 源:数组元素
OUT := DB2.Data[0], // 目标:数组元素
COUNT := 10 // 元素个数
);
2. MOVE_BLK_VARIANT(最强大)
- 只能传同类型数据
- 支持 Variant、结构体、单变量、动态索引
- SRC_INDEX / DEST_INDEX 可用变量
- 有错误码 RET_VAL
scl:
// 复制 DB1.MyStructArr[3] 开始 5 个结构体 → DB2.MyStructArr[0]
RET_VAL := MOVE_BLK_VARIANT(
SRC := DB1.MyStructArr, // 源数组(或Variant)
DEST := DB2.MyStructArr, // 目标数组
COUNT := 5, // 元素个数
SRC_INDEX := 3, // 源起始索引(变量)
DEST_INDEX := 0 // 目标起始索引(变量)
);
// 单变量 → 数组(COUNT=1)
MOVE_BLK_VARIANT(
SRC := MyIntVar,
DEST := DB1.Data[10],
COUNT := 1,
SRC_INDEX := 0,
DEST_INDEX := 0
);
3. BLKMOV(底层字节)
- 整块复制
- 完全按字节复制,不关心类型
- 必须非优化 DB
- IN/OUT 是数组或数组元素
scl:
// 复制 DB10:"src_DB" 到 DB20:"des_DB
#TMP1 := BLKMOV(SRCBLK := "src_DB", DSTBLK => "des_DB");
#TMP3 := BLKMOV(SRCBLK := P#M200.0 BYTE 10, DSTBLK => P#M300.0 BYTE 10);
- 需要注意的是:
BLKMOV的SRCBLK和DSTBLK的参数中如果是数组元素,其含义为:块移动这个元素所代表的数据,而不是以此为起点移动,这与MOVE_BLK的参数中的数组元素意义完全不同。
scl:
// 复制 "src_DB".DBW64 到 "des_DB".DBW0
#TMP1 := BLKMOV(SRCBLK := "src_DB".DBW64, DSTBLK => "des_DB".DBW0);
这行代码的意思是:复制 "src_DB".DBW64 到 "des_DB".DBW0"(只复制一个WORD),而非"将src_DB从DBW64复制到des_DB".DBW0开始的位置。
- BLKMOV的通用规则:
源区域和目标区域不得重叠。如果源和目标区域长度不同,则只能移动较小长度的区域。
如果源区域小于目标区域,则将整个源区域的数据都写入到目标区域中。而目标区域的其余字节则保持不变。
如果目标区域小于源区域,将写满整个目标区域。而忽略源区域的剩余字节。
三、怎么选
✅ 用 MOVE_BLK 当:
- 只是普通基本类型数组复制
- 下标编译时固定
- 追求最简单、最快
✅ 用 MOVE_BLK_VARIANT 当:
- 要结构体 / UDT 数组复制
- 要动态索引(变量做偏移)
- 写通用 FB/FC(接口用 Variant)
- 要单变量 ↔ 数组复制
- 要错误码 RET_VAL
✅ 用 BLKMOV 当:
- 要忽略类型的底层字节操作
- 旧 S7‑300/400 程序移植
- 配合和取代 PEEK/POKE 风格
四、综合运用demo
- 源数据块:一个有各种不同格式数据的DB块,名称为src_DB

- 目标数据块:array of bytes格式数据的DB块(比如用来拼接网络发送内容的块)

- **设计目标:**将源数据块不分数据类型按照预设的起点和长度逐字节移动到目标数据块中预设的起点区域中。
- 实施过程:
- 创建一个中间数据块,数据类型为Array of bytes,将其命名为:bytes_DB;
- 使用BLKMOV将src_DB整体复制到中间数据块bytes_DB中,利用BLKMOV可以忽略类型复制的特性,将源DB块转为Array of bytes格式的DB块;
- 使用MOVE_BLK或MOVE_BLK_VARIANT将中间数据块bytes_DB的字节复制到目标DB块中。

上述过程是可逆的,就是说,可以把一个Array of bytes格式的DB块的内容复制到一个与src_DB数据类型相同的DB块中,还原出原有数据。而这,正是网络通信所干的事情:decode和encode。