能否为FUNCTION_BLOCK添加静态参数实现不同实例的可变缓存容量?
问题解答
你设想的写法是否可行?
你提供的VAR_INPUT CONSTANT定义方式不被现行主流IEC 61131-3编译器支持。原因是数组上下限属于编译期必须确定的常量,而VAR_INPUT CONSTANT本质是实例级输入参数,编译阶段无法获取每个实例的具体赋值,因此会直接触发编译错误。
不同容量缓存FB的最优实现方案
根据你使用的PLC支持的标准等级,可按优先级选择以下方案:
1. 泛型FUNCTION_BLOCK方案(适配支持IEC 61131-3第四版标准的PLC)
这是最贴近你需求的原生方案,使用标准新增的GENERIC泛型特性,参数在编译期指定,无运行时开销:
// 泛型FB定义 FUNCTION_BLOCK GENERIC FB_Buffer VAR_GENERIC StorageSize : DINT := 10; // 泛型参数,编译期确定 END_VAR VAR Storage : ARRAY [1..StorageSize] OF REAL; END_VAR
实例化写法和你设想的几乎一致:
FUNCTION_BLOCK FB_Usage VAR SmallBuffer : FB_Buffer(StorageSize := 10); LargeBuffer : FB_Buffer(StorageSize := 1000); END_VAR
2. 动态数组方案(适配支持可变长度数组的PLC)
如果你的PLC不支持泛型,但支持动态数组(ARRAY[*]),可以用初始化阶段分配内存的方式实现:
FUNCTION_BLOCK FB_Buffer VAR_INPUT StorageSize : DINT; END_VAR VAR Storage : ARRAY[*] OF REAL; _initDone : BOOL; END_VAR // 首次运行时分配数组空间,不同PLC分配语法略有差异,部分平台用RESIZE系统函数 IF NOT _initDone THEN __NEW(Storage, 1, StorageSize); _initDone := TRUE; END_IF
实例化直接传入容量参数即可:
VAR SmallBuffer : FB_Buffer(StorageSize := 10); LargeBuffer : FB_Buffer(StorageSize := 1000); END_VAR
3. 全局缓存池映射方案(全版本兼容)
如果连动态数组都不支持,是兼容所有IEC标准PLC的兜底方案:
- 提前在全局变量区定义一个容量足够覆盖所有实例总需求的公共缓存数组
- 每个FB实例存储自身的起始偏移量和容量,读写操作直接映射到全局缓存的对应区间
// 全局缓存定义 GVL_BufferPool VAR_GLOBAL TotalPool : ARRAY[1..10000] OF REAL; // 按最大总容量提前定义 _currentOffset : DINT := 1; END_VAR
FB实现示例:
FUNCTION_BLOCK FB_Buffer VAR_INPUT StorageSize : DINT; END_VAR VAR _startIdx : DINT; _initDone : BOOL; END_VAR // 初始化分配区间 IF NOT _initDone THEN _startIdx := GVL_BufferPool._currentOffset; GVL_BufferPool._currentOffset := GVL_BufferPool._currentOffset + StorageSize; // 可自行添加总容量溢出判断逻辑 _initDone := TRUE; END_IF // 写入缓存方法示例 METHOD Write : BOOL VAR_INPUT Pos : DINT; Value : REAL; END_VAR IF Pos >= 1 AND Pos <= StorageSize THEN GVL_BufferPool.TotalPool[_startIdx + Pos - 1] := Value; Write := TRUE; END_IF
内容的提问来源于stack exchange,提问作者relatively_random
相关产品推荐
相关产品推荐

