PLC中数据块的动态数组实现
什么是动态数组
在PLC编程中,数据块(Data Block)用于存储程序运行所需的各类数据。传统静态数组的大小在编译时已经固定,例如 Array[1..10] of Int 只能存放10个整数,运行期间无法改变。这种固定大小的数组在面对以下场景时会显得笨拙:
- 接收来自上位机的未知数量数据
- 需要动态存储传感器采集的历史值
- 实现可变长度的配方或批次管理
动态数组的出现解决了这个问题。它允许在运行时根据实际需求调整数组的有效元素范围,无需重新修改程序结构。本文以西门子TIA Portal(V16及以上版本)中的S7-1200/1500系列PLC为例,详细讲解动态数组的配置与使用方法。
动态数组与静态数组的区别
| 特性 | 静态数组 | 动态数组 |
|---|---|---|
| 声明方式 | Array[1..10] of Int |
Array[*] of Int |
| 大小确定时机 | 编译时 | 运行时通过 SCL 分配 |
| 内存占用 | 固定预分配 | 按需分配 |
| 灵活性 | 低 | 高 |
| 适用场景 | 数据量已知且固定 | 数据量未知或经常变化 |
实现步骤
第一步:创建支持动态数组的数据块
- 打开 TIA Portal 软件,进入项目视图。
- 展开项目树中的“PLC_1”,右键点击“程序块”,选择“添加新块”。
- 选择“数据块(DB)”,设置块名称为
DB_DynamicArray。 - 取消勾选“优化块访问”选项,点击“确定”创建。
注意:动态数组只能在非优化的数据块中使用。优化块访问会使用符号寻址,无法直接处理动态数组的边界访问。
第二步:声明动态数组数据类型
- 双击创建的数据块
DB_DynamicArray,进入编辑器界面。 - 在声明区域添加以下变量:
Name | Data type | Address | Comment
-------------|-------------|----------|-------------------
arrBuffer | Array[*] of Int | - | 动态整数数组
- 声明一个用于控制数组大小的整型变量:
Name | Data type | Address | Comment
-------------|-------------|----------|-------------------
nActualSize | Int | M0.0 | 实际分配的元素个数
- 保存编译项目。
第三步:在程序中动态分配数组大小
动态数组的大小需要在 Main 程序或功能块中使用 SCL 语言动态设置。以下示例演示如何分配数组大小并写入数据。
- 添加一个新的 SCL 程序块,命名为
InitDynamicArray。 - 编写以下代码:
// 动态分配数组大小为20个元素
#arrBuffer := HALTED; // 清除旧数据
#nActualSize := 20;
// 为数组各元素赋值
FOR #i := 1 TO #nActualSize DO
#arrBuffer[#i] := #i * 10;
END_FOR;
- 保存并编译程序块,检查是否有错误。
第四步:访问动态数组元素
动态数组的使用与普通数组完全相同,通过下标索引访问。以下代码演示如何读取数组中的数据:
// 读取第5个元素的值
#nValue := #arrBuffer[5];
// 遍历数组并累加
#nSum := 0;
FOR #i := 1 TO #nActualSize DO
#nSum := #nSum + #arrBuffer[#i];
END_FOR;
完整示例:接收上位机数据
假设上位机通过 PC Interface 发送一批不确定数量的温度值,PLC 需要动态存储这些数据。
数据块配置
创建数据块 DB_TempData,声明以下变量:
Name | Data type | Comment
---------------|----------------|------------------
arrTempData | Array[*] of Real | 温度数据动态数组
nDataCount | Int | 实际接收的数据个数
bDataReady | Bool | 数据接收完成标志
接收数据程序
创建功能块 FB_ReceiveData,使用 SCL 编写逻辑:
// 假设每次最多接收100个数据
#nMaxCount := 100;
// 动态设置数组大小
#arrTempData := HALTED;
#nDataCount := 0;
// 模拟从通信缓冲区读取数据(实际项目中替换为具体通信指令)
FOR #i := 1 TO #nMaxCount DO
// 此处为示例,实际从串口/以太网读取
// #tempValue 为从缓冲区读取的临时变量
IF #tempValue <> 0 OR #i > 10 THEN
#arrTempData[#i] := #tempValue;
#nDataCount := #i;
ELSE
EXIT; // 遇到结束标记,退出循环
END_IF;
END_FOR;
#bDataReady := TRUE;
常见应用场景
配方管理
在食品加工或药品生产中,不同产品需要不同的参数配方。使用动态数组可以根据当前产品型号动态加载对应数量的工艺参数,无需为每种产品预留固定存储空间。
数据缓存
当PLC需要暂存传感器采集的批量数据(如每100ms采样一次,连续采样1分钟共600个数据点)时,动态数组可以根据实际采样时长动态调整大小。
通信缓冲区
与上位机或第三方设备通信时,接收到的数据报文长度可能不固定。动态数组能够根据实际报文长度自动分配存储空间,避免固定数组可能出现的溢出或浪费问题。
注意事项
-
版本要求:动态数组功能仅在 TIA Portal V16 及以上版本、S7-1200(固件V4.2及以上)及 S7-1500 系列中支持。
-
内存管理:动态数组在分配新大小前应调用
HALTED关键字释放旧数据,防止内存泄漏。 -
边界检查:访问动态数组元素时务必确保下标在有效范围内(1 至 实际分配大小),超出范围会导致PLC进入停止状态。
-
性能考量:动态数组的分配操作比静态数组耗时更长,建议在初始化阶段或通信任务中集中处理,避免在高速循环中频繁调整大小。
-
调试限制:在监控模式下,动态数组的部分属性可能无法直接显示,需要通过间接方式验证数据正确性。

暂无评论,快来抢沙发吧!