功能块完整参考手册
功能块 (Function Block, FB) 是 IEC 61131-3 标准中最核心的编程单元。与函数不同,功能块有内部状态——每次调用时输出不仅取决于当前输入,还取决于内部保存的历史数据。
| 对比 | 函数 (FUNCTION) | 功能块 (FUNCTION_BLOCK) |
|---|---|---|
| 状态记忆 | 无(每次调用独立) | 有(内部 VAR 跨周期保持) |
| 输出方式 | 函数名直接返回 | 通过 VAR_OUTPUT 返回 |
| 实例化 | 直接调用 | 必须先声明实例 |
| 典型场景 | 数学计算、类型转换 | 定时器、计数器、状态机、PID |
> 温馨提示:使用功能块前,必须先声明实例(VAR ... END_VAR),然后在程序体中调用。忘记声明实例是最常见的编译错误。
一、定时器 (Timer) — 3 种
定时器是 PLC 编程中最常用的功能块,分为 TON(接通延时)、TOF(断开延时)、TP(脉冲)三种。
1.1 TON — 接通延时定时器
功能描述:输入 IN 变为 TRUE 后开始计时,经过 PT 设定的延时时间后,输出 Q 变为 TRUE。如果 IN 在延时期间变回 FALSE,计时器复位。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
IN | BOOL | 输入 | 启动计时(上升沿启动,下降沿复位) |
PT | TIME | 输入 | 预设延时时间 |
Q | BOOL | 输出 | 延时到达后为 TRUE |
ET | TIME | 输出 | 已经过时间(IN=FALSE 时复位为 0) |
时序图:
IN ┌─────┐ ┌─────
│ │ │
└─────┘ └─────
PT │<── 3s ──>│
Q ┌───────────
│
└───────────
ET ████████████████→
SCL 示例:
// 声明
VAR
tonDelay : TON;
bStart : BOOL; // 启动信号
bReady : BOOL; // 就绪输出
elapse : TIME; // 已过时间
END_VAR
// 调用
tonDelay(IN := bStart, PT := T#3s);
bReady := tonDelay.Q;
elapse := tonDelay.ET;
实际应用:电机启动防冲击
PROGRAM ConveyorStart
VAR
tonMotorDelay : TON; // 电机启动延时
bStartBtn : BOOL AT %IX0.0;
bMotorRun : BOOL AT %QX0.0;
END_VAR
// 按下启动按钮后,电机延迟 5 秒启动
// 防止同时启动多台电机造成电网冲击
tonMotorDelay(IN := bStartBtn, PT := T#5s);
bMotorRun := tonMotorDelay.Q;
END_PROGRAM
注意事项:
IN的保持时间必须 >=PT,否则Q永远不会为 TRUE- 扫描周期必须小于
PT,否则精度不够 - 高精度定时请使用周期中断 OB(如 OB30),不要放在 OB1
1.2 TOF — 断开延时定时器
功能描述:输入 IN 变为 FALSE 后,输出 Q 保持 TRUE 持续 PT 时间,然后变为 FALSE。如果 IN 在延时期间变回 TRUE,计时器复位。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
IN | BOOL | 输入 | 触发输入(下降沿启动计时) |
PT | TIME | 输入 | 断开延时时间 |
Q | BOOL | 输出 | IN=TRUE 时立即为 TRUE;IN=FALSE 后保持 PT 时间 |
ET | TIME | 输出 | 已经过时间 |
时序图:
IN ┌──────────────────────┐ ┌─────
│ │ │
└──────────────────────┘ └─────
PT │<──5s──>│
Q ┌──────────────────────────────┐
│ │
└──────────────────────────────┘
ET ████████████→
SCL 示例:
VAR
tofMotor : TOF;
bMotorRun : BOOL;
bCoolantOn : BOOL;
END_VAR
// 电机停止后,冷却液继续运行 5 秒
tofMotor(IN := bMotorRun, PT := T#5s);
bCoolantOn := tofMotor.Q;
实际应用:传送带停止后吹气清理
PROGRAM BlowOff
VAR
tofAirBlow : TOF;
bConveyorRun : BOOL AT %IX0.0;
bAirValve : BOOL AT %QX0.0;
END_VAR
// 传送带停止后,吹气阀继续打开 3 秒
// 清理传送带上的残留碎屑
tofAirBlow(IN := bConveyorRun, PT := T#3s);
bAirValve := tofAirBlow.Q;
END_PROGRAM
注意事项:
- TOF 在
IN为 TRUE 时Q立即为 TRUE,容易被误认为"一直输出" - 常用于"停机后保留"场景:冷却风扇、后吹气、尾料处理
1.3 TP — 脉冲定时器
功能描述:输入 IN 的上升沿触发一个固定宽度 PT 的脉冲输出。脉冲期间,后续的上升沿被忽略。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
IN | BOOL | 输入 | 触发输入(上升沿启动脉冲) |
PT | TIME | 输入 | 脉冲宽度 |
Q | BOOL | 输出 | 脉冲输出(宽度 = PT) |
ET | TIME | 输出 | 已经过时间 |
时序图:
IN ┌─┐ ┌─┐
│ │ │ │
└─┘ └─┘
PT │<200ms>│
Q ┌──────┐ ┌──────┐
│ │ │ │
└──────┘ └──────┘
ET ████████████→
SCL 示例:
VAR
tpPulse : TP;
bTrigger : BOOL;
bBuzzer : BOOL;
END_VAR
// 触发时蜂鸣器响 200ms
tpPulse(IN := bTrigger, PT := T#200ms);
bBuzzer := tpPulse.Q;
实际应用:按钮按下生成单次脉冲
PROGRAM PulseGen
VAR
tpBtnPulse : TP;
bButton : BOOL AT %IX0.0;
bShot : BOOL AT %QX0.0; // 单次喷射
END_VAR
// 按钮按下 -> 喷射阀打开 500ms
// 即使按钮一直按着,也只喷一次
tpBtnPulse(IN := bButton, PT := T#500ms);
bShot := tpPulse.Q;
END_PROGRAM
注意事项:
- TP 的脉冲宽度不随输入长度变化——输入只负责触发
- 正在脉冲中时,新触发不生效(非重触发)
- 如果需要"可重触发脉冲",请用 TON + R_TRIG 组合
二、计数器 (Counter) — 3 种
计数器用于统计脉冲数量,分为 CTU(递增)、CTD(递减)、CTUD(双向)三种。
2.1 CTU — 递增计数器
功能描述:每个 CU 上升沿计数值 CV 加 1。CV >= PV 时输出 Q 为 TRUE。R 为 TRUE 时 CV 清零。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
CU | BOOL | 输入 | 计数脉冲输入(上升沿触发) |
R | BOOL | 输入 | 复位(CV=0, Q=FALSE) |
PV | INT | 输入 | 预设值 |
Q | BOOL | 输出 | CV >= PV 时为 TRUE |
CV | INT | 输出 | 当前计数值(0 到 32767) |
SCL 示例:
VAR
ctuParts : CTU;
bSensor : BOOL;
bReset : BOOL;
bDone : BOOL;
iCount : INT;
END_VAR
ctuParts(CU := bSensor, R := bReset, PV := 100);
bDone := ctuParts.Q;
iCount := ctuParts.CV;
实际应用:产品批次计数
PROGRAM BatchCount
VAR
ctBatch : CTU; // 批次计数器
bSensorIn : BOOL AT %IX0.0; // 入口传感器
bResetBatch : BOOL AT %IX0.1; // 批次复位按钮
bFullSignal : BOOL AT %QX0.0; // 满箱信号
END_VAR
// 每箱 50 个,满箱后输出信号
ctBatch(CU := bSensorIn, R := bResetBatch, PV := 50);
bFullSignal := ctBatch.Q;
END_PROGRAM
2.2 CTD — 递减计数器
功能描述:每个 CD 上升沿计数值 CV 减 1。CV <= 0 时输出 Q 为 TRUE。LD 为 TRUE 时 CV 加载为 PV 值。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
CD | BOOL | 输入 | 计数脉冲输入(上升沿触发) |
LD | BOOL | 输入 | 加载预设值(CV = PV) |
PV | INT | 输入 | 预设值 |
Q | BOOL | 输出 | CV <= 0 时为 TRUE |
CV | INT | 输出 | 当前计数值 |
SCL 示例:
VAR
ctdRemain : CTD;
bSensor : BOOL;
bLoad : BOOL;
bEmpty : BOOL;
END_VAR
ctdRemain(CD := bSensor, LD := bLoad, PV := 50);
bEmpty := ctdRemain.Q;
实际应用:物料余量监控
PROGRAM MaterialMonitor
VAR
ctdMaterial : CTD;
bTakeOne : BOOL AT %IX0.0; // 取料传感器
bLoadNew : BOOL AT %IX0.1; // 上料按钮
bEmptyAlarm : BOOL AT %QX0.0; // 缺料报警
END_VAR
// 初始 100 个,每取一个减 1,<=0 报警
ctdMaterial(CD := bTakeOne, LD := bLoadNew, PV := 100);
bEmptyAlarm := ctdMaterial.Q;
END_PROGRAM
2.3 CTUD — 双向计数器
功能描述:同时支持递增和递减。CU 上升沿增 1,CD 上升沿减 1。CV >= PV 时 QU 为 TRUE;CV <= 0 时 QD 为 TRUE。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
CU | BOOL | 输入 | 递增脉冲(上升沿) |
CD | BOOL | 输入 | 递减脉冲(上升沿) |
R | BOOL | 输入 | 复位(CV=0, QU=FALSE, QD=FALSE) |
LD | BOOL | 输入 | 加载预设值(CV = PV) |
PV | INT | 输入 | 预设值 |
QU | BOOL | 输出 | CV >= PV 时 TRUE(上溢出) |
QD | BOOL | 输出 | CV <= 0 时 TRUE(下溢出) |
CV | INT | 输出 | 当前计数值 |
SCL 示例:
VAR
ctudStock : CTUD;
bItemIn : BOOL;
bItemOut : BOOL;
bReset : BOOL;
bLoad : BOOL;
bOverflow : BOOL;
bUnderflow : BOOL;
iCurrent : INT;
END_VAR
ctudStock(CU := bItemIn, CD := bItemOut, R := bReset, LD := bLoad, PV := 200);
bOverflow := ctudStock.QU;
bUnderflow := ctudStock.QD;
iCurrent := ctudStock.CV;
实际应用:仓库库存管理
PROGRAM StockManager
VAR
ctudStock : CTUD;
bInSensor : BOOL AT %IX0.0; // 入库传感器
bOutSensor : BOOL AT %IX0.1; // 出库传感器
bResetStock : BOOL AT %IX0.2; // 盘点复位
bFullWarn : BOOL AT %QX0.0; // 满仓预警
bEmptyWarn : BOOL AT %QX0.1; // 空仓预警
iStockLevel : INT; // 当前库存量
END_VAR
// 仓库容量 200 箱,双向计数
ctudStock(CU := bInSensor, CD := bOutSensor,
R := bResetStock, PV := 200);
iStockLevel := ctudStock.CV;
bFullWarn := ctudStock.QU; // 满仓
bEmptyWarn := ctudStock.QD; // 空仓
END_PROGRAM
注意事项:
- CTU/CTD 默认是 INT 类型,范围 0~32767
- 需要更大范围时用
CTU_DINT/CTUD_DINT(32 位) - CU 和 CD 在同周期内同时触发 → 值保持不变(先增后减)
- 高频计数请用高速计数器模块(HSC),软件计数器受扫描周期限制
三、边沿检测 (Edge Detection) — 2 种
边沿检测用于捕获信号的变化瞬间,输出保持一个扫描周期。
3.1 R_TRIG — 上升沿检测
功能描述:检测输入 CLK 从 FALSE 到 TRUE 的变化,输出 Q 保持一个扫描周期为 TRUE。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
CLK | BOOL | 输入 | 被检测信号 |
Q | BOOL | 输出 | 检测到上升沿时 TRUE(一个周期) |
时序图:
CLK ──────┐ ┌─────┐ ┌─────
│ │ │ │
└─────┘ └─────┘
Q ┌─┐ ┌─┐ ┌─┐
│ │ │ │ │ │
└─┘ └─┘ └─┘
SCL 示例:
VAR
rtSensor : R_TRIG;
bInput : BOOL;
iCount : INT;
END_VAR
rtSensor(CLK := bInput);
IF rtSensor.Q THEN
iCount := iCount + 1; // 仅在上升沿计数一次
END_IF;
实际应用:按钮单次触发
PROGRAM ButtonControl
VAR
rtStart : R_TRIG;
rtStop : R_TRIG;
bStartBtn : BOOL AT %IX0.0;
bStopBtn : BOOL AT %IX0.1;
bRunning : BOOL AT %QX0.0;
END_VAR
// 用 R_TRIG 确保"按一次只触发一次"
rtStart(CLK := bStartBtn);
rtStop(CLK := bStopBtn);
IF rtStart.Q THEN
bRunning := TRUE;
END_IF;
IF rtStop.Q THEN
bRunning := FALSE;
END_IF;
END_PROGRAM
3.2 F_TRIG — 下降沿检测
功能描述:检测输入 CLK 从 TRUE 到 FALSE 的变化,输出 Q 保持一个扫描周期为 TRUE。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
CLK | BOOL | 输入 | 被检测信号 |
Q | BOOL | 输出 | 检测到下降沿时 TRUE(一个周期) |
时序图:
CLK ┌─────┐ ┌─────┐
│ │ │ │
└─────┘ └─────┘
Q ┌─┐ ┌─┐
│ │ │ │
└─┘ └─┘
SCL 示例:
VAR
ftButton : F_TRIG;
bInput : BOOL;
bToggle : BOOL;
END_VAR
ftButton(CLK := bInput);
IF ftButton.Q THEN
bToggle := NOT bToggle; // 按钮释放时切换
END_IF;
R_TRIG 与 F_TRIG 对比:
| 特性 | R_TRIG | F_TRIG |
|---|---|---|
| 触发条件 | FALSE → TRUE | TRUE → FALSE |
| 输出 Q 宽度 | 1 个扫描周期 | 1 个扫描周期 |
| 典型场景 | 按钮按下、传感器检测 | 按钮释放、限位解除 |
注意事项:
- 边沿检测输出的 Q 只有一个扫描周期,必须在当周期使用
- 如果信号变化速度快于扫描周期,边沿会被漏掉
- 高速信号(> 1kHz)请使用硬件中断或高速计数器模块
四、触发器 (Flip-Flop) — 2 种
触发器用于实现"锁存"功能,区别在于 SET 和 RESET 同时有效时谁优先。
4.1 SR — 置位优先触发器
功能描述:SET1 为 TRUE 时输出 Q1 置位为 TRUE。RESET 为 TRUE 时 Q1 复位为 FALSE。两者同时为 TRUE 时,置位优先(Q1 = TRUE)。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
SET1 | BOOL | 输入 | 置位输入 |
RESET | BOOL | 输入 | 复位输入 |
Q1 | BOOL | 输出 | 输出状态 |
真值表:
| SET1 | RESET | Q1(当前) | Q1(下一周期) |
|---|---|---|---|
| 0 | 0 | — | 不变 |
| 0 | 1 | — | 0 |
| 1 | 0 | — | 1 |
| 1 | 1 | — | 1(置位优先) |
SCL 示例:
VAR
srLatch : SR;
bSet : BOOL;
bReset : BOOL;
bOut : BOOL;
END_VAR
srLatch(SET1 := bSet, RESET := bReset);
bOut := srLatch.Q1;
// SET1 和 RESET 同时为 TRUE 时,Q1 = TRUE(置位优先)
实际应用:启动/停止电机(置位优先)
PROGRAM MotorControl
VAR
srMotor : SR;
bStart : BOOL AT %IX0.0;
bStop : BOOL AT %IX0.1;
bRun : BOOL AT %QX0.0;
END_VAR
// 置位优先:启动信号优先级高于停止
// 适合启停按钮在同一位置,持续按启动无法停止的场景
srMotor(SET1 := bStart, RESET := bStop);
bRun := srMotor.Q1;
END_PROGRAM
4.2 RS — 复位优先触发器
功能描述:SET 为 TRUE 时输出 Q1 置位为 TRUE。RESET1 为 TRUE 时 Q1 复位为 FALSE。两者同时为 TRUE 时,复位优先(Q1 = FALSE)。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
SET | BOOL | 输入 | 置位输入 |
RESET1 | BOOL | 输入 | 复位输入 |
Q1 | BOOL | 输出 | 输出状态 |
真值表:
| SET | RESET1 | Q1(当前) | Q1(下一周期) |
|---|---|---|---|
| 0 | 0 | — | 不变 |
| 0 | 1 | — | 0 |
| 1 | 0 | — | 1 |
| 1 | 1 | — | 0(复位优先) |
SCL 示例:
VAR
rsLatch : RS;
bSet : BOOL;
bReset : BOOL;
bOut : BOOL;
END_VAR
rsLatch(SET := bSet, RESET1 := bReset);
bOut := rsLatch.Q1;
// SET 和 RESET1 同时为 TRUE 时,Q1 = FALSE(复位优先)
实际应用:急停场景(复位优先)
PROGRAM SafetyLatch
VAR
rsSafety : RS;
bRunOk : BOOL AT %IX0.0; // 运行正常
bEstop : BOOL AT %IX0.1; // 急停按钮(常闭触点)
bPowerOn : BOOL AT %QX0.0; // 主电源输出
END_VAR
// 复位优先:急停信号优先级最高
// 即使运行正常和急停同时触发,也以安全为准
rsSafety(SET := bRunOk, RESET1 := NOT bEstop);
bPowerOn := rsSafety.Q1;
END_PROGRAM
SR 与 RS 选型原则:
| 场景 | 推荐 | 理由 |
|---|---|---|
| 安全关键系统 | RS(复位优先) | 故障时默认复位到安全状态 |
| 工艺保持场景 | SR(置位优先) | 启动信号优先于停止信号 |
| 急停逻辑 | RS(复位优先) | 急停信号优先级最高 |
| 电机正反转互锁 | 两者皆可 + 外部互锁 | 硬件互锁比软件更可靠 |
五、标准库功能块 (Standard Library FB)
标准库提供了大量工业控制常用的功能块,涵盖连续控制、信号处理、数据转换、逻辑运算等。
5.1 PID — PID 控制器
功能描述:比例-积分-微分控制器,广泛应用于温度、压力、流量、速度等闭环控制。支持自动整定。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
SETPOINT | REAL | 输入 | 目标值 |
ACTUAL | REAL | 输入 | 实际值(反馈) |
KP | REAL | 输入 | 比例增益 |
TI | REAL | 输入 | 积分时间(秒,0=禁用积分) |
TD | REAL | 输入 | 微分时间(秒,0=禁用微分) |
CYCLE | TIME | 输入 | 采样周期 |
MANUAL | BOOL | 输入 | TRUE=手动模式 |
MANUAL_VALUE | REAL | 输入 | 手动模式输出值 |
RESET | BOOL | 输入 | 复位积分项 |
OUTPUT | REAL | 输出 | 控制输出 |
LIMIT_H | REAL | 输入 | 输出上限 |
LIMIT_L | REAL | 输入 | 输出下限 |
INTEGRAL | REAL | 输出 | 当前积分项值(调试用) |
SCL 示例:
VAR
pidTemp : PID;
rSetpoint : REAL := 100.0; // 目标温度 100°C
rActual : REAL; // 实际温度(来自传感器)
rOutput : REAL; // 控制输出(0~100%)
END_VAR
// 在周期中断 OB 中调用(如 OB30,每 100ms)
pidTemp(SETPOINT := rSetpoint, ACTUAL := rActual,
KP := 2.5, TI := 10.0, TD := 0.5, CYCLE := T#100ms,
LIMIT_H := 100.0, LIMIT_L := 0.0);
rOutput := pidTemp.OUTPUT;
实际应用:恒温控制
PROGRAM TempControl
VAR
pidHeater : PID;
rTarget : REAL := 150.0; // 目标温度 150°C
rTemp : REAL; // 热电偶反馈
rHeat : REAL; // 加热器输出 0~100%
bRun : BOOL AT %IX0.0;
END_VAR
// PID 恒温控制
IF bRun THEN
pidHeater(SETPOINT := rTarget, ACTUAL := rTemp,
KP := 3.0, TI := 8.0, TD := 0.0, CYCLE := T#200ms,
LIMIT_H := 100.0, LIMIT_L := 0.0);
rHeat := pidHeater.OUTPUT;
ELSE
rHeat := 0.0;
END_IF;
END_PROGRAM
注意事项:
- PID 必须在固定周期的中断 OB 中调用,不要在 OB1 中调用
- 积分饱和(windup)是常见问题,务必设置输出限幅
TI=0禁用积分 -> 变成 PD 控制器TD=0禁用微分 -> 变成 PI 控制器(工业中最常用)- 微分对噪声敏感,传感器信号不干净时建议禁用微分
5.2 INTEGRAL — 积分器
功能描述:对输入信号进行时间积分,输出累积值。常用于流量累计、速度位置转换。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
X | REAL | 输入 | 被积信号 |
CYCLE | TIME | 输入 | 积分周期 |
RESET | BOOL | 输入 | 复位输出为 0 |
Y | REAL | 输出 | 积分结果 |
OVERFLOW | BOOL | 输出 | 溢出标志 |
SCL 示例:
VAR
intFlow : INTEGRAL;
rFlow : REAL; // 瞬时流量 L/min
rTotal : REAL; // 累计流量 L
END_VAR
// 流量累计
intFlow(X := rFlow, CYCLE := T#100ms);
rTotal := intFlow.Y;
注意事项:
- 积分周期必须和调用周期一致
- 输出饱和后
OVERFLOW为 TRUE,需要定期复位
5.3 DERIVATIVE — 微分器
功能描述:对输入信号进行微分运算,输出变化率。常用于速度计算、趋势检测。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
X | REAL | 输入 | 被微信号 |
CYCLE | TIME | 输入 | 微分周期 |
Y | REAL | 输出 | 微分结果(变化率) |
SCL 示例:
VAR
derSpeed : DERIVATIVE;
rPos : REAL; // 位置 mm
rSpeed : REAL; // 速度 mm/s
END_VAR
// 位置 -> 速度转换
derSpeed(X := rPos, CYCLE := T#50ms);
rSpeed := derSpeed.Y;
注意事项:
- 微分对噪声非常敏感,输入信号建议先滤波
- 信号突变时会产生尖峰,必要时加限幅
5.4 HYSTERESIS — 滞回比较器
功能描述:带滞回区间的比较器,防止信号在阈值附近来回抖动。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
X | REAL | 输入 | 输入信号 |
ON_POINT | REAL | 输入 | 开启阈值 |
OFF_POINT | REAL | 输入 | 关闭阈值(必须 < ON_POINT) |
Q | BOOL | 输出 | 比较结果 |
时序图:
X
↑
│ ON_POINT ──┐ ┌─────── 开启
│ │ │
│ OFF_POINT ─┘ └─────── 关闭
│
└──────────────────────────────→
Q ┌──────────────┐
│ │
└──────────────┘
↑ ↑
开启 关闭
SCL 示例:
VAR
hysLevel : HYSTERESIS;
rLevel : REAL; // 液位 mm
bPumpOn : BOOL; // 水泵控制
END_VAR
// 液位控制:液位低于 200mm 启动泵,高于 500mm 停止
hysLevel(X := rLevel, ON_POINT := 500.0, OFF_POINT := 200.0);
bPumpOn := hysLevel.Q;
注意事项:
ON_POINT必须大于OFF_POINT,否则行为异常- 滞回宽度 = ON_POINT - OFF_POINT,越宽抗抖动越好,但控制精度越低
5.5 SCALING — 模拟量标定
功能描述:将原始模拟量值(如 027648)线性映射到工程值(如 0100.0)。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
X | REAL | 输入 | 原始输入值 |
X_LOW | REAL | 输入 | 输入下限 |
X_HIGH | REAL | 输入 | 输入上限 |
Y_LOW | REAL | 输入 | 输出下限 |
Y_HIGH | REAL | 输入 | 输出上限 |
Y | REAL | 输出 | 标定后的工程值 |
SCL 示例:
VAR
scaleTemp : SCALING;
rRaw : REAL; // 原始 ADC 值 0~27648
rTemp : REAL; // 温度 -40~150°C
END_VAR
// 4-20mA 温度传感器标定
scaleTemp(X := rRaw, X_LOW := 0.0, X_HIGH := 27648.0,
Y_LOW := -40.0, Y_HIGH := 150.0);
rTemp := scaleTemp.Y;
计算公式:Y = Y_LOW + (X - X_LOW) * (Y_HIGH - Y_LOW) / (X_HIGH - X_LOW)
注意事项:
- 断线检测:如果原始值低于有效范围下限(如 4mA 对应 5530),应报传感器故障
- 电气零点和信号零点不同,注意区分
5.6 LIMIT — 限幅器
功能描述:将输入信号限制在指定范围内,超出则钳位到边界值。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
X | REAL | 输入 | 输入信号 |
H | REAL | 输入 | 上限 |
L | REAL | 输入 | 下限 |
Y | REAL | 输出 | 限幅后的输出 |
QH | BOOL | 输出 | 超出上限标志 |
QL | BOOL | 输出 | 超出下限标志 |
SCL 示例:
VAR
limitSpeed : LIMIT;
rSpeedCmd : REAL; // 速度指令
rSpeedOut : REAL; // 限幅后速度
bOverSpeed : BOOL; // 超速标志
END_VAR
// 速度限幅 0~3000 RPM
limitSpeed(X := rSpeedCmd, H := 3000.0, L := 0.0);
rSpeedOut := limitSpeed.Y;
bOverSpeed := limitSpeed.QH;
5.7 DEADBAND — 死区滤波器
功能描述:在零附近设置一个不敏感区间,消除噪声引起的微小幅值波动。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
X | REAL | 输入 | 输入信号 |
BAND | REAL | 输入 | 死区宽度(对称) |
Y | REAL | 输出 | 滤波后输出 |
SCL 示例:
VAR
dbLevel : DEADBAND;
rLevel : REAL; // 液位信号
rFiltered : REAL; // 滤波后
END_VAR
// 死区 ±0.5mm,消除液面波动
dbLevel(X := rLevel, BAND := 0.5);
rFiltered := dbLevel.Y;
原理:|X| < BAND 时输出 0,否则输出 X - sign(X) * BAND
5.8 RAMP — 斜坡发生器
功能描述:使输出平滑地从当前值变化到目标值,防止突变。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
ENABLE | BOOL | 输入 | 使能斜坡 |
TARGET | REAL | 输入 | 目标值 |
RISE_TIME | TIME | 输入 | 上升时间(从 0 到 100%) |
FALL_TIME | TIME | 输入 | 下降时间(从 100% 到 0) |
Y | REAL | 输出 | 当前斜坡输出 |
BUSY | BOOL | 输出 | 斜坡进行中 |
DONE | BOOL | 输出 | 斜坡完成 |
时序图:
TARGET ─┐
│
│ ┌───────
│ ╱
│ ╱
│ ╱
│╱
└──────────────────────→
Y ┌───┐
│ ╲
│ ╲
│ ╲
│ └───────────────→
↑ RISE_TIME ↑ FALL_TIME
SCL 示例:
VAR
rampSpeed : RAMP;
rTargetSpeed : REAL := 1500.0; // 目标速度
rCurrentSpeed : REAL; // 当前速度
END_VAR
// 速度斜坡:加速 5 秒,减速 3 秒
rampSpeed(ENABLE := TRUE, TARGET := rTargetSpeed,
RISE_TIME := T#5s, FALL_TIME := T#3s);
rCurrentSpeed := rampSpeed.Y;
实际应用:传送带平稳启停
PROGRAM ConveyorRamp
VAR
rampCv : RAMP;
bRun : BOOL AT %IX0.0;
rSpeed : REAL AT %QW0; // 变频器速度指令
END_VAR
// 斜坡加减速,防止机械冲击
rampCv(ENABLE := bRun, TARGET := 50.0,
RISE_TIME := T#3s, FALL_TIME := T#2s);
rSpeed := rampCv.Y;
END_PROGRAM
5.9 PULSEGEN — 脉冲串发生器
功能描述:生成指定数量和频率的脉冲串,用于步进电机驱动等场景。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
TRIGGER | BOOL | 输入 | 启动脉冲串(上升沿) |
FREQUENCY | REAL | 输入 | 脉冲频率 Hz |
COUNT | UDINT | 输入 | 脉冲数量 |
Q | BOOL | 输出 | 脉冲输出 |
BUSY | BOOL | 输出 | 正在发送脉冲 |
DONE | BOOL | 输出 | 脉冲发送完成 |
REMAINING | UDINT | 输出 | 剩余脉冲数 |
SCL 示例:
VAR
pgStep : PULSEGEN;
bStart : BOOL;
bStepPulse : BOOL AT %QX0.0;
END_VAR
// 步进电机驱动:发 200 个脉冲,频率 500Hz
pgStep(TRIGGER := bStart, FREQUENCY := 500.0, COUNT := 200);
bStepPulse := pgStep.Q;
5.10 PWM — 脉宽调制发生器
功能描述:生成 PWM 信号,输出占空比可调,用于加热器、灯光、阀门的比例控制。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
ENABLE | BOOL | 输入 | 使能 |
PERIOD | TIME | 输入 | PWM 周期 |
DUTY | REAL | 输入 | 占空比 0.0~100.0% |
Q | BOOL | 输出 | PWM 输出 |
时序图:
PERIOD ──┬─────── 周期 ────────┬───────
│ │
│<── DUTY% ──>│ │
Q ┌────────────┐ ┌────
│ │ │
└────────────┘ └────
SCL 示例:
VAR
pwmHeater : PWM;
rDuty : REAL := 65.0; // 占空比 65%
bHeater : BOOL AT %QX0.0; // 加热器 SSR 控制
END_VAR
// PWM 加热器控制
pwmHeater(ENABLE := TRUE, PERIOD := T#2s, DUTY := rDuty);
bHeater := pwmHeater.Q;
注意事项:
- 周期选择要权衡:太短(< 50ms)可能导致 SSR 频繁开关;太长(> 10s)控制精度差
- 固态继电器(SSR)推荐周期 1~2s
5.11 AVERAGE — 移动平均滤波器
功能描述:对输入信号做 N 次移动平均,消除随机噪声。N 越大越平滑,延迟也越大。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
X | REAL | 输入 | 输入信号 |
N | UINT | 输入 | 平均窗口大小(2~1024) |
RESET | BOOL | 输入 | 复位缓冲区 |
Y | REAL | 输出 | 平均值 |
BUFFER_FULL | BOOL | 输出 | 缓冲区已满(输出稳定) |
SCL 示例:
VAR
avgPressure : AVERAGE;
rPressure : REAL; // 压力传感器原始值
rSmooth : REAL; // 平滑后压力值
END_VAR
// 64 点移动平均
avgPressure(X := rPressure, N := 64);
rSmooth := avgPressure.Y;
5.12 MEDIAN — 中值滤波器
功能描述:对输入信号取 N 个采样值的中位数,有效消除脉冲噪声(尖峰),同时保留边缘信息。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
X | REAL | 输入 | 输入信号 |
N | UINT | 输入 | 窗口大小(必须奇数,3~31) |
RESET | BOOL | 输入 | 复位缓冲区 |
Y | REAL | 输出 | 中值输出 |
SCL 示例:
VAR
medLevel : MEDIAN;
rLevel : REAL; // 液位信号(可能有尖峰干扰)
rFiltered : REAL; // 中值滤波后
END_VAR
// 5 点中值滤波,消除传感器尖峰
medLevel(X := rLevel, N := 5);
rFiltered := medLevel.Y;
AVERAGE 与 MEDIAN 对比:
| 特性 | AVERAGE | MEDIAN |
|---|---|---|
| 高斯噪声抑制 | 优 | 一般 |
| 脉冲噪声抑制 | 一般 | 优 |
| 边缘保持 | 差(模糊) | 好 |
| 延迟 | N/2 周期 | N/2 周期 |
5.13 COUNTER_MODULO — 模 N 计数器
功能描述:计数到 N 后自动归零并输出进位信号。常用于分频、循环计数。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
CU | BOOL | 输入 | 计数脉冲(上升沿) |
N | UDINT | 输入 | 模数(2~4294967295) |
RESET | BOOL | 输入 | 复位 |
CV | UDINT | 输出 | 当前计数值 |
CARRY | BOOL | 输出 | 进位脉冲(每个周期一个脉冲) |
SCL 示例:
VAR
cmCycle : COUNTER_MODULO;
bSensor : BOOL;
iCycle : UDINT; // 当前周期序号
bNewCycle : BOOL; // 新周期开始
END_VAR
// 每 10 个产品为一个周期
cmCycle(CU := bSensor, N := 10);
iCycle := cmCycle.CV;
bNewCycle := cmCycle.CARRY;
5.14 SHIFT_REG — 移位寄存器
功能描述:在时钟脉冲的上升沿,将数据逐位从低位向高位移动。常用于序列检测、数据串行化。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
CLK | BOOL | 输入 | 时钟脉冲(上升沿触发移位) |
DATA_IN | BOOL | 输入 | 串行数据输入 |
LENGTH | UINT | 输入 | 寄存器长度(1~1024) |
RESET | BOOL | 输入 | 复位所有位为 0 |
DATA_OUT | BOOL | 输出 | 串行数据输出(移出的最高位) |
PARALLEL_OUT | ARRAY[] OF BOOL | 输出 | 并行输出(位数组) |
SCL 示例:
VAR
srBits : SHIFT_REG;
bClk : BOOL;
bData : BOOL;
bOut : BOOL;
END_VAR
srBits(CLK := bClk, DATA_IN := bData, LENGTH := 8);
bOut := srBits.DATA_OUT;
5.15 FIFO — 先进先出缓冲区
功能描述:先存入的数据先取出,适用于数据缓冲、任务排队。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
PUT | BOOL | 输入 | 存入数据(上升沿) |
GET | BOOL | 输入 | 取出数据(上升沿) |
DATA_IN | ANY | 输入 | 存入的数据 |
RESET | BOOL | 输入 | 清空缓冲区 |
DATA_OUT | ANY | 输出 | 取出的数据 |
FULL | BOOL | 输出 | 缓冲区满 |
EMPTY | BOOL | 输出 | 缓冲区空 |
COUNT | UINT | 输出 | 当前元素数量 |
SCL 示例:
VAR
fifoAlarm : FIFO;
bPut : BOOL;
bGet : BOOL;
iNewAlarm : INT; // 新报警代码
iOldAlarm : INT; // 取出最早的报警
bQueueFull : BOOL;
END_VAR
// 报警队列:先进先出
fifoAlarm(PUT := bPut, GET := bGet, DATA_IN := iNewAlarm);
iOldAlarm := fifoAlarm.DATA_OUT;
bQueueFull := fifoAlarm.FULL;
5.16 LIFO — 后进先出缓冲区
功能描述:后存入的数据先取出(栈结构),适用于现场恢复、撤销操作。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
PUSH | BOOL | 输入 | 压栈(上升沿) |
POP | BOOL | 输入 | 出栈(上升沿) |
DATA_IN | ANY | 输入 | 压入的数据 |
RESET | BOOL | 输入 | 清空栈 |
DATA_OUT | ANY | 输出 | 弹出的数据 |
FULL | BOOL | 输出 | 栈满 |
EMPTY | BOOL | 输出 | 栈空 |
COUNT | UINT | 输出 | 当前栈中元素数量 |
SCL 示例:
VAR
lifoCmd : LIFO;
bPush : BOOL;
bPop : BOOL;
iNewCmd : INT;
iLastCmd : INT;
END_VAR
// 命令栈:后进先出
lifoCmd(PUSH := bPush, POP := bPop, DATA_IN := iNewCmd);
iLastCmd := lifoCmd.DATA_OUT;
5.17 SEL — 二选一选择器
功能描述:根据 S 选择输出两个输入之一。S=FALSE 输出 IN0,S=TRUE 输出 IN1。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
S | BOOL | 输入 | 选择信号 |
IN0 | ANY | 输入 | 输入 0(S=FALSE 时选中) |
IN1 | ANY | 输入 | 输入 1(S=TRUE 时选中) |
Y | ANY | 输出 | 选中输出 |
SCL 示例:
VAR
selMode : SEL;
rAuto : REAL := 100.0;
rManual : REAL := 50.0;
bAutoMode : BOOL;
rOutput : REAL;
END_VAR
selMode(S := bAutoMode, IN0 := rManual, IN1 := rAuto);
rOutput := selMode.Y;
5.18 MUX — 多路选择器
功能描述:根据 S 值从多个输入中选择一个输出。S=0 选 IN0,S=1 选 IN1,依此类推。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
S | UINT | 输入 | 选择信号(0~N-1) |
IN0 | ANY | 输入 | 输入通道 0 |
IN1 | ANY | 输入 | 输入通道 1 |
IN2 | ANY | 输入 | 输入通道 2 |
IN3 | ANY | 输入 | 输入通道 3 |
Y | ANY | 输出 | 选中的输入 |
SCL 示例:
VAR
muxRecipe : MUX;
iRecipeNo : UINT; // 配方号 0~3
rTemp0 : REAL := 100.0; // 配方 0 温度
rTemp1 : REAL := 120.0; // 配方 1 温度
rTemp2 : REAL := 150.0; // 配方 2 温度
rTemp3 : REAL := 200.0; // 配方 3 温度
rTargetTemp : REAL;
END_VAR
// 配方选择
muxRecipe(S := iRecipeNo, IN0 := rTemp0, IN1 := rTemp1,
IN2 := rTemp2, IN3 := rTemp3);
rTargetTemp := muxRecipe.Y;
5.19 DEMUX — 多路分配器
功能描述:将输入信号分配到多个输出通道之一,由 S 选择目标通道。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
S | UINT | 输入 | 选择信号(0~N-1) |
X | ANY | 输入 | 输入信号 |
Y0 | ANY | 输出 | 输出通道 0 |
Y1 | ANY | 输出 | 输出通道 1 |
Y2 | ANY | 输出 | 输出通道 2 |
Y3 | ANY | 输出 | 输出通道 3 |
SCL 示例:
VAR
demuxValve : DEMUX;
iCh : UINT; // 通道号
rOpenVal : REAL; // 阀门开度
rValve0 : REAL; // 阀门 0 开度
rValve1 : REAL; // 阀门 1 开度
rValve2 : REAL; // 阀门 2 开度
rValve3 : REAL; // 阀门 3 开度
END_VAR
demuxValve(S := iCh, X := rOpenVal,
Y0 := rValve0, Y1 := rValve1,
Y2 := rValve2, Y3 := rValve3);
5.20 SORT — 数组排序
功能描述:对数组进行升序排序,可同时输出原始索引。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
ENABLE | BOOL | 输入 | 触发排序(上升沿) |
ARR_IN | ARRAY[] OF REAL | 输入 | 待排序数组 |
ARR_OUT | ARRAY[] OF REAL | 输出 | 排序后的数组 |
IDX_OUT | ARRAY[] OF UINT | 输出 | 原始索引映射 |
DONE | BOOL | 输出 | 排序完成 |
SCL 示例:
VAR
sortData : SORT;
arrRaw : ARRAY[0..9] OF REAL;
arrSorted : ARRAY[0..9] OF REAL;
arrIdx : ARRAY[0..9] OF UINT;
bSort : BOOL;
END_VAR
sortData(ENABLE := bSort, ARR_IN := arrRaw,
ARR_OUT := arrSorted, IDX_OUT := arrIdx);
5.21 ENCODER — 二进制编码器
功能描述:将独热码(one-hot)输入编码为二进制输出。如 IN2=TRUE 时输出 Y=2。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
IN0~IN7 | BOOL | 输入 | 8 位输入(独热码) |
Y | UINT | 输出 | 编码后的二进制值 |
VALID | BOOL | 输出 | 输入有效(至少一位为 TRUE) |
ERROR | BOOL | 输出 | 错误(多位为 TRUE) |
SCL 示例:
VAR
enc : ENCODER;
bIn0, bIn1, bIn2, bIn3 : BOOL;
iCode : UINT;
bValid : BOOL;
END_VAR
enc(IN0 := bIn0, IN1 := bIn1, IN2 := bIn2, IN3 := bIn3);
iCode := enc.Y;
bValid := enc.VALID;
5.22 DECODER — 二进制解码器
功能描述:将二进制输入解码为独热码输出。如 Y=2 时 OUT2=TRUE。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
X | UINT | 输入 | 二进制输入 |
OUT0~OUT7 | BOOL | 输出 | 8 位解码输出 |
SCL 示例:
VAR
dec : DECODER;
iSelect : UINT;
bSel0, bSel1, bSel2, bSel3 : BOOL;
END_VAR
dec(X := iSelect, OUT0 := bSel0, OUT1 := bSel1,
OUT2 := bSel2, OUT3 := bSel3);
5.23 BCD_TO_INT — BCD 码转整数
功能描述:将 BCD 编码(Binary-Coded Decimal)转换为整数。常用于读取 BCD 编码的拨码开关或设备参数。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
BCD_VALUE | WORD | 输入 | BCD 编码输入 |
INT_VALUE | INT | 输出 | 转换后的整数 |
ERROR | BOOL | 输出 | BCD 格式错误(无效的 nibble) |
SCL 示例:
VAR
bcdInput : BCD_TO_INT;
wSwitch : WORD; // BCD 拨码开关 0x1234
iValue : INT; // 转换结果 1234
bErr : BOOL;
END_VAR
bcdInput(BCD_VALUE := wSwitch);
iValue := bcdInput.INT_VALUE;
bErr := bcdInput.ERROR;
5.24 INT_TO_BCD — 整数转 BCD 码
功能描述:将整数转换为 BCD 编码。用于输出到 BCD 显示的设备。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
INT_VALUE | INT | 输入 | 整数输入(0~9999) |
BCD_VALUE | WORD | 输出 | BCD 编码输出 |
ERROR | BOOL | 输出 | 超出范围 |
SCL 示例:
VAR
intToBcd : INT_TO_BCD;
iCount : INT := 1234;
wBcdOut : WORD;
END_VAR
intToBcd(INT_VALUE := iCount);
wBcdOut := intToBcd.BCD_VALUE; // 0x1234
5.25 SEG7 — 七段数码管编码器
功能描述:将 09 的数字编码为七段数码管的段选信号(ag)。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
VALUE | UINT | 输入 | 显示数字(0~9) |
DP | BOOL | 输入 | 小数点控制 |
BLANK | BOOL | 输入 | 消隐(全部熄灭) |
SEG_A~SEG_G | BOOL | 输出 | 段选信号 |
SEG_DP | BOOL | 输出 | 小数点输出 |
SCL 示例:
VAR
seg : SEG7;
iDigit : UINT := 5;
a, b, c, d, e, f, g : BOOL;
END_VAR
seg(VALUE := iDigit, DP := FALSE);
a := seg.SEG_A;
b := seg.SEG_B;
c := seg.SEG_C;
d := seg.SEG_D;
e := seg.SEG_E;
f := seg.SEG_F;
g := seg.SEG_G;
5.26 GRAY_CODE — 格雷码编解码器
功能描述:在格雷码和二进制之间转换。格雷码相邻数值只有一位变化,常用于编码器位置读取,防止多位同时变化时的读取错误。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
MODE | BOOL | 输入 | FALSE=二进制→格雷码, TRUE=格雷码→二进制 |
X | UDINT | 输入 | 输入值 |
Y | UDINT | 输出 | 转换结果 |
SCL 示例:
VAR
gcEncoder : GRAY_CODE;
rawPos : UDINT; // 来自格雷码编码器
realPos : UDINT; // 解码后的真实位置
END_VAR
// 格雷码 -> 二进制(解码编码器位置)
gcEncoder(MODE := TRUE, X := rawPos);
realPos := gcEncoder.Y;
六、通讯功能块 (Communication FB)
通讯功能块用于实现网络通信,包括 TCP 和 UDP 协议。
6.1 TCON — TCP 连接建立
功能描述:建立 TCP 连接到远程服务器。支持主动连接(客户端模式)。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
REQ | BOOL | 输入 | 连接请求(上升沿触发) |
CONNECT_ID | UINT | 输入 | 连接标识符(1~65535) |
SERVER_IP | STRING(15) | 输入 | 服务器 IP 地址 |
SERVER_PORT | UINT | 输入 | 服务器端口 |
LOCAL_PORT | UINT | 输入 | 本地端口(0=自动分配) |
DONE | BOOL | 输出 | 连接建立成功 |
BUSY | BOOL | 输出 | 连接进行中 |
ERROR | BOOL | 输出 | 错误标志 |
STATUS | WORD | 输出 | 状态码 |
SCL 示例:
VAR
tconPLC : TCON;
bConnect : BOOL;
bDone : BOOL;
END_VAR
// 连接到上位机 192.168.1.100:502
tconPLC(REQ := bConnect, CONNECT_ID := 1,
SERVER_IP := '192.168.1.100', SERVER_PORT := 502);
bDone := tconPLC.DONE;
6.2 TSEND — TCP 数据发送
功能描述:通过已建立的 TCP 连接发送数据。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
REQ | BOOL | 输入 | 发送请求(上升沿触发) |
CONNECT_ID | UINT | 输入 | 连接标识符 |
DATA | ARRAY[] OF BYTE | 输入 | 待发送数据 |
LENGTH | UINT | 输入 | 发送数据长度 |
DONE | BOOL | 输出 | 发送完成 |
BUSY | BOOL | 输出 | 发送进行中 |
ERROR | BOOL | 输出 | 错误标志 |
STATUS | WORD | 输出 | 状态码 |
SCL 示例:
VAR
tsendData : TSEND;
bSend : BOOL;
sendBuf : ARRAY[0..255] OF BYTE;
END_VAR
tsendData(REQ := bSend, CONNECT_ID := 1,
DATA := sendBuf, LENGTH := 100);
6.3 TRCV — TCP 数据接收
功能描述:通过已建立的 TCP 连接接收数据。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
ENABLE | BOOL | 输入 | 使能接收 |
CONNECT_ID | UINT | 输入 | 连接标识符 |
DATA | ARRAY[] OF BYTE | 输出 | 接收缓冲区 |
BUFFER_SIZE | UINT | 输入 | 缓冲区大小 |
RCVD_LEN | UINT | 输出 | 实际接收长度 |
DONE | BOOL | 输出 | 接收完成 |
BUSY | BOOL | 输出 | 等待接收中 |
ERROR | BOOL | 输出 | 错误标志 |
SCL 示例:
VAR
trcvData : TRCV;
bEnable : BOOL := TRUE;
recvBuf : ARRAY[0..255] OF BYTE;
rcvdLen : UINT;
END_VAR
trcvData(ENABLE := bEnable, CONNECT_ID := 1,
DATA := recvBuf, BUFFER_SIZE := 256);
rcvdLen := trcvData.RCVD_LEN;
6.4 TDISCON — TCP 断开连接
功能描述:断开指定 ID 的 TCP 连接。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
REQ | BOOL | 输入 | 断开请求(上升沿触发) |
CONNECT_ID | UINT | 输入 | 连接标识符 |
DONE | BOOL | 输出 | 断开完成 |
BUSY | BOOL | 输出 | 断开进行中 |
ERROR | BOOL | 输出 | 错误标志 |
STATUS | WORD | 输出 | 状态码 |
SCL 示例:
VAR
tdisc : TDISCON;
bDisc : BOOL;
END_VAR
tdisc(REQ := bDisc, CONNECT_ID := 1);
6.5 TUSEND — UDP 数据发送
功能描述:通过 UDP 发送数据报文。UDP 是无连接协议,不需要先建立连接。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
REQ | BOOL | 输入 | 发送请求(上升沿) |
DATA | ARRAY[] OF BYTE | 输入 | 待发送数据 |
LENGTH | UINT | 输入 | 数据长度 |
TARGET_IP | STRING(15) | 输入 | 目标 IP |
TARGET_PORT | UINT | 输入 | 目标端口 |
DONE | BOOL | 输出 | 发送完成 |
ERROR | BOOL | 输出 | 错误标志 |
SCL 示例:
VAR
tusend : TUSEND;
bSend : BOOL;
buf : ARRAY[0..63] OF BYTE;
END_VAR
// 向 192.168.1.200:10000 发送 UDP 广播
tusend(REQ := bSend, DATA := buf, LENGTH := 64,
TARGET_IP := '192.168.1.200', TARGET_PORT := 10000);
6.6 TURCV — UDP 数据接收
功能描述:接收 UDP 数据报文。可指定本地端口监听。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
ENABLE | BOOL | 输入 | 使能接收 |
LOCAL_PORT | UINT | 输入 | 本地监听端口 |
DATA | ARRAY[] OF BYTE | 输出 | 接收缓冲区 |
BUFFER_SIZE | UINT | 输入 | 缓冲区大小 |
RCVD_LEN | UINT | 输出 | 实际接收长度 |
SOURCE_IP | STRING(15) | 输出 | 发送方 IP |
SOURCE_PORT | UINT | 输出 | 发送方端口 |
DONE | BOOL | 输出 | 接收完成 |
ERROR | BOOL | 输出 | 错误标志 |
SCL 示例:
VAR
turcv : TURCV;
bEnable : BOOL := TRUE;
buf : ARRAY[0..255] OF BYTE;
len : UINT;
srcIP : STRING(15);
srcPort : UINT;
END_VAR
turcv(ENABLE := bEnable, LOCAL_PORT := 10000,
DATA := buf, BUFFER_SIZE := 256);
len := turcv.RCVD_LEN;
srcIP := turcv.SOURCE_IP;
srcPort := turcv.SOURCE_PORT;
6.7 T_CONFIG — 通讯参数配置
功能描述:配置通讯接口的通用参数,如超时、重试次数、缓冲区大小等。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
REQ | BOOL | 输入 | 配置请求(上升沿触发) |
INTERFACE_ID | UINT | 输入 | 接口标识符 |
TIMEOUT | TIME | 输入 | 通讯超时时间 |
RETRY_COUNT | UINT | 输入 | 重试次数 |
BUFFER_SIZE | UINT | 输入 | 缓冲区大小 |
DONE | BOOL | 输出 | 配置完成 |
ERROR | BOOL | 输出 | 错误标志 |
SCL 示例:
VAR
tCfg : T_CONFIG;
bCfg : BOOL;
END_VAR
tCfg(REQ := bCfg, INTERFACE_ID := 1,
TIMEOUT := T#5s, RETRY_COUNT := 3, BUFFER_SIZE := 1024);
七、系统功能块 (System FB)
系统功能块提供与 PLC 系统本身交互的能力,如时间同步、看门狗、诊断等。
7.1 SYNC — 系统同步
功能描述:同步多个 PLC 或模块之间的时间基准,用于分布式系统的协调控制。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
ENABLE | BOOL | 输入 | 使能同步 |
MODE | UINT | 输入 | 0=从站, 1=主站 |
SYNC_INTERVAL | TIME | 输入 | 同步间隔 |
SYNCED | BOOL | 输出 | 同步状态 TRUE=已同步 |
OFFSET | TIME | 输出 | 时间偏差 |
ERROR | BOOL | 输出 | 同步错误 |
SCL 示例:
VAR
syncBus : SYNC;
bSyncOK : BOOL;
END_VAR
syncBus(ENABLE := TRUE, MODE := 0, SYNC_INTERVAL := T#1s);
bSyncOK := syncBus.SYNCED;
7.2 WATCHDOG — 看门狗定时器
功能描述:监控程序运行状态,超时未喂狗则触发故障处理。用于检测程序死锁、任务挂起。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
ENABLE | BOOL | 输入 | 使能看门狗 |
TIMEOUT | TIME | 输入 | 超时时间 |
FEED | BOOL | 输入 | 喂狗输入(上升沿复位定时器) |
Q | BOOL | 输出 | 正常状态(TRUE=正常) |
TRIGGERED | BOOL | 输出 | 看门狗触发标志 |
ELAPSED | TIME | 输出 | 距上次喂狗时间 |
SCL 示例:
VAR
wdgMain : WATCHDOG;
bFeed : BOOL;
bHealthy : BOOL;
END_VAR
// 每 500ms 必须喂狗一次
wdgMain(ENABLE := TRUE, TIMEOUT := T#500ms, FEED := bFeed);
bHealthy := wdgMain.Q;
// 主循环中确保喂狗
IF bHealthy THEN
// 程序运行正常
ELSE
// 看门狗触发,执行安全停机
END_IF;
实际应用:程序运行监控
PROGRAM SafetyMonitor
VAR
wdgTask1 : WATCHDOG;
wdgTask2 : WATCHDOG;
bFeed1 : BOOL;
bFeed2 : BOOL;
bAllOK : BOOL;
bEstop : BOOL AT %QX0.0;
END_VAR
// 监控两个关键任务,每个 1s 超时
wdgTask1(ENABLE := TRUE, TIMEOUT := T#1s, FEED := bFeed1);
wdgTask2(ENABLE := TRUE, TIMEOUT := T#1s, FEED := bFeed2);
// 任一任务超时 -> 急停
bAllOK := wdgTask1.Q AND wdgTask2.Q;
bEstop := NOT bAllOK;
END_PROGRAM
7.3 DIAG — 诊断信息
功能描述:获取 PLC 系统的诊断信息,如 CPU 使用率、扫描周期、内存状态等。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
REQ | BOOL | 输入 | 读取请求(上升沿触发) |
DIAG_TYPE | UINT | 输入 | 诊断类型:0=CPU, 1=内存, 2=IO, 3=网络 |
DONE | BOOL | 输出 | 诊断完成 |
VALUE1 | REAL | 输出 | 诊断数据 1(如 CPU 负载 %) |
VALUE2 | REAL | 输出 | 诊断数据 2(如扫描周期 ms) |
VALUE3 | REAL | 输出 | 诊断数据 3(如内存使用 MB) |
ERROR | BOOL | 输出 | 错误标志 |
STATUS | WORD | 输出 | 状态码 |
SCL 示例:
VAR
diagCPU : DIAG;
bReq : BOOL;
cpuLoad : REAL;
scanTime : REAL;
END_VAR
diagCPU(REQ := bReq, DIAG_TYPE := 0);
cpuLoad := diagCPU.VALUE1; // CPU 负载百分比
scanTime := diagCPU.VALUE2; // 当前扫描周期 ms
7.4 TIMESTAMP — 系统时间戳
功能描述:获取当前系统时间戳,支持多种格式输出。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
ENABLE | BOOL | 输入 | 使能读取 |
FORMAT | UINT | 输入 | 0=毫秒, 1=微秒, 2=日期时间字符串 |
TS_MS | UDINT | 输出 | 毫秒时间戳(自启动) |
TS_US | ULINT | 输出 | 微秒时间戳 |
DATE_STR | STRING(32) | 输出 | 日期时间字符串 '2026-07-26 14:30:00' |
VALID | BOOL | 输出 | 时间有效 |
SCL 示例:
VAR
tsNow : TIMESTAMP;
ms : UDINT;
dtStr : STRING(32);
END_VAR
tsNow(ENABLE := TRUE, FORMAT := 0);
ms := tsNow.TS_MS;
dtStr := tsNow.DATE_STR;
7.5 SIMULATION — 仿真模式控制
功能描述:控制 PLC 运行在仿真模式,用于离线调试和测试。
参数表:
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
ENABLE | BOOL | 输入 | 使能仿真模式 |
SIM_MODE | UINT | 输入 | 0=IO 仿真, 1=全部仿真, 2=时序仿真 |
ACTIVE | BOOL | 输出 | 仿真模式激活标志 |
ERROR | BOOL | 输出 | 错误标志 |
SCL 示例:
VAR
simCtrl : SIMULATION;
bSimOn : BOOL;
END_VAR
// 开启 IO 仿真模式
simCtrl(ENABLE := TRUE, SIM_MODE := 0);
bSimOn := simCtrl.ACTIVE;
八、综合示例:温度控制站
下面是一个综合运用多种功能块的实际工业控制案例:
PROGRAM TempStation
VAR
// 传感器输入
rTempActual : REAL AT %IW0; // 实际温度(ADC 原始值)
bStartBtn : BOOL AT %IX0.0; // 启动按钮
bStopBtn : BOOL AT %IX0.1; // 停止按钮
bEstop : BOOL AT %IX0.2; // 急停(常闭)
// 执行器输出
rHeaterOut : REAL AT %QW0; // 加热器输出 0~100%
bPumpRun : BOOL AT %QX0.0; // 水泵运行
bAlarm : BOOL AT %QX0.1; // 报警指示灯
// 功能块实例
scaleTemp : SCALING; // 模拟量标定
pidTemp : PID; // PID 控制器
rampHeater : RAMP; // 加热器斜坡
hysAlarm : HYSTERESIS; // 超温报警
ftEstop : F_TRIG; // 急停下降沿检测
rsRun : RS; // 运行状态(复位优先)
avgTemp : AVERAGE; // 温度平滑
wdgCtrl : WATCHDOG; // 控制循环看门狗
tCfg : T_CONFIG; // 通讯配置
tconScada : TCON; // 上位机连接
tsendAlarm : TSEND; // 报警上报
// 变量
rTempScaled : REAL; // 标定后温度
rTempSmooth : REAL; // 平滑后温度
rSetpoint : REAL := 150.0; // 目标温度
bRunState : BOOL; // 运行状态
bSendAlarm : BOOL; // 报警发送标志
alarmBuf : ARRAY[0..63] OF BYTE; // 报警数据缓冲区
cycleCount : UDINT; // 运行周期计数
cmCycle : COUNTER_MODULO; // 周期计数器
END_VAR
// ===== 1. 温度信号处理 =====
// 标定:ADC 0~27648 -> 温度 0~300°C
scaleTemp(X := rTempActual, X_LOW := 0.0, X_HIGH := 27648.0,
Y_LOW := 0.0, Y_HIGH := 300.0);
rTempScaled := scaleTemp.Y;
// 移动平均滤波,窗口 16 点
avgTemp(X := rTempScaled, N := 16);
rTempSmooth := avgTemp.Y;
// ===== 2. 运行状态控制 =====
// 急停检测(下降沿 -> 急停触发)
ftEstop(CLK := bEstop);
// 复位优先触发器:启动/停止/急停
rsRun(SET := bStartBtn, RESET1 := bStopBtn OR ftEstop.Q);
bRunState := rsRun.Q1;
bPumpRun := bRunState;
// ===== 3. PID 温度控制 =====
IF bRunState THEN
// 斜坡给定:目标温度 150°C,加速 30s 减速 20s
rampHeater(ENABLE := TRUE, TARGET := rSetpoint,
RISE_TIME := T#30s, FALL_TIME := T#20s);
// PID 控制,周期 200ms
pidTemp(SETPOINT := rampHeater.Y, ACTUAL := rTempSmooth,
KP := 2.8, TI := 12.0, TD := 0.0, CYCLE := T#200ms,
LIMIT_H := 100.0, LIMIT_L := 0.0);
rHeaterOut := pidTemp.OUTPUT;
ELSE
rHeaterOut := 0.0;
END_IF;
// ===== 4. 超温报警 =====
// 温度 > 280°C 报警,< 260°C 解除(带滞回防抖动)
hysAlarm(X := rTempSmooth, ON_POINT := 280.0, OFF_POINT := 260.0);
bAlarm := hysAlarm.Q;
// ===== 5. 看门狗监控 =====
// 每个周期喂狗,超时 1s
wdgCtrl(ENABLE := TRUE, TIMEOUT := T#1s, FEED := TRUE);
// 如果看门狗触发 -> 停机
IF NOT wdgCtrl.Q THEN
bPumpRun := FALSE;
rHeaterOut := 0.0;
bAlarm := TRUE;
END_IF;
// ===== 6. 通讯:上位机连接 =====
tCfg(REQ := bStartBtn, INTERFACE_ID := 1,
TIMEOUT := T#5s, RETRY_COUNT := 3, BUFFER_SIZE := 1024);
tconScada(REQ := bStartBtn, CONNECT_ID := 1,
SERVER_IP := '192.168.1.100', SERVER_PORT := 502);
// ===== 7. 报警上报 =====
IF bAlarm AND NOT bSendAlarm THEN
// 报警发生 -> 发送报警数据到上位机
tsendAlarm(REQ := TRUE, CONNECT_ID := 1,
DATA := alarmBuf, LENGTH := 64);
bSendAlarm := TRUE;
ELSIF NOT bAlarm THEN
bSendAlarm := FALSE;
END_IF;
// ===== 8. 运行周期计数 =====
cmCycle(CU := TRUE, N := 1000);
cycleCount := cmCycle.CV;
END_PROGRAM
九、排错速查表
| 问题 | 原因 | 解决方法 |
|---|---|---|
| TON 不触发输出 Q | IN 保持时间 < PT | 检查 IN 信号持续时间是否足够 |
| TOF 不受控 | 不理解 TOF 在 IN=TRUE 时 Q=TRUE | 注意 TOF 在 IN 有效时 Q 立即输出 |
| TP 只触发一次 | 脉冲中再次触发被忽略 | 需要可重触发脉冲,用 TON + R_TRIG |
| 计数器不计数 | 脉冲宽度 < 扫描周期 | 使用 R_TRIG 捕获边沿,或改用 HSC |
| CTUD 值异常跳变 | CU 和 CD 同周期同时触发 | 加互锁确保不同时触发 |
| R_TRIG 漏检 | 输入变化太快 | 使用硬件中断或高速计数器模块 |
| ET 时间不准确 | OB 周期抖动 | 放周期中断 OB(如 OB30)而非 OB1 |
| SR 无法复位 | 未理解 SET1 优先级高于 RESET | 改 RS 或检查逻辑 |
| PID 输出震荡 | KP 过大或 TI 过小 | 降低 KP 或增加 TI |
| PID 积分饱和 | 输出长时间卡在限幅值 | 检查输出限幅是否正确,是否需复位积分 |
| AVERAGE 输出延迟大 | N 窗口设置太大 | 减小 N 值,或改用 MEDIAN |
| FIFO 数据丢失 | 读速度 < 写速度导致溢出 | 增大缓冲区或提高读取频率 |
| TCON 连接失败 | IP 地址或端口错误 | 使用 PING 测试网络连通性 |
| WATCHDOG 频繁触发 | 扫描周期大于 TIMEOUT | 增大 TIMEOUT 或将程序拆到多个 OB |
| 通讯 FB 状态码异常 | 通讯参数配置错误 | 调用 T_CONFIG 设置正确的超时和重试 |