PLC 编程中定时器和计数器是最常用的功能模块。本教程通过实际案例讲解各种使用模式。
标准定时器模式
通电延时 (TON)
FUNCTION_BLOCK TON_Example
VAR_INPUT
IN : BOOL; // 启动输入
PT : TIME; // 预设时间
END_VAR
VAR_OUTPUT
Q : BOOL; // 输出
ET : TIME; // 已过时间
END_VAR
VAR
running : BOOL := FALSE;
start_time : TIME;
END_VAR
IF IN AND NOT running THEN
// 检测到上升沿,启动定时
start_time := CURRENT_TIME;
running := TRUE;
Q := FALSE;
END_IF
IF NOT IN THEN
// 输入信号断开,复位
running := FALSE;
Q := FALSE;
ET := T#0s;
END_IF
IF running THEN
ET := CURRENT_TIME - start_time;
IF ET >= PT THEN
Q := TRUE;
running := FALSE; // 定时完成
END_IF
END_IF
END_FUNCTION_BLOCK
应用场景:电机启动延时、设备预热计时、信号去抖。
闪烁定时器 (Blink)
FUNCTION_BLOCK BlinkTimer
VAR_INPUT
enable : BOOL;
t_on : TIME := T#500ms; // 导通时间
t_off : TIME := T#500ms; // 断开时间
END_VAR
VAR_OUTPUT
output : BOOL;
END_VAR
VAR
state : BOOL := FALSE;
timer : TIME;
start_time : TIME;
running : BOOL := FALSE;
END_VAR
IF enable AND NOT running THEN
running := TRUE;
state := TRUE;
start_time := CURRENT_TIME;
END_IF
IF NOT enable THEN
running := FALSE;
state := FALSE;
output := FALSE;
RETURN;
END_IF
IF running THEN
timer := CURRENT_TIME - start_time;
IF state AND timer >= t_on THEN
state := FALSE;
start_time := CURRENT_TIME;
ELSIF NOT state AND timer >= t_off THEN
state := TRUE;
start_time := CURRENT_TIME;
END_IF
output := state;
END_IF
END_FUNCTION_BLOCK
应用场景:指示灯控制、报警闪烁、PWM 信号生成。
计数器模式
通用加减计数器
FUNCTION_BLOCK UniversalCounter
VAR_INPUT
count_up : BOOL;
count_down : BOOL;
reset : BOOL;
preset : INT := 100; // 预设值
auto_reset : BOOL := FALSE; // 到达预设值自动复位
END_VAR
VAR_OUTPUT
current_value : INT := 0;
done : BOOL;
END_VAR
IF reset THEN
current_value := 0;
done := FALSE;
RETURN;
END_IF
// 上升沿计数
IF count_up AND NOT count_up_prev THEN
current_value := current_value + 1;
END_IF
IF count_down AND NOT count_down_prev THEN
IF current_value > 0 THEN
current_value := current_value - 1;
END_IF
END_IF
// 到达预设值
IF current_value >= preset THEN
done := TRUE;
IF auto_reset THEN
current_value := 0;
done := FALSE;
END_IF
END_IF
// 保存前一个状态用于上升沿检测
count_up_prev := count_up;
count_down_prev := count_down;
END_FUNCTION_BLOCK
应用场景:工件计数、流量累计、转数检测。
频率测量器
FUNCTION_BLOCK FreqMeter
VAR_INPUT
pulse : BOOL; // 被测脉冲信号
gate_time : TIME := T#1s; // 闸门时间
END_VAR
VAR_OUTPUT
frequency : REAL; // 测量频率 (Hz)
valid : BOOL;
END_VAR
VAR
count : INT := 0;
prev_pulse : BOOL := FALSE;
gate_timer : TIME;
gate_start : TIME;
measuring : BOOL := FALSE;
total_count : INT := 0;
END_VAR
// 启动测量
IF NOT measuring THEN
gate_start := CURRENT_TIME;
measuring := TRUE;
count := 0;
valid := FALSE;
END_IF
// 脉冲计数
IF pulse AND NOT prev_pulse THEN
count := count + 1;
END_IF
prev_pulse := pulse;
// 闸门时间到,计算频率
gate_timer := CURRENT_TIME - gate_start;
IF gate_timer >= gate_time THEN
total_count := count;
// 频率 = 脉冲数 / 闸门时间(秒)
frequency := INT_TO_REAL(total_count);
valid := TRUE;
measuring := FALSE;
END_IF
END_FUNCTION_BLOCK
应用场景:转速测量、流量计读数、脉冲频率检测。
综合应用:电机控制系统
PROGRAM MotorControl
VAR
// 输入
start_btn AT %I* : BOOL;
stop_btn AT %I* : BOOL;
speed_sensor AT %I* : BOOL; // 转速脉冲
// 输出
motor_contact AT %Q* : BOOL;
alarm_led AT %Q* : BOOL;
speed_display AT %QW* : INT;
// 功能块实例
start_delay : TON_Example;
blinker : BlinkTimer;
speed_meter : FreqMeter;
run_hours : UniversalCounter;
// 状态
motor_running : BOOL := FALSE;
fault : BOOL := FALSE;
END_VAR
// 启动延时 2 秒
start_delay(IN := start_btn, PT := T#2s);
// 停止按钮或故障时停机
IF stop_btn OR fault THEN
motor_running := FALSE;
END_IF
// 延时完成后启动
IF start_delay.Q AND NOT motor_running THEN
motor_running := TRUE;
END_IF
// 控制接触器
motor_contact := motor_running;
// 转速监测 (闸门时间 1 秒)
speed_meter(pulse := speed_sensor, gate_time := T#1s);
IF speed_meter.valid THEN
speed_display := REAL_TO_INT(speed_meter.frequency);
END_IF
// 超速报警 (假设 > 1500 RPM)
IF speed_display > 1500 THEN
fault := TRUE;
END_IF
// 故障时报警灯闪烁
blinker(enable := fault, t_on := T#200ms, t_off := T#200ms);
alarm_led := blinker.output;
最佳实践
- 定时器分辨率:根据精度需求选择计时方式,毫秒级用 TIME 类型,微秒级用硬件定时器
- 计数器溢出:INT 上限 32767,长时间运行建议使用 DINT
- 脉冲捕获:确保采样频率至少是被测信号的 2 倍(奈奎斯特采样定理)
- 避免看门狗超时:不要在定时器中执行耗时操作(如大量 IO 读写)
- 使用功能块封装:将定时器/计数器逻辑封装为 FUNCTION_BLOCK,提高代码复用性