ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

PLC编程进阶:SCL定时器从入门到实战,掌握工业自动化核心时序控制

2026/8/7 13:28:23 拓冰建站 浏览量
PLC编程进阶:SCL定时器从入门到实战,掌握工业自动化核心时序控制 1. 从梯形图到SCL为什么定时器是PLC编程的“分水岭”如果你是从梯形图LAD或指令表STL转战SCLStructured Control Language结构化控制语言的工程师那么第一个让你感到既熟悉又陌生的功能块十有八九是定时器。在梯形图里一个TON接通延时定时器就是一个方框拖进来填上时间连上使能和输出直观得像搭积木。但到了SCL里你可能会有点懵没有那个熟悉的图形了我该怎么“调用”一个定时器难道要自己用IF语句去写一个计时循环这正是SCL学习的第一个关键节点。很多人把SCL简单地理解为“高级一点的梯形图”这是一个巨大的误解。SCL的本质是一种高级编程语言基于PASCAL/ST它带来的不仅是语法的变化更是编程思维的跃迁——从面向“触点线圈”的电路逻辑转向面向“数据与算法”的软件工程。而定时器恰恰是检验这种思维转变是否成功的绝佳试金石。它不再是一个“黑盒”功能块而是一个有着明确输入、输出参数和内部状态的数据对象。掌握SCL中的定时器你才算真正摸到了结构化编程的门把手。在工业自动化项目尤其是像电梯控制、包装流水线、过程控制等复杂逻辑场景中定时器的应用无处不在。它不只是简单的延时接通或断开更是实现顺序控制、周期扫描、超时保护、脉冲生成等核心功能的基础。用SCL来驾驭定时器意味着你能更灵活、更高效、更可靠地构建这些逻辑。比如在最新的博途TIA Portal环境中用SCL编写一个五层电梯的调度程序其定时逻辑如开关门延时、楼层间运行时间、故障保护延时的清晰度和可维护性会远胜于用梯形图堆砌出来的庞然大物。2. IEC定时器家族TON, TOF, TP 的SCL化生存指南在IEC 61131-3标准中定义了三种最基础的定时器类型它们在SCL中都有对应的实现方式。理解它们的“性格”是正确使用的前提。2.1 TON接通延时最常用的“守时者”TON是当之无愧的明星。它的行为很简单当使能端IN为TRUE时开始计时计时达到预设值PT后输出Q变为TRUE。计时过程中或IN变为FALSE时输出Q为FALSE且当前时间ET被复位。在SCL中我们不再拖放功能块而是“实例化”一个定时器数据块并调用它。以西门子博途TIA Portal为例最标准的做法是使用系统提供的TON、TOF等IEC定时器。// 在博途SCL中声明和使用TON FUNCTION_BLOCK MyTimingLogic VAR // 1. 声明一个TON定时器实例 myDelayTimer: TON; // 控制变量 startButton: BOOL; processDone: BOOL; presetTime: TIME : T#5S; // 预设5秒 END_VAR // 2. 调用定时器 myDelayTimer( IN : startButton, // 使能条件 PT : presetTime // 预设时间 ); // 3. 使用定时器的输出 processDone : myDelayTimer.Q; // 计时到输出为TRUE核心要点与避坑指南定时器是背景数据块myDelayTimer: TON;这行代码并不是声明一个“功能”而是实例化了一个定时器类型的背景数据块。它有自己的内存空间存储着ET当前时间、Q等状态。这意味着同一个定时器实例不能在程序的多个地方同时调用否则状态会混乱。IN信号的“干净”至关重要TON对IN信号的上升沿敏感。如果startButton是一个由按钮触发的、可能持续多个扫描周期的信号直接连接可能导致计时意外重启。一个常见的技巧是配合边沿检测// 先检测上升沿生成一个单扫描周期的脉冲 IF startButton AND NOT startButton_Memory THEN triggerPulse : TRUE; ELSE triggerPulse : FALSE; END_IF; startButton_Memory : startButton; // 用这个脉冲作为TON的IN myDelayTimer(IN : triggerPulse, PT : T#5S);PT参数的类型是TIME预设值必须赋值TIME类型如T#5S5秒、T#2M30S2分30秒。直接写数字5是行不通的。2.2 TOF断开延时用于“善后”的定时器TOF的行为与TON相反。当IN为TRUE时输出Q立即为TRUE。当IN从TRUE变为FALSE时TOF开始计时计时达到PT后输出Q才变为FALSE。它常用于设备停止后的吹扫、冷却等需要维持一段时间的场景。VAR coolingFanTimer: TOF; fanRunCmd: BOOL; fanRunning: BOOL; coolingTime: TIME : T#30S; END_VAR coolingFanTimer( IN : fanRunCmd, PT : coolingTime ); fanRunning : coolingFanTimer.Q; // 主设备停止后风扇还会再运行30秒实操心得TOF的一个常见误解是“计时过程中IN又变TRUE会怎样”答案是计时会立即停止输出Q会立刻重新变为TRUE。这符合其“断开延时”的定义——它只关心从TRUE到FALSE的那个下降沿。2.3 TP脉冲定时器生成“标准脉冲”TP用于生成一个固定宽度的脉冲。当IN出现上升沿时输出Q立即变为TRUE并开始计时无论IN是否保持TRUEQ都会在PT时间后自动变为FALSE。如果在Q为TRUE期间IN又出现新的上升沿不会影响当前正在进行的脉冲。VAR beepPulseTimer: TP; alarmActive: BOOL; beepSignal: BOOL; pulseWidth: TIME : T#500MS; END_VAR beepPulseTimer( IN : alarmActive, PT : pulseWidth ); beepSignal : beepPulseTimer.Q; // 每次alarmActive变TRUEbeep响500ms对比与选型千万不要用TON来模拟TP有些人会用TON(IN:signal, PT:time)然后用signal AND NOT TON.Q来产生脉冲这在信号signal持续时间小于PT时是无效的。TP是专为生成精确脉冲而设计的。3. 超越标准库用SCL原生逻辑构建自定义定时器虽然直接调用TON/TOF/TP是最规范的做法但在某些特定场景下或者为了加深理解我们完全可以用SCL的原生语句如IF、定时器指令、系统时钟来构建定时逻辑。这能让你获得极大的灵活性。3.1 基于系统时钟和比较的“软件定时器”这是最基础、最直观的方法适用于所有支持SCL的PLC平台如西门子、倍福、Codesys等。FUNCTION_BLOCK CustomTimer VAR_INPUT enable: BOOL; // 使能 presetTime: TIME; // 预设时间 reset: BOOL; // 复位 END_VAR VAR_OUTPUT q: BOOL; // 输出 elapsedTime: TIME; // 已过时间 END_VAR VAR startTime: TIME; // 开始计时的时刻 isTiming: BOOL : FALSE; // 计时状态标志 END_VAR IF reset THEN // 复位逻辑 isTiming : FALSE; q : FALSE; elapsedTime : T#0S; startTime : T#0S; ELSIF enable AND NOT isTiming THEN // 首次使能记录开始时间 isTiming : TRUE; startTime : TIME(); // 获取当前系统时间 q : FALSE; ELSIF isTiming THEN // 计时中 elapsedTime : TIME() - startTime; // 计算已过时间 IF elapsedTime presetTime THEN // 时间到 q : TRUE; // 可以选择保持状态或自动停止计时 // isTiming : FALSE; // 若只需单次触发则取消注释此行 ELSE q : FALSE; END_IF; ELSIF NOT enable THEN // 使能断开复位计时状态模拟TON行为 isTiming : FALSE; q : FALSE; elapsedTime : T#0S; END_IF;为什么这样做优势与陷阱优势1完全可控你可以自定义计时到后的行为是保持输出还是自动复位是否循环计时这是标准TON做不到的。优势2状态透明所有中间变量startTime,isTiming你都能访问和干预便于调试和实现复杂逻辑如中途暂停、修改预设值。陷阱1TIME()函数的分辨率TIME()通常获取的是PLC的系统时间其最小分辨率可能是1毫秒或一个扫描周期。对于极高精度的定时如微秒级这种方法不适用需要使用硬件定时器中断。陷阱2扫描周期的影响这种定时器受PLC扫描周期影响。如果预设时间很短接近或小于扫描周期定时可能不准。对于精确的短时间定时应使用定时器中断或专用的高速定时器指令。3.2 实现一个可暂停、可重置的增强型定时器标准IEC定时器没有“暂停”功能。用SCL自定义我们可以轻松实现。FUNCTION_BLOCK PausableTimer VAR_INPUT start: BOOL; // 启动 pause: BOOL; // 暂停 reset: BOOL; // 复位 preset: TIME; END_VAR VAR_OUTPUT done: BOOL; currentET: TIME; END_VAR VAR internalET: TIME; // 累计的已过时间 isRunning: BOOL; lastScanTime: TIME; END_VAR IF reset THEN internalET : T#0S; isRunning : FALSE; done : FALSE; currentET : T#0S; RETURN; // 复位优先直接返回 END_IF; // 启动逻辑边沿检测 IF start AND NOT start_Memory THEN isRunning : TRUE; lastScanTime : TIME(); // 记录本次扫描开始时间 END_IF; start_Memory : start; IF isRunning AND NOT pause THEN // 正常运行累计时间 上次累计 (当前时间 - 上次记录的时间) internalET : internalET (TIME() - lastScanTime); lastScanTime : TIME(); // 更新记录时间 ELSIF pause THEN // 暂停不累计时间但保持isRunning状态和lastScanTime不变 // 什么也不做等待pause解除 END_IF; // 检查是否超时 currentET : internalET; IF internalET preset THEN done : TRUE; isRunning : FALSE; // 计时完成停止运行 ELSE done : FALSE; END_IF; // 如果计时未完成但使能断开非暂停则复位模拟TON IF NOT start AND isRunning AND NOT pause THEN isRunning : FALSE; internalET : T#0S; END_IF;这个自定义定时器就实现了工业现场常见的需求一个长过程的加热可以中途暂停恢复后继续累计时间。它的核心思想是将“已过时间”作为一个变量累加而不是每次都从系统时间开始计算。4. 项目实战五层简易电梯控制程序中的定时器应用拆解让我们结合“电梯控制程序”这个热词看看SCL定时器如何在实际项目中大显身手。假设我们要用SCL在博途中实现一个五层电梯的核心定时逻辑。4.1 场景定义与定时需求分析一个简易电梯控制系统至少包含以下几个需要定时的环节开关门延时电梯到达目标楼层后开门并保持一段时间然后自动关门。楼层间运行时间用于估算电梯位置或在无位置传感器时做粗略定位。按钮响应消抖消除乘客呼梯按钮或轿厢内选层按钮的机械抖动。故障安全保护例如门在关闭过程中受到阻碍定时器超时后应重新开门或报警。4.2 SCL代码实现关键环节我们重点实现开关门控制和按钮消抖。FUNCTION_BLOCK ElevatorDoorControl VAR_INPUT atFloor: BOOL; // 到达楼层信号 openButton: BOOL; // 开门按钮 closeButton: BOOL; // 关门按钮 obstacleDetected: BOOL; // 光幕或安全触板信号 END_VAR VAR_OUTPUT doorOpenCmd: BOOL; // 开门命令 doorCloseCmd: BOOL; // 关门命令 doorStatus: INT; // 0:关, 1:开, 2:运动中 alarm: BOOL; // 门故障报警 END_VAR VAR // 定时器实例 tDoorOpenHold: TON; // 开门保持定时 tDoorCloseAction: TON; // 关门动作定时从收到命令到门应关好的时间 tObstacleTimeout: TON; // 障碍物超时定时 // 内部状态 doorState: INT : 0; openRequest: BOOL; closeRequest: BOOL; END_VAR // 1. 开门逻辑 openRequest : atFloor OR openButton; // 到达楼层或按下开门钮都请求开门 IF openRequest AND doorState 0 THEN // 如果门关着且有开门请求 doorState : 1; // 状态开门中 doorOpenCmd : TRUE; doorCloseCmd : FALSE; tDoorCloseAction(IN : FALSE, PT : T#0S); // 复位关门定时器 END_IF; // 2. 门已完全打开后的保持逻辑 IF doorState 1 AND 门已全开传感器 THEN doorState : 2; // 状态门已开 doorOpenCmd : FALSE; // 停止开门电机 // 启动开门保持定时器例如保持5秒 tDoorOpenHold(IN : TRUE, PT : T#5S); END_IF; // 3. 保持时间到或按下关门钮启动关门 IF (tDoorOpenHold.Q OR closeButton) AND doorState 2 AND NOT obstacleDetected THEN doorState : 3; // 状态关门中 doorCloseCmd : TRUE; tDoorOpenHold(IN : FALSE, PT : T#0S); // 复位开门保持定时器 // 启动关门动作定时器假设正常关门需3秒 tDoorCloseAction(IN : TRUE, PT : T#3S); END_IF; // 4. 关门过程中的障碍物检测与处理 IF obstacleDetected AND doorState 3 THEN doorCloseCmd : FALSE; // 立即停止关门 doorOpenCmd : TRUE; // 反转开门 // 启动障碍物超时定时器例如2秒内障碍应移除 tObstacleTimeout(IN : TRUE, PT : T#2S); END_IF; // 5. 障碍物超时处理 IF tObstacleTimeout.Q THEN alarm : TRUE; // 超时未移除触发报警 doorOpenCmd : FALSE; // 电梯应停止运行等待维护 END_IF; // 6. 关门成功检测 IF tDoorCloseAction.Q AND doorState 3 AND NOT obstacleDetected THEN IF 门已全关传感器 THEN doorState : 0; // 状态门已关 doorCloseCmd : FALSE; ELSE // 定时器到了但门没关好可能机械故障 alarm : TRUE; END_IF; END_IF; // 输出状态 doorStatus : doorState;按钮消抖的SCL实现FUNCTION_BLOCK Debounce VAR_INPUT rawInput: BOOL; // 原始按钮信号 debounceTime: TIME : T#100MS; // 消抖时间通常50-200ms END_VAR VAR_OUTPUT cleanOutput: BOOL; // 消抖后的干净信号 END_VAR VAR tDebounce: TP; // 使用脉冲定时器 lastState: BOOL : FALSE; END_VAR // 当原始信号变化时触发一个固定宽度的定时器 tDebounce(IN : rawInput lastState, PT : debounceTime); lastState : rawInput; // 只有在定时器脉冲结束后信号状态仍保持稳定才认为有效 cleanOutput : rawInput AND tDebounce.Q;4.3 调试技巧与常见问题定时器“不计时”或“瞬间完成”首先检查PT参数的单位是否正确是T#2S而不是整数2其次检查IN条件是否在整个扫描周期内保持为TRUE可能是边沿信号一闪而过。在博途中可以在监控表中添加定时器的ET当前时间值观察其是否递增。多个定时器协调在电梯这类状态机中定时器常常是状态转换的条件。务必理清状态图确保一个定时器只在正确的状态下被使能IN为TRUE在状态离开时被复位IN为FALSE。混乱的使能会导致定时器行为诡异。扫描周期与定时精度对于T#100MS这样的短时间定时PLC的扫描周期可能几毫秒到几十毫秒会影响精度。对于高精度需求需要考虑使用硬件中断或PLC系统提供的更高精度定时功能。在SCL中TIME()函数的最小分辨率也需要注意。5. 进阶思考SCL定时器与嵌入式定时器的异同从网络热词可以看到大家不仅关心PLC的SCL也关注stm32定时器、51定时器、freertos软件定时器等。理解它们的异同能帮你建立更统一的定时编程思维。特性PLC SCL中的IEC定时器嵌入式MCU硬件定时器如STM32 TIMRTOS软件定时器如FreeRTOS本质软件功能块基于系统时钟和扫描周期硬件外设独立于CPU运行精度高操作系统服务基于系统Tick精度受扫描周期影响通常毫秒级可达纳秒/微秒级由晶振和分频决定受系统Tick周期影响通常毫秒级中断无直接中断概念状态在扫描周期末更新可配置中断计时到自动触发响应极快可配置回调函数在定时器任务中执行阻塞非阻塞调用后立即返回后台计时非阻塞中断模式或阻塞轮询模式非阻塞回调函数在独立任务执行资源消耗数据块内存和CPU扫描时间消耗专用的硬件定时器资源消耗内存和CPU时间创建任务/消息应用场景逻辑控制、顺序延时、过程监控精确PWM生成、输入捕获、超时检测任务周期调度、软件看门狗、延迟操作核心思维迁移在STM32中用HAL库配置一个定时器中断和你用SCL写一个TON功能块抽象逻辑是相通的都是“设置一个目标值 - 启动计数 - 达到目标后触发动作”。只是前者你在配置寄存器、写中断服务函数后者你在调用封装好的功能块。理解了这个共性再去看rk3588硬件定时器驱动开发这类底层开发你就会发现它们无非是在更底层操作系统或寄存器层面实现我们熟悉的“定时”抽象。6. 性能、风格与最佳实践写出工业级的SCL定时器代码当项目中的定时器越来越多代码的可读性、可维护性和性能就变得至关重要。1. 结构化与封装不要把所有定时器的调用散落在主程序各处。像电梯项目那样为“门控制”、“运行控制”、“报警管理”分别创建独立的FUNCTION_BLOCK每个FB内部管理自己所需的定时器。这样结构清晰且方便复用。2. 时间基准统一在一个项目中尽量统一时间单位。例如全部使用TIME类型预设值用T#字面量。避免一些地方用秒一些地方用毫秒导致混乱。可以定义全局常量VAR_GLOBAL CONSTANT ONE_SECOND: TIME : T#1S; DOOR_HOLD_TIME: TIME : T#5S; DEBOUNCE_TIME: TIME : T#100MS; END_VAR3. 避免在循环中创建定时器实例绝对不要在FOR循环或频繁执行的函数内部实例化TON等定时器。这会导致大量临时实例被创建和销毁浪费资源且行为不可预测。定时器实例应在FB或全局数据块的静态变量区声明。4. 使用TON_TIME等扩展功能西门子等厂商的库中可能提供了更强大的定时器如TON_TIME可以输出TIME类型的剩余时间方便做进度显示。多熟悉所用平台的高级库。5. 仿真与测试SCL代码尤其是包含复杂定时逻辑的必须进行充分仿真。利用TIA Portal的PLCSIM Advanced等工具模拟各种信号时序和边界条件如使能信号在计时到前瞬间断开观察定时器行为是否符合预期。从梯形图的“图形化调用”到SCL的“数据化驱动”定时器的使用方式是衡量一个PLC程序员是否进阶的关键标志。它强迫你去思考数据流、状态机和程序结构。当你能够熟练地用SCL组织起数十个定时器让它们在一个复杂的生产线控制程序中协同工作时你就会真正体会到结构化编程带来的力量逻辑更清晰调试更简单维护更容易。下次当你再面对一个需要精确定时和复杂序列控制的项目时不妨先从设计一套清晰的定时器管理方案开始用SCL把它优雅地实现出来。