第三章 中断编程入门:中断程序结构、中断使能与禁止、中断服务程序编写、中断返回
各位同学,今天我们来聊聊中断编程。说实话,我刚入行那会儿,对中断也是一头雾水。总觉得程序跑得好好的,干嘛要搞个中断来打断它?直到我在现场调试一台高速包装机,设备突然卡死,我才意识到——没有中断,PLC就是个聋子瞎子。
中断,说白了就是PLC的「紧急通道」。平时CPU按部就班地扫描主程序,一旦有紧急事件(比如传感器触发、计数器溢出),CPU立刻放下手头工作,跳转去处理这个事件。处理完再回来接着干。嗯,就像你正在写代码,老板突然喊你开会——中断就是这个「老板喊你」的动作。
核心概念:中断不是「打断」,而是「优先级响应」。PLC的扫描周期是固定的,但外部事件不会等你。中断就是让PLC具备「随时响应」的能力。
3.1 中断程序结构:三个关键部分
一个完整的中断程序,我习惯把它分成三块:
- 中断初始化——在OB100或主程序开头配置中断参数
- 中断服务程序——真正处理紧急事件的代码块
- 中断返回——处理完毕,回到断点继续执行
拿西门子S7-1200举例,中断程序的结构长这样:
// 中断初始化(在OB1或启动OB中执行)
"中断使能"(ENABLE := TRUE);
"高速计数器中断连接"(HSC := 1, EVENT := 1, OB_NR := 20);
// 中断服务程序(OB20)
IF "HSC1_状态".方向 = TRUE THEN
"计数结果" := "计数结果" + 1;
ELSE
"计数结果" := "计数结果" - 1;
END_IF;
// 中断返回(自动执行,无需显式指令)
// CPU自动恢复现场,继续执行主程序
我在项目中遇到过一个问题:有人把中断服务程序写得特别长,结果主程序卡死了。为什么?因为中断服务程序执行期间,CPU不扫描主程序。你想想看,如果中断里跑了个循环,主程序就永远等不到下一轮扫描了。
我的经验:中断服务程序尽量短小精悍。我给自己定了个规矩——中断程序不超过10行。超过10行的逻辑,放到主程序里用标志位触发。
3.2 中断使能与禁止:该出手时就出手
中断使能,就是告诉CPU「你可以响应中断了」。中断禁止,就是「现在别理我,忙着呢」。
为什么要禁止中断?我举个例子。你在处理一个关键数据块,写到一半突然来了个中断,把数据改了——这就乱套了。所以,在操作共享数据时,我习惯先关中断,操作完再开中断。
不同PLC的指令不一样,但逻辑相同:
| PLC品牌 | 使能指令 | 禁止指令 | 说明 |
|---|---|---|---|
| 西门子S7-1200 | ENABLE_INTERRUPT | DISABLE_INTERRUPT | 可针对单个中断号操作 |
| 三菱FX系列 | EI | DI | 全局使能/禁止 |
| 欧姆龙CJ系列 | MSKS | MSKR | 需要指定中断任务号 |
我曾经犯过一个低级错误:在中断服务程序里调用了DISABLE_INTERRUPT,结果中断只触发了一次,后面再也不来了。排查了半天才发现——中断服务程序里把自己给禁了。嗯,这就像你开会时把门锁了,外面的人进不来,你也出不去。
避坑指南:我曾经在中断服务程序里写了个循环等待,结果CPU直接报「看门狗超时」。记住:中断程序里不要用WAIT、延时、循环等待这类指令。中断讲究的是「快进快出」。
3.3 中断服务程序编写:实战要点
写中断服务程序,我总结了三个字:短、快、稳。
- 短——代码行数少,逻辑简单
- 快——执行时间短,不影响主程序扫描
- 稳——不依赖外部条件,不调用复杂功能块
来看一个实际案例。高速计数器每计数1000个脉冲触发一次中断,我们需要记录当前计数值并复位计数器:
// 中断服务程序 OB30
// 触发条件:HSC1计数值达到1000
// 第一步:读取当前计数值(快照)
#当前值 := "HSC1".COUNT;
// 第二步:累加总计数
"总计数" := "总计数" + #当前值;
// 第三步:复位计数器(准备下一轮)
"HSC1".复位 := TRUE;
// 注意:复位后要延时一个扫描周期再清除复位信号
// 但中断里不能延时,所以用标志位交给主程序处理
"复位标志" := TRUE;
// 第四步:更新频率计算
"频率值" := 1000 / (#当前时间 - #上次时间);
#上次时间 := #当前时间;
// 中断返回(自动)
看到没?中断里只做「快照」和「简单计算」。真正的复位信号清除、数据归档,我放到主程序里用标志位触发。这样既保证了中断的响应速度,又不会丢失数据。
小技巧:我习惯在中断服务程序的第一行,把关键数据复制到临时变量里。为什么?因为中断执行期间,外部信号可能还在变化。先「拍照」再处理,保证数据一致性。
3.4 中断返回:不是结束,是继续
中断返回,很多人以为就是程序结束。其实不对。中断返回的真正含义是:恢复现场,继续执行。
CPU在进入中断前,会自动保存当前的工作状态(累加器、状态字、指针等)。中断返回时,自动恢复这些状态。你不需要写任何返回指令——PLC的固件帮你做了。
但有一点要注意:中断返回后,主程序从断点处继续执行。这意味着,如果你在中断里修改了某个全局变量,主程序会立刻感知到。这既是好事也是坏事——好处是数据实时更新,坏处是可能引发逻辑冲突。
我遇到过最典型的问题:中断里修改了计数器的值,主程序刚好在判断这个值做逻辑切换。结果主程序刚判断完「值小于100」,中断就把值改成了101。嗯,逻辑就乱套了。
避坑指南:我曾经在中断里修改了某个DB块的数值,主程序同时也在修改同一个数值。结果两个程序「打架」,数据忽大忽小。后来我加了个互斥标志——中断里修改数据前,先检查主程序是否正在使用该数据。如果正在使用,就等下一个中断周期再改。
3.5 知识体系总览
说了这么多,咱们用一张图把中断编程的核心逻辑串起来:
这张图把中断编程的四个核心环节串起来了:主程序循环 → 中断触发 → 中断服务程序 → 中断返回。再加上使能/禁止控制、中断类型、编写要点和避坑指南。你把它打印出来贴在工位上,写中断程序时瞄一眼,基本不会出错。
好了,中断编程入门就讲到这里。记住我说的:中断不是洪水猛兽,它是PLC的「特种部队」。用好了,你的设备响应速度能提升一个量级。用不好,嗯...我当年踩过的坑,希望你别再踩一遍。
课后练习:打开你的PLC编程软件,创建一个高速计数器中断。设置计数值达到500时触发中断,在中断服务程序里翻转一个输出点。试试看,能不能一次成功?
公众号:蓝海资料掘金营,微信deep3321