S7-1200外部中断实战:OB40创建与DETACH分离策略详解
1. 从一次产线改造聊起为什么外部中断值得单独拿出来说去年帮一家做包装机械的客户做产线提速改造碰到一个很典型的问题一台S7-1200 1214C DC/DC/DC主程序里跑着PID温度闭环、Modbus RTU轮询三台变频器、再加上几路高速计数扫描周期稳定在8~12ms。设备上有个色标传感器用来抓包装膜上的定位标记信号宽度只有1.5ms左右。原来的做法是在主循环里用上升沿检测结果高速运行时频繁丢标废品率一度飙到7%。后来把色标信号切到外部中断OB40里处理丢标问题直接消失扫描周期也不再被这个信号牵着走。这个案例基本能说明外部中断在S7-1200里的定位它不是为了替代主程序而是为了把那些等不起的事件从主循环里剥离出来让CPU用硬件级别的时间精度去响应。很多刚接触S7-1200的朋友梯形图写得很熟但一提到OB40、DETACH这类东西就发怵觉得是高级功能。其实外部中断的创建和分离逻辑非常直白难的是搞清楚什么时候该用、什么时候该分离、分离之后事件去哪了。这篇内容我打算按实际项目的思路来写先讲清楚外部中断在S7-1200里到底是怎么一回事再把创建过程一步步拆开重点放在DETACH这个容易被忽略但极其关键的动作上最后用几个真实场景说明创建和分离配合起来能解决什么问题。适合已经会基本梯形图、想往非标项目实战方向走的读者也适合那些被高速信号、急停响应、精确定位折腾过的朋友。2. 外部中断到底解决什么问题先搞懂硬件事件和扫描周期的关系2.1 扫描周期是排队制外部中断是插队制S7-1200的OB1主程序是循环执行的CPU一个周期一个周期地跑读输入、执行程序、写输出、处理通信、系统自检然后再来一遍。这个周期是固定的排队逻辑你程序里写了多少行、调用了多少FB、挂了多少个Modbus从站都会实打实地累加到扫描时间上。我实测过一个1214C挂三台变频器做轮询光通信处理就能吃掉3~5ms。问题就出在这里如果某个输入信号只持续1~2ms而你的扫描周期是10ms那这个信号很可能在两次扫描之间来了又走了CPU根本没看见。这就像你去银行办业务取号排队窗口每10分钟叫一次号你朋友在这10分钟里进来又出去了你压根不知道他来过。外部中断OB40干的事就是给特定硬件事件开一个插队通道。当配置为中断输入的通道检测到指定边沿上升沿、下降沿或双边沿时CPU会暂停当前正在执行的OB1转去执行OB40里的程序执行完再回到OB1被打断的地方继续。这个过程由硬件触发响应时间在微秒级别跟扫描周期基本脱钩。2.2 哪些信号值得走外部中断不是所有输入都适合挂外部中断。我一般按下面这个标准来判断信号类型典型脉宽是否建议用外部中断原因色标/标记传感器0.5~3ms强烈建议脉宽小于扫描周期主程序必丢高速计数/编码器Z相微秒级必须用或走HSC主程序完全跟不上急停/安全门不定建议用要求最快响应不能等扫描普通按钮/限位几十ms以上不必用主程序上升沿足够温度/压力模拟量秒级变化不必用变化慢周期采样足够这里有个经验判断标准不是信号重不重要而是信号持续时间是否可能短于扫描周期。急停按钮虽然人按下去会保持但如果是安全继电器输出的窄脉冲或者需要记录按下瞬间的时间戳那也值得走中断。2.3 OB40和硬件中断组织块的关系S7-1200里跟外部中断相关的事件组织块主要是OB40。CPU支持多个硬件中断事件每个事件可以绑定到一个OB40实例实际上是通过事件ID区分。在博途里你不需要手动创建多个OB40而是在硬件组态里给每个中断输入分配事件然后在程序里添加OB40用Event_Class或者读取启动信息来区分是哪个通道触发的。这里要澄清一个常见误解OB40不是一个通道一个块而是一类事件一个块。多个中断输入可以共用一个OB40在OB40内部通过读取OB40_EV_CLASS、OB40_EV_ID或者用RD_SYS_INT_INFO之类的指令来判断来源。当然如果你希望每个通道逻辑独立也可以给不同事件分配不同的OB编号S7-1200支持OB40~OB47这一段但实际项目里共用一个再分支更常见。3. 创建外部中断的完整流程从硬件组态到OB40落地3.1 硬件组态里先把通道变成中断输入外部中断的第一步不在程序里而在硬件组态。以1214C DC/DC/DC为例它的本体集成输入点里I0.0~I0.5这几路支持硬件中断功能具体哪些点支持要看CPU型号和固件版本G2系列的支持范围更宽。操作路径是在博途里打开设备视图点开CPU的属性。找到硬件中断或者数字量输入下的输入通道配置。选中你要用的通道比如I0.0把硬件中断勾上。选择触发边沿上升沿、下降沿或双边沿。系统会自动分配一个硬件标识符Hardware Identifier这个ID后面在OB40里判断事件来源时要用到。注意不是所有输入点都支持硬件中断。1214C本体上通常只有前6个点I0.0~I0.5支持信号板上的点要看具体型号。如果你把中断配到了不支持的点上博途会直接报错或者该选项灰掉。我见过有人折腾半天最后发现是选错了通道。组态完成后编译一下博途会在系统常数里生成对应的硬件ID比如Local~DI_0.0之类的符号记下来后面写程序要用。3.2 添加OB40并理解它的启动信息在程序块里右键添加新块选择组织块找到OB40硬件中断。添加后OB40会自动带上启动参数最重要的是OB40_EV_CLASS和OB40_EV_ID这两个。OB40_EV_CLASS事件类硬件中断一般是16#11。OB40_EV_ID事件ID对应你在硬件组态里分配的那个硬件标识符。在OB40里你可以用这两个值来判断是哪个通道触发的。比如IF #OB40_EV_ID 261 THEN // 对应I0.0的中断事件 色标计数 : 色标计数 1; ELSIF #OB40_EV_ID 262 THEN // 对应I0.1的中断事件 急停标志 : TRUE; END_IF;这里的261、262是举例实际值以你项目里系统常数显示的为准。千万不要硬编码猜ID一定要从系统常数里复制不同CPU、不同固件版本ID分配规则可能不一样。3.3 中断程序里能做什么、不能做什么OB40里的程序要尽量短、快、确定。我一般遵循几个原则只做标记和计数不做复杂运算。比如置位一个标志、累加一个计数器、记录一个时间戳然后让OB1去处理后续逻辑。不要在里面调用通信指令。Modbus、TCP这些在中断里跑会严重拖慢响应甚至导致通信异常。不要用延时或等待。中断程序里没有等一会儿这个概念任何阻塞操作都会让CPU卡住。访问的变量尽量是全局DB或M区避免复杂的间接寻址。举个实际写法色标中断来了OB40里只做一件事——把当前的高速计数器值读出来存到一个DB里同时置位有新标标志。OB1检测到这个标志后再去做位置计算、补偿、报警判断。这样中断执行时间能控制在几十微秒不影响其他中断的响应。3.4 一个完整的创建示例假设我们要用I0.0做色标中断I0.1做急停中断步骤如下硬件组态I0.0设为上升沿中断I0.1设为下降沿中断记下各自的硬件ID。添加OB40在启动参数里确认OB40_EV_ID可用。在OB40里写分支逻辑CASE #OB40_EV_ID OF 261: // I0.0 色标 DB_Data.MarkCount : DB_Data.MarkCount 1; DB_Data.NewMark : TRUE; 262: // I0.1 急停 DB_Data.EStopFlag : TRUE; DB_Data.EStopTime : RD_SYS_T(); END_CASE;OB1里处理NewMark和EStopFlag处理完清零。下载测试用信号发生器给一个1ms脉冲观察计数是否准确。这套流程跑通之后你会发现外部中断的创建本身并不复杂真正需要功力的是下一步——什么时候该把它分离掉。4. DETACH到底在干什么中断分离的时机和逻辑4.1 中断不分离会出什么问题先说一个我踩过的坑。有个项目用I0.0做中断输入设备正常运行时没问题但到了调试阶段操作工频繁手动触发那个传感器结果OB40被疯狂调用OB1几乎没机会执行触摸屏直接卡死通信也断了。原因就是中断事件一直在触发CPU不停地在OB1和OB40之间切换主程序被饿死了。这就是DETACH存在的意义。DETACH指令的作用是把某个硬件中断事件从OB40上摘下来让这个通道的边沿触发暂时不再产生中断。注意它摘的是事件和OB的绑定关系不是禁用输入点本身。输入点该读还是能读只是不再触发中断了。对应的还有ATTACH指令用来重新把事件绑回去。这两个指令配合使用就能实现需要时开中断不需要时关中断的动态管理。4.2 DETACH的指令格式和参数在博途里DETACH和ATTACH都在扩展指令→中断下面。以S7-1200为例DETACH(OB_NR : 40, EVENT : 261);OB_NR组织块编号硬件中断就是40。EVENT事件ID就是硬件组态里分配的那个硬件标识符。执行成功后事件261就不再触发OB40了。要恢复的话ATTACH(OB_NR : 40, EVENT : 261);这两个指令都有返回值建议用RET_VAL接一下出错时能知道是参数不对还是事件不存在。4.3 什么场景下必须分离我总结了几类必须用DETACH的场景第一类调试/手动模式。设备在手动调试时操作工会反复触发传感器这时候中断没意义反而干扰主程序。可以在切换到手动模式时DETACH切回自动时ATTACH。第二类批量处理期间。比如一个工位要连续处理100个工件处理期间不希望被新的中断打断可以先DETACH处理完再ATTACH。这比在OB40里加一堆条件判断要干净得多。第三类故障恢复。某个中断通道的传感器坏了一直误触发可以先DETACH把它隔离等换好传感器再ATTACH避免影响其他逻辑。第四类初始化阶段。CPU刚启动、系统还没准备好时中断来了也没法正确处理可以在OB100里先DETACH等初始化完成后再ATTACH。4.4 DETACH和ATTACH的配对管理这里有个容易出错的地方DETACH和ATTACH必须成对管理不能重复DETACH同一个事件也不能ATTACH一个没DETACH的事件。我一般会在DB里给每个中断事件维护一个状态位变量名类型含义MarkInt_AttachedBool色标中断当前是否已绑定EStopInt_AttachedBool急停中断当前是否已绑定每次DETACH前先判断状态位ATTACH后更新状态位。这样即使程序逻辑复杂也不会出现重复分离或重复绑定的异常。实操心得DETACH之后如果这个通道还有边沿信号进来它不会触发OB40但输入点的状态仍然可以在OB1里通过普通输入读取。所以分离中断不等于屏蔽信号只是改变了响应方式。5. 创建与分离配合的实战场景拆解5.1 场景一高速色标定位中的动态中断管理回到开头那个包装机案例。色标信号在自动运行时需要中断但在设备启动、换料、清洗阶段操作工会手动拉动膜这时候色标会频繁触发。我的做法是自动模式ATTACH色标事件OB40负责计数和记录位置。手动/清洗模式DETACH色标事件OB1里用普通输入做低速检测。模式切换时先DETACH再切模式避免切换瞬间的误触发。这样既保证了自动运行时的精度又避免了调试阶段的干扰。实测下来自动模式下丢标率从7%降到0.1%以下手动模式也不会再卡触摸屏。5.2 场景二急停中断的一次性处理急停信号通常只需要响应一次——按下时记录状态、触发安全逻辑之后设备已经停了再触发也没意义。这时候可以在OB40里处理完急停逻辑后直接DETACH急停事件// OB40中急停分支 DB_Data.EStopFlag : TRUE; DB_Data.EStopTime : RD_SYS_T(); DETACH(OB_NR : 40, EVENT : 262);等操作工复位急停、确认安全后在复位逻辑里再ATTACH回去。这样避免了急停按钮抖动或反复按导致的重复中断。5.3 场景三多中断源的优先级和分离策略S7-1200支持多个硬件中断事件它们之间是有优先级的。如果两个中断同时来高优先级的先执行。但更常见的情况是一个高频中断比如色标和一个低频但重要的中断比如安全门共存。如果高频中断一直触发低频中断可能被延迟。我的策略是高频中断在不需要时果断DETACH把CPU资源让出来。比如色标中断只在检测工位激活其他工位运行时DETACH掉。这样安全门中断的响应时间能稳定在微秒级不会被色标拖累。5.4 场景四中断丢失后的排查和恢复有时候中断会莫名其妙不触发了排查思路一般是检查硬件组态里中断是否还被勾选。检查程序里是否有DETACH没配对ATTACH。用在线监控看OB40是否被调用OB40_EV_ID是否有值。检查输入点的LED是否正常闪烁排除硬件问题。确认没有在OB40里执行了会导致CPU故障的操作。我遇到过一次是因为在OB40里调了一个带延时的FB导致CPU报错中断被系统自动禁用了。后来把那个FB移到OB1里就正常了。中断程序里千万不要放任何可能阻塞或报错的复杂逻辑这是铁律。6. 常见问题速查与避坑经验6.1 中断不触发的排查表现象可能原因排查方法OB40完全不执行硬件组态没勾中断检查设备视图里的输入通道配置OB40执行但EV_ID不对事件ID读错从系统常数复制不要手写中断偶尔丢脉宽太窄或干扰用示波器看信号加硬件滤波中断频繁误触发信号抖动硬件加RC滤波或改双边沿为单边沿DETACH后无法ATTACH事件ID不匹配确认ATTACH用的EVENT和DETACH一致中断导致CPU停机OB40里有错误逻辑检查是否有阻塞指令、非法访问6.2 几个我踩过的坑坑一以为DETACH是禁用输入。实际上DETACH只影响中断触发输入点状态照常读取。如果你在OB1里还用这个点做逻辑它仍然有效。坑二在OB40里用上升沿指令。OB40本身就是边沿触发的里面再用R_TRIG是多余的而且可能因为扫描机制导致漏检。直接在OB40里执行逻辑即可。坑三多个事件共用一个OB40时没做分支。如果两个通道都绑到OB40但程序里没判断EV_ID那不管哪个触发都执行同一段代码逻辑就乱了。坑四ATTACH/DETACH的EVENT参数用了硬件ID的符号名。有些版本里符号名不能直接用在EVENT参数上需要用数值。我一般先在系统常数里找到对应的数值再用常量或DB变量传递。坑五忘记在OB100里初始化中断状态。CPU重启后中断绑定状态可能不是你预期的最好在OB100里统一ATTACH或DETACH一遍确保初始状态可控。6.3 中断响应时间的实测数据我用1214C DC/DC/DC做过简单测试OB1扫描周期约6msOB40从信号边沿到执行第一条指令实测约50~80微秒。如果OB40里程序很短十几条指令整个中断处理时间在100微秒以内。这个数据意味着只要信号脉宽大于100微秒外部中断基本不会丢。对比主程序6ms的周期差距是60倍以上。当然这个数据会受CPU型号、固件版本、OB40内程序复杂度影响。G2系列的新CPU响应更快但具体数值建议自己实测。7. 写在最后中断是工具分离是策略外部中断这个东西创建本身半小时就能学会但真正用好靠的是对什么时候该让它工作、什么时候该让它休息的判断。DETACH和ATTACH这对指令看起来只是两个简单的绑定操作实际上是把中断从一直开着的开关变成了按需启用的资源。我在非标项目里的一条经验是凡是中断都要有明确的启用和停用条件。不要让它一直挂着也不要让它永远关着。自动运行时开手动调试时关关键工位开空闲工位关正常生产开故障恢复关。这种动态管理比在OB40里堆一堆IF判断要清晰得多也稳定得多。如果你正在做高速计数、精确定位、急停响应这类项目建议先把外部中断的创建跑通再花时间把DETACH/ATTACH的配对逻辑理清楚。这两步做扎实了后面遇到再快的信号心里都有底。