跳到主要内容

标准功能块

Darra PLC 提供完整的 IEC 61131-3 标准功能块库,包括定时器、计数器、触发器和数学函数。这些功能块由 IecFunctionBlocks.csIEC61131Functions.cs 实现。

定时器

TON — 接通延时

输入持续为 TRUE 达到预设时间后,输出变为 TRUE。

VAR
tonDelay : TON;
END_VAR

tonDelay(IN := bInput, PT := T#3s);
// tonDelay.Q — 延时后输出 (BOOL)
// tonDelay.ET — 已经过时间 (TIME)
输入类型说明
INBOOL使能输入
PTTIME预设时间
输出类型说明
QBOOLIN 为 TRUE 且 ET >= PT 时为 TRUE
ETTIME经过时间 (IN=FALSE 时复位为 0)

TOF — 断开延时

输入变为 FALSE 后,输出延时一段时间才变为 FALSE。

VAR
tofMotor : TOF;
END_VAR

tofMotor(IN := bMotorRun, PT := T#5s);
bCoolantOn := tofMotor.Q; // 电机停止后冷却液继续运行 5 秒

TP — 脉冲定时器

输入上升沿触发一个固定宽度的脉冲。

VAR
tpPulse : TP;
END_VAR

tpPulse(IN := bTrigger, PT := T#200ms);
bBuzzer := tpPulse.Q; // 蜂鸣 200ms

计数器

CTU — 递增计数器

VAR
ctuParts : CTU;
END_VAR

ctuParts(CU := bPartSensor, R := bReset, PV := 100);
// ctuParts.Q — CV >= PV 时为 TRUE (BOOL)
// ctuParts.CV — 当前计数值 (INT)
bBatchDone := ctuParts.Q;
iPartCount := ctuParts.CV;

CTD — 递减计数器

VAR
ctdRemain : CTD;
END_VAR

ctdRemain(CD := bPartSensor, LD := bLoadPreset, PV := 50);
// ctdRemain.Q — CV <= 0 时为 TRUE
// ctdRemain.CV — 当前计数值 (从 PV 递减)
bMaterialEmpty := ctdRemain.Q;

CTUD — 双向计数器

VAR
ctudStock : CTUD;
END_VAR

ctudStock(CU := bItemIn, CD := bItemOut, R := bReset, LD := bLoad, PV := 200);
// ctudStock.QU — CV >= PV (上溢出)
// ctudStock.QD — CV <= 0 (下溢出)
// ctudStock.CV — 当前计数值

触发器

SR — 置位优先触发器

VAR
srLatch : SR;
END_VAR

srLatch(SET1 := bSet, RESET := bReset);
bOutput := srLatch.Q1;
// SET1 和 RESET 同时为 TRUE 时,Q1 = TRUE (置位优先)

RS — 复位优先触发器

VAR
rsLatch : RS;
END_VAR

rsLatch(SET := bSet, RESET1 := bReset);
bOutput := rsLatch.Q1;
// SET 和 RESET1 同时为 TRUE 时,Q1 = FALSE (复位优先)

R_TRIG — 上升沿检测

VAR
rtSensor : R_TRIG;
END_VAR

rtSensor(CLK := bSensorInput);
IF rtSensor.Q THEN
iCount := iCount + 1; // 仅在上升沿计数一次
END_IF;

F_TRIG — 下降沿检测

VAR
ftButton : F_TRIG;
END_VAR

ftButton(CLK := bButton);
IF ftButton.Q THEN
// 按钮释放时执行
bToggle := NOT bToggle;
END_IF;

数学函数

基本数学

函数说明示例
ABS(x)绝对值ABS(-5.3)5.3
SQRT(x)平方根SQRT(16.0)4.0
LN(x)自然对数LN(2.718)1.0
LOG(x)常用对数LOG(100.0)2.0
EXP(x)指数 (e^x)EXP(1.0)2.718
EXPT(x,y)幂运算 (x^y)EXPT(2.0, 10.0)1024.0

三角函数

函数说明输入单位
SIN(x)正弦弧度
COS(x)余弦弧度
TAN(x)正切弧度
ASIN(x)反正弦弧度
ACOS(x)反余弦弧度
ATAN(x)反正切弧度
ATAN2(y,x)四象限反正切弧度

选择与限制

// LIMIT — 限幅
rClamped := LIMIT(MN := 0.0, IN := rValue, MX := 100.0);

// SEL — 二选一 (G=FALSE 选 IN0, G=TRUE 选 IN1)
rResult := SEL(G := bSelect, IN0 := rValueA, IN1 := rValueB);

// MUX — 多选一 (按 K 索引选择)
rResult := MUX(K := iIndex, IN0 := 1.0, IN1 := 2.0, IN2 := 3.0);

// MIN / MAX
rMin := MIN(rA, rB, rC);
rMax := MAX(rA, rB, rC);

位操作

函数说明示例
SHL(x, n)左移 n 位SHL(1, 3)8
SHR(x, n)右移 n 位SHR(16, 2)4
ROL(x, n)循环左移
ROR(x, n)循环右移

字符串函数

函数说明
LEN(s)字符串长度
LEFT(s, n)左取 n 字符
RIGHT(s, n)右取 n 字符
MID(s, n, p)从 p 位置取 n 字符
CONCAT(s1, s2)拼接
FIND(s1, s2)查找子串位置
INSERT(s1, s2, p)插入
DELETE(s, n, p)删除
REPLACE(s1, s2, n, p)替换

数据移动

// MOVE — 赋值 (常用于 CFC/LAD)
MOVE(IN := rSource, OUT => rDest);

// 批量操作在 ST 中通常直接赋值
arDest := arSource; // 数组复制
stDest := stSource; // 结构体复制
性能提示

标准函数内部已高度优化, 执行效率远高于等价的 ST 手写循环。优先使用标准函数库而非自行实现。

面向对象 (OOP) 扩展

IEC 61131-3 Third Edition 引入面向对象特性, Darra PLC 完整支持。

继承 (EXTENDS)

FUNCTION_BLOCK 可继承另一个 FB, 复用代码并扩展:

// 基类: 通用设备
FUNCTION_BLOCK FB_Device
VAR_INPUT
bEnable : BOOL;
END_VAR
VAR_OUTPUT
bReady : BOOL;
iErrorCode : INT;
END_VAR
VAR
sDeviceName : STRING[32];
END_VAR

METHOD PUBLIC Initialize
sDeviceName := 'Device';
iErrorCode := 0;
END_METHOD

METHOD PUBLIC Diagnose : STRING[64]
Diagnose := CONCAT(sDeviceName, ': OK');
END_METHOD

END_FUNCTION_BLOCK

// 子类: 电机设备
FUNCTION_BLOCK FB_Motor EXTENDS FB_Device // 继承
VAR_INPUT
rSetSpeed : REAL;
END_VAR
VAR_OUTPUT
rActualSpeed : REAL;
END_VAR
VAR
rRampRate : REAL := 10.0;
END_VAR

// 覆盖基类方法
METHOD PUBLIC Initialize
SUPER^.Initialize(); // 调用父类
sDeviceName := 'Motor';
END_METHOD

METHOD PUBLIC SetRampRate
VAR_INPUT
rRate : REAL;
END_VAR
rRampRate := LIMIT(0.1, rRate, 100.0);
END_METHOD

END_FUNCTION_BLOCK

接口 (INTERFACE / IMPLEMENTS)

定义统一契约, 多个 FB 可实现同一接口, 支持多态:

// 定义接口
INTERFACE I_Controllable
METHOD Start : BOOL
END_METHOD
METHOD Stop : BOOL
END_METHOD
METHOD GetStatus : E_Status
END_METHOD
END_INTERFACE

// 实现接口
FUNCTION_BLOCK FB_Pump IMPLEMENTS I_Controllable
VAR
eStatus : E_Status;
END_VAR

METHOD Start : BOOL
eStatus := E_Status.RUNNING;
Start := TRUE;
END_METHOD

METHOD Stop : BOOL
eStatus := E_Status.STOPPED;
Stop := TRUE;
END_METHOD

METHOD GetStatus : E_Status
GetStatus := eStatus;
END_METHOD

END_FUNCTION_BLOCK

// 多态调用
VAR
pController : REF_TO I_Controllable;
fbPump : FB_Pump;
fbMotor : FB_Motor_Controllable;
END_VAR

// 运行时切换实例
IF bUsePump THEN
pController := REF(fbPump);
ELSE
pController := REF(fbMotor);
END_IF;

// 统一调用接口
pController^.Start(); // 调用具体实现

方法 (METHOD)

方法是 FB 上定义的函数, 带访问控制和返回值:

FUNCTION_BLOCK FB_Counter
VAR
iValue : INT;
END_VAR

// 公共方法
METHOD PUBLIC Increment : INT
iValue := iValue + 1;
Increment := iValue;
END_METHOD

// 公共方法带参数
METHOD PUBLIC AddValue : INT
VAR_INPUT
iDelta : INT;
END_VAR
iValue := iValue + iDelta;
AddValue := iValue;
END_METHOD

// 私有方法 (只能在 FB 内部调用)
METHOD PRIVATE Validate : BOOL
Validate := iValue >= 0 AND iValue <= 10000;
END_METHOD

// 只读属性
METHOD PUBLIC GET Value : INT
Value := iValue;
END_METHOD

// 读写属性
PROPERTY PUBLIC Counter : INT
GET
Counter := iValue;
END_GET
SET
IF Counter >= 0 THEN
iValue := Counter;
END_IF;
END_SET
END_PROPERTY

END_FUNCTION_BLOCK

// 调用
VAR
fbCnt : FB_Counter;
iNow : INT;
END_VAR

iNow := fbCnt.Increment();
iNow := fbCnt.AddValue(5);
iNow := fbCnt.Value; // 调 GET
fbCnt.Counter := 100; // 调 SET

访问控制

修饰符可见性
PUBLIC外部 + 子类 (默认)
PRIVATE仅本 FB 内部
PROTECTED本 FB + 子类
INTERNAL同项目

FINAL / ABSTRACT

// 抽象 FB, 必须被继承
FUNCTION_BLOCK ABSTRACT FB_ControlBase

METHOD ABSTRACT Execute // 必须被子类实现
END_METHOD

END_FUNCTION_BLOCK

// 终态 FB, 不能被继承
FUNCTION_BLOCK FINAL FB_SingletonLogger
// ...
END_FUNCTION_BLOCK

自定义功能块完整示例

综合应用继承、接口、方法:

// 通用斜坡生成器基类
FUNCTION_BLOCK FB_RampBase IMPLEMENTS I_Controllable
VAR_INPUT
bEnable : BOOL;
rTarget : REAL;
rRate : REAL := 10.0;
END_VAR
VAR_OUTPUT
rOutput : REAL;
bAtTarget : BOOL;
END_VAR
VAR
rLastOutput : REAL;
tonDelay : TON;
END_VAR

METHOD PUBLIC Start : BOOL
bEnable := TRUE;
Start := TRUE;
END_METHOD

METHOD PUBLIC Stop : BOOL
bEnable := FALSE;
Stop := TRUE;
END_METHOD

METHOD PUBLIC GetStatus : E_Status
IF bEnable THEN
GetStatus := E_Status.RUNNING;
ELSE
GetStatus := E_Status.STOPPED;
END_IF;
END_METHOD

// 主执行逻辑 (子类可覆盖)
METHOD PUBLIC Execute
IF bEnable THEN
IF rLastOutput < rTarget THEN
rLastOutput := MIN(rLastOutput + rRate, rTarget);
ELSE
rLastOutput := MAX(rLastOutput - rRate, rTarget);
END_IF;
END_IF;
rOutput := rLastOutput;
bAtTarget := ABS(rOutput - rTarget) < 0.01;
END_METHOD

END_FUNCTION_BLOCK

// S 形斜坡子类
FUNCTION_BLOCK FB_SCurveRamp EXTENDS FB_RampBase
VAR_INPUT
rJerk : REAL := 5.0;
END_VAR
VAR
rAccel : REAL;
END_VAR

// 覆盖 Execute 实现 S 形
METHOD PUBLIC Execute
IF bEnable THEN
// S 形加加速度逻辑
IF rLastOutput < rTarget THEN
rAccel := MIN(rAccel + rJerk, rRate);
rLastOutput := rLastOutput + rAccel * 0.001;
ELSE
rAccel := MAX(rAccel - rJerk, -rRate);
rLastOutput := rLastOutput + rAccel * 0.001;
END_IF;
END_IF;
rOutput := rLastOutput;
bAtTarget := ABS(rOutput - rTarget) < 0.01;
END_METHOD

END_FUNCTION_BLOCK

排错表

问题原因解决
方法调用找不到方法是 PRIVATE改为 PUBLIC
SUPER^ 调用报错基类无此方法确认方法存在
接口实现不全忘了实现某个方法补实现
FB 实例不共享数据每实例独立 VAR用 VAR_STAT 共享
抽象 FB 可实例化未标记 ABSTRACT加 ABSTRACT 关键字
多态失效用具体类型而非接口改用 REF_TO I_XXX

最佳实践

  • 单一职责: 每个 FB 只做一件事
  • 优先组合: 组合 (has-a) 优于继承 (is-a)
  • 接口小而精: 接口只暴露公共协议, 不要包含实现细节
  • GET/SET 属性: 对外暴露数据优先用 PROPERTY 而非直接 VAR_OUTPUT
  • 初始化放 Initialize 方法: OB100 统一调用所有 fbXxx.Initialize()
  • 诊断属性: 每个 FB 暴露 sDiagMsg : STRING 便于在线监视
  • 避免深层继承: 继承层级 ≤ 3 层

相关文档