文章目录

ST定时器调用:TON/TOF在ST中必须实例化,不能像梯形图直接使用

发布于 2026-03-20 09:51:52 · 浏览 5 次 · 评论 0 条

在结构化文本(ST)编程中调用定时器功能块(如 TONTOF)时,必须显式声明并实例化,不能像梯形图(LAD)中那样直接拖放一个定时器符号、填写参数就完成调用。这是 ST 语言语法本质决定的——它基于 Pascal 风格的强类型函数块调用机制,所有功能块(FB)都属于“类模板”,必须先创建具体对象(即实例),才能访问其输入、输出和内部状态。


一、为什么 ST 中不能“直接使用”TON/TOF?

梯形图中的定时器(例如 TON T37, T#5S)看似“直接”,实则是编辑器在后台自动完成了三件事:

  1. 隐式声明一个名为 T37TON 类型变量;
  2. 自动绑定该变量到当前网络的作用域;
  3. 静态分配其背景数据块(DB)或内部存储空间。

而 ST 是纯文本语言,没有图形上下文,也不支持隐式声明。你写的每一行代码,都必须明确告诉 PLC:

  • 这个定时器叫什么名字(实例名);
  • 它的数据类型是什么(TONTOF);
  • 它的输入参数(IN, PT)由谁提供;
  • 它的输出(Q, ET)要赋给哪个变量。

否则,编译器会报错:
Error 42: 'TON' is a function block type, not a function. An instance must be declared.


二、正确调用步骤(以 TON 为例)

1. 声明定时器实例变量

VARVAR_GLOBAL 区域中,声明一个具名变量,类型为 TON

VAR
    MyTimer1 : TON;         // ✅ 正确:声明一个名为 MyTimer1 的 TON 实例
    MyTimer2 : TOF;         // ✅ 同理,TOF 实例
END_VAR

⚠️ 注意:

  • TONTOF 是系统预定义的功能块类型(IEC 61131-3 标准),首字母大写,不可写成 tonTon
  • 实例名(如 MyTimer1)必须符合标识符规则:以字母或下划线开头,仅含字母、数字、下划线,且不能与关键字冲突;
  • 不可省略分号 ;,这是 ST 的语句终结符。

2. 在程序体中调用该实例

PROGRAM 主体或 FUNCTION_BLOCK 内部,以函数块调用语法执行

MyTimer1(IN := StartButton, PT := T#8S);

这行代码等效于:

  • StartButton 的布尔值传给 MyTimer1IN 输入端;
  • 将时间常量 T#8S(8 秒)传给 PT(预设时间)输入端;
  • 执行 MyTimer1 的内部逻辑(检测上升沿、计时、置位 Q、更新 ET)。

✅ 关键点:

  • 调用必须使用 带参数名的赋值语法IN := ..., PT := ...),不可省略参数名;
  • 参数顺序不重要,但参数名必须准确(IN, PT, Q, ET 是标准接口,大小写敏感);
  • PT 必须是 TIME 类型,如 T#500MST#2ST#1M30S,不可写成整数 5000 或字符串 "5s"

3. 读取输出结果

定时器执行后,通过实例名访问其输出成员:

IF MyTimer1.Q THEN
    **启动电机**;
END_IF;

MotorRunTime := MyTimer1.ET;  // 获取已计时长(TIME 类型)

QBOOL 类型,表示定时完成;
ETTIME 类型,表示当前已计时长(从 INTRUE 开始累计,INFALSE 时清零)。


三、TON 与 TOF 的核心区别及调用要点

特性 TON(延时接通定时器) TOF(延时断开定时器)
触发条件 INFALSETRUE 的上升沿开始计时 INTRUEFALSE 的下降沿开始计时
Q 输出 计时 ≥ PTQTRUEINFALSEQ 立即变 FALSE INTRUEQ 始终为 TRUEINFALSE 后,计时 PT 时间,再将 QFALSE
ET 行为 INTRUE 时累加;INFALSEET 清零 INTRUEET 清零;INFALSE 时开始累加,达 PT 后停止
典型用途 启动延时(如:按下启动按钮后 3 秒再开泵) 停止延时(如:松开停止按钮后,风机再运行 10 秒散热)

调用 TOF 的语法完全一致,仅需替换实例类型和逻辑理解:

VAR
    CoolDownTimer : TOF;
END_VAR

// 在程序体中:
CoolDownTimer(IN := MotorStopSignal, PT := T#10S);

IF CoolDownTimer.Q THEN
    **保持风机运行**;
END_IF;

四、常见错误及修正方案

❌ 错误 1:把 TON 当作函数调用

// 错误!TON 不是函数,无返回值,不能这样写:
IF TON(IN := X, PT := T#3S).Q THEN ...

✅ 修正:必须先声明实例,再调用,最后读取 .Q

MyT : TON;
MyT(IN := X, PT := T#3S);
IF MyT.Q THEN ...

❌ 错误 2:漏掉 IN 参数

// 错误!TON 至少需要 IN 和 PT,缺一不可:
MyT(PT := T#3S);  // 编译报错:missing required parameter 'IN'

✅ 修正:显式提供 IN

MyT(IN := X, PT := T#3S);

❌ 错误 3:混淆 ET 类型与比较方式

// 错误!ET 是 TIME 类型,不能直接与整数比较:
IF MyT.ET > 5000 THEN ...  // ❌ 类型不匹配

✅ 修正:用 TIME_TO_MS() 转换,或直接与 TIME 常量比较:

IF MyT.ET >= T#5S THEN ...              // ✅ 推荐:同类型比较
IF TIME_TO_MS(MyT.ET) >= 5000 THEN ... // ✅ 转换为毫秒整数

❌ 错误 4:在 FORWHILE 循环内重复声明实例

FOR i := 1 TO 5 DO
    TempTimer : TON;  // ❌ 错误!VAR 声明不能在执行区
    TempTimer(IN := ..., PT := ...);
END_FOR;

✅ 修正:所有实例必须在 VAR 区统一声明,循环内只调用:

VAR
    TimerArray : ARRAY[1..5] OF TON;  // 声明数组实例
END_VAR

FOR i := 1 TO 5 DO
    TimerArray[i](IN := Trigger[i], PT := T#2S);
END_FOR;

五、进阶技巧:批量管理与复位控制

▶ 批量声明多个定时器(数组方式)

当需要多个同类定时器(如 10 台电机各自独立延时),用数组避免重复声明:

VAR
    MotorStartTimers : ARRAY[1..10] OF TON;
    MotorStopSignals : ARRAY[1..10] OF BOOL;
    MotorStartCmds   : ARRAY[1..10] OF BOOL;
END_VAR

// 在程序体中循环调用:
FOR motorID := 1 TO 10 DO
    MotorStartTimers[motorID](
        IN := MotorStartCmds[motorID],
        PT := T#3S
    );

    IF MotorStartTimers[motorID].Q THEN
        MotorRunning[motorID] := TRUE;
    END_IF;
END_FOR;

▶ 手动复位定时器(清除 ET 和 Q)

TON/TOF 默认在 INFALSE 时自动清零 ET 并复位 Q,但有时需强制复位(如故障急停后清空所有计时):

// 方法 1:用 RESET 指令(部分平台支持,非 IEC 标准)
// MyTimer1.RESET := TRUE;  // 非通用,慎用

// 方法 2:最通用安全做法——重新调用并传 FALSE 给 IN
MyTimer1(IN := FALSE, PT := MyTimer1.PT);  // 强制清零 ET,Q 变 FALSE

// 方法 3:封装复位逻辑(推荐)
ResetTimer(IN := ResetSignal, Instance := ADR(MyTimer1));

其中 ResetTimer 是自定义功能块,内部执行:

Instance^.IN := FALSE;
Instance^.PT := Instance^.PT;  // 保持原设定

六、与梯形图的等效对照(帮助迁移理解)

假设梯形图中有如下网络:

|----[ I0.0 ]-----------------( TON T37, T#5S )----|
|                                                    |
|----[ T37.Q ]-----------------------------( Q0.0 )--|

对应 ST 的完整等效代码为:

VAR
    T37 : TON;   // 声明实例,名称与 LAD 中一致便于追踪
END_VAR

// 程序体:
T37(IN := "I0.0", PT := T#5S);

"Q0.0" := T37.Q;

注意:"I0.0""Q0.0" 是符号地址(加引号表示字符串地址,实际取决于 PLC 品牌是否启用符号寻址;若用绝对地址,则写 I0.0 不加引号,但需确认变量已映射)。


七、调试建议:如何验证定时器是否正常工作

  1. 在线监控变量:在编程软件中打开变量表,添加 MyTimer1.IN, MyTimer1.Q, MyTimer1.ET,观察其变化;
  2. 插入中间变量辅助判断
    Debug_TON_IN := MyTimer1.IN;
    Debug_TON_Q  := MyTimer1.Q;
    Debug_TON_ET := TIME_TO_MS(MyTimer1.ET);

    将这些变量加入监控,排除逻辑误判;

  3. TP(脉冲定时器)验证边沿:若 TON 不触发,先用 TP 测试 IN 信号是否有干净上升沿;
  4. 检查 PT 是否为零T#0S 会导致 Q 立即置位,易被误判为“未计时”。

八、扩展:自定义定时器封装(可选高级用法)

若项目中频繁使用带使能、复位、超时报警的复合定时器,可封装为自定义 FB:

FUNCTION_BLOCK SafeTON
VAR_INPUT
    EN   : BOOL;     // 使能
    IN   : BOOL;     // 启动信号
    PT   : TIME;     // 定时时间
    RESET: BOOL;     // 复位信号
END_VAR
VAR_OUTPUT
    Q    : BOOL;     // 输出
    ET   : TIME;     // 已计时
    ERROR: BOOL;     // 超时未动作报警(可选)
END_VAR
VAR
    InternalTON : TON;
    LastIN      : BOOL;
END_VAR

IF NOT EN THEN
    Q := FALSE;
    ET := T#0S;
    ERROR := FALSE;
ELSIF RESET THEN
    InternalTON(IN := FALSE, PT := PT);
    Q := FALSE;
    ET := T#0S;
ELSE
    InternalTON(IN := IN, PT := PT);
    Q := InternalTON.Q;
    ET := InternalTON.ET;
    IF IN AND NOT InternalTON.Q AND InternalTON.ET >= PT THEN
        ERROR := TRUE;  // 卡在临界点未触发
    END_IF;
END_IF;

调用方式:

MySafeTimer(EN := TRUE, IN := Start, PT := T#10S, RESET := FaultReset);
MotorReady := MySafeTimer.Q;

该封装提升了复用性与鲁棒性,但初学者应先掌握原生 TON/TOF 实例化。


九、不同 PLC 品牌的细微差异(兼容性提醒)

品牌 TON 类型路径 实例声明语法 注意事项
Siemens S7-1200/1500 TON(系统库默认可用) MyT : TON; 支持 TONR(保持型),PT 可为 LTIME
Beckhoff TwinCAT Tc2_Standard.TON MyT : Tc2_Standard.TON; 需先引用 Tc2_Standard
Codesys TON(标准库) MyT : TON; 可通过 TONTOFTP 统一调用
Rockwell Logix TON(标签数据类型) MyT : TON; 实例名即标签名,IN/Q 为子元素(MyT.IN

无论品牌,实例化原则不变:声明 → 调用 → 读取。


十、总结核心口诀(便于记忆)

  • 声明是前提:没 VAR MyTimer : TON;,一切调用皆非法;
  • 调用带参数MyTimer(IN := ..., PT := ...),缺一不可;
  • 输出靠点取MyTimer.QMyTimer.ET,不可省略实例名;
  • TOF 看下降INFALSE 才启动,别与 TON 逻辑混淆;
  • ET 比较要小心:务必用 TIME 常量或转换函数,勿直比整数。

掌握这一机制,就打通了 ST 编程中功能块调用的底层逻辑,后续对 CTU(增计数器)、MOVE(移动指令)、SEL(选择器)等所有功能块的理解都将一通百通。

评论 (0)

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

扫一扫,手机查看

扫描上方二维码,在手机上查看本文