恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
博图FB块与IEC定时器完全指南:从创建到调用,覆盖S7-1200/1500项目实战
首页
资讯中心
/
博图FB块与IEC定时器完全指南:从创建到调用,覆盖S7-1200/1500项目实战
博图FB块与IEC定时器完全指南:从创建到调用,覆盖S7-1200/1500项目实战
发布时间:2026/10/1 11:48:15
做PLC项目的工程师基本都绕不开西门子的博图环境TIA Portal而博图里最常用的两个东西一个是FB块一个是定时器。FB块解决了逻辑复用的问题定时器解决了时间控制的刚需这两样组合起来基本能覆盖设备控制里八成以上的逻辑场景。这篇内容就把FB块从创建到调用的完整流程讲清楚同时把定时器在FB块内部的使用方式、选型逻辑和常见坑位都盘一遍适合刚开始用博图做S7-1200/1500项目的工程师也适合从老款Step 7转到博图的朋友快速建立新习惯。1. FB块和定时器的基本功为什么这两个要一起聊很多刚接触博图的人会有个疑问FB块到底比FC高级在哪定时器放在FB里和放在主程序里又有什么区别。这个问题的答案直接决定了项目后期好不好维护。1.1 FB块不是“高级功能”是高复用逻辑的容器FB的全称是Function Block中文叫函数块。它和FC函数最大的区别就是FB带自己的存储区也就是背景数据块Instance DB。你在FB里定义的静态变量、定时器实例、计数器实例都会存在这块专属于它的数据区域里。这带来的直接好处就是同一个FB块可以被调用多次而每次调用都有自己独立的数据空间互不干扰。举个例子。你写一个气缸控制逻辑包含伸出、缩回、到位检测、超时报警。如果用FC写这些中间状态要么放在全局DB里要么通过形参传进传出一旦调用两套气缸变量就要复制一份改起来先是名字后缀1、2、3后来后缀变成了一堆数字最后自己都认不出来。而用FB写气缸逻辑封装在一个统一接口里调用两次就是两个背景DB互不影响。在博图里FB的接口区划分很讲究输入、输出、静态变量、临时变量各有各的用途。很多初学者把Input当函数入参、把OutPut当返回值来理解这不算错但忽略了Static区才是FB的灵魂所在。Static变量在FB被调用之后仍然保持值相当于给这个功能块配了一个永久记忆本。定时器、计数器的实例就放在静态区或者作为局部变量在块内声明这是博图推荐的做法。1.2 博图里的定时器已经换了一代——IEC定时器从Step 7转到博图的工程师要特别注意西门子在S7-1200/1500平台已经全面采用IEC定时器就是TON延时接通、TOF延时断开、TP脉冲、TONR累计延时。S7-300/400时代那种S5定时器T1、T2、T3这种在博图里虽然还能兼容部分老项目但新项目基本不会用它。IEC定时器的本质是一个函数块实例。这意味着什么意味着你每次使用一个定时器本质上都是在调用一个FB它同样需要自己的背景数据。这也就解释了为什么很多人在主OB1里拉一个TON定时器的时候博图总会自动生成一个背景数据块DB。如果你在FB块内部去调用定时器情况也一样——定时器要么使用专门的DB来保存状态要么以多重背景的方式挂在FB自己的背景数据块里。我在实际项目里比较推荐后者在一个FB块内部直接把定时器声明成静态变量这样定时器的存储区就包含在FB块的背景数据块里不占用额外的全局DB编号调用关系也清楚移植到别的项目时不需要连锅端地复制一堆DB。1.3 定时器放在FB里的优势定时器放在FB内部不只是省几个DB编号的事。更重要的优势是封装性和可迁移性。比如你有一段设备启动的时序逻辑先启动主接触器延时2秒再启动油泵油泵启动3秒后如果压力没有建立就报警停机。这段逻辑如果直接写在OB1里整个OB1会变成一长串定时器接线图看半天不知道这段是干什么用的。而把它放进一个叫做“设备启动时序”的FB内部外部接口只需要启动指令、故障复位、压力反馈内部把三个定时器按顺序串起来调用面极其干净。排查问题的时候也很有优势。你在FB的调试界面里能看到所有静态变量和定时器状态。这个FB的所有内部状态都集中在这一个块里而不像FC那样状态散落在各个全局DB里。对电气工程师来说这种“把设备逻辑装进一个盒子里”的做法在调试阶段节省的时间不是一点点。2. FB块的完整实操从建块到调用2.1 新建一个FB块语言和编号怎么选在博图左侧项目树里打开“程序块”右键新建选择函数块会弹出一个对话框。第一项是名称建议有意义的命名规范比如“FB_ConveyorControl”、“FB_AutoStartSequence”不要用FB1、FB2这种默认编号。虽然编号可以自定义但可读性比编号重要得多如果你有跨项目复用的习惯名字一搜就能找到编号未必。语言选择上默认是LAD梯形图也可以选FBD功能块图或SCL结构化文本。对于定时器逻辑比较多的块我个人更倾向于SCL因为SCL写延时逻辑天生简洁几行IF语句就能完成一个复杂的时序控制。但如果你习惯看触点线圈这类图形化编程LAD完全没问题。博图允许同一个项目里混用语言一个块用LAD一个块用SCL不冲突不存在什么性能差异按熟练度来就好。编号上有一个细节S7-1200的FB编号范围是1~65535S7-1500也是这个范围。如果你建了FB却不想限制编号可以留空由系统分配。系统分配的编号不会冲突但如果你把块放在组织块下的文件夹里编号不会自动跟硬件槽位对应纯属于逻辑对象不必强迫自己编得特别有规律。2.2 接口区规划Input/Output/InOut/Static/TempFB块界面的上半区域是接口区。这里必须认真规划。先看主要类别Input外部调用时输入的参数比如启动、停止、速度设定值。Output输出给外部的状态比如运行中、故障、当前计数。InOut既是输入又是输出比较典型的场景是数组参数或者某个结构体需要访问和修改传入的数据。Static静态变量FB内部自己保存状态的区域调用结束不清零。这是定时器、计数器、标志位的默认存放位置。Temp临时变量每次调用开始时分配调用结束就释放。适合临时计算值但要注意它不是保持型的下个扫描周期不保证原来的值。这里有个常见误区有人把定时器的预设时间PT作为一个Input直接接到一个常数上这当然可以但如果你希望这个延时可被上位机HMI调整最好在FB外部做一个专门的“参数DB”把PT值和多重背景的地址连起来。这样虽然多了一点小事但后期要调整延时值的时候不需要重编译下载FB只改数据就能生效。再提醒一个细节Input和Output在FB内部读取和赋值的区别。Input可以直接读但尽量不要直接写Input变量Output可以直接写但不要拿来当内部逻辑的临时寄存器用。最好把所有内部中间状态放在Static区保证接口语义干净。这在SCL里面尤其重要因为直接操作Input会产生不可预期的结果而且极难排查。2.3 实例化DB和多重背景两种调用方式的选择FB块写完之后必须在某个地方调用它这叫做实例化。实例化的结果就是生成一个背景数据块Instance DB。在OB1里拖入FB博图会提示你为它生成一个背景DB你可以命名为“Conveyor_DB”这个DB存储了该FB实例下所有的静态变量和运行状态。如果你在一个FB块内部再去调用另一个FB比如在“机器总控FB”里调用“气缸控制FB”就是嵌套调用。这时有两种选择一种是给内部FB单独分配一个背景DB另一种是使用多重背景把内部FB实例作为外部FB的静态变量声明这样所有内部FB的数据都合并到一个背景DB里面。多重背景的写法是在FB的Static区定义一个名为“Cylinder_A”的变量数据类型选择“气缸控制FB”。然后你在当前FB的代码里可以直接调用Cylinder_A它就相当于那个内部FB的一个实例。调用后你不需要额外建DB数据都存在外部FB的背景DB里。这种做法在大型程序里特别常见因为背景DB数量大幅减少且能直接看到分层关系。两种方式怎么选如果每个内部FB实例的使用频率、运行周期都很独立比如一个负责通信一个负责运动控制单独分配DB更清晰如果内部FB是典型的复用逻辑比如四个一模一样的阀组控制强烈建议用多重背景编程体验和后期维护都比单独建DB好很多。3. 在FB块里调用定时器一个电机定时启停的完整案例3.1 TON/TOF/TP到底怎么选定时器虽然种类多但实际选用时可以按需处理TON接通延时输入信号变True后经过设定时间输出才变True。常用于延时启动、超时报警。TOF断开延时输入信号变False后输出再维持一段时间才变False。常用于设备停机后延时关闭冷却风扇。TP脉冲输入信号任意时输出固定输出一个设定宽度的高电平。常用于生成一个固定长度的触发脉冲。TONR累计延时允许定时过程被中断后继续累计时间。常用于统计设备的累计运行时间。你会发现TON是使用频率最高的一种因为绝大多数设备流程是“启动多少秒以后执行下一步”。但在FB内部写SCL时序逻辑时有一种技巧让定时器的启动输入衔接上流程里的状态位这样用几个TON串行或并行就能组成相对复杂的时序。我用一个简单的电机定时启停模型来演示这样大家能直接拿去做实验。3.2 案例用FB实现电机自动循环启停假设需求是这样一个电机按一下自动按钮先启动运行8秒停止4秒再启动8秒这样循环按停止按钮或者出现故障立即停止。用FB来实现接口规划如下InputAutoStart启动自动循环、Stop停止、Fault外部故障OutputMotorRun电机运行输出、CycleActive循环进行中StaticTimerRunTON实例、TimerStopTON实例、IsRunState运行/停止状态标志SCL代码可以这样写IF #AutoStart AND NOT #Stop AND NOT #Fault THEN #CycleActive : TRUE; END_IF; IF #Stop OR #Fault THEN #CycleActive : FALSE; #MotorRun : FALSE; #TimerRun(IN : FALSE); #TimerStop(IN : FALSE); // 状态复位 END_IF; IF #CycleActive THEN IF #IsRunState THEN #TimerRun(IN : TRUE, PT : T#8S, Q #RunDone, ET #RunTime); #MotorRun : #RunDone OR NOT #TimerRun.Q; // 实际上运行状态由定时器保持 IF #RunDone THEN #IsRunState : FALSE; #TimerRun(IN : FALSE); // 复位运行定时器 END_IF; ELSE #TimerStop(IN : TRUE, PT : T#4S, Q #StopDone, ET #StopTime); IF #StopDone THEN #IsRunState : TRUE; #TimerStop(IN : FALSE); END_IF; END_IF; ELSE // 未启动输出复位 #MotorRun : FALSE; #TimerRun(IN : FALSE); #TimerStop(IN : FALSE); END_IF;这段代码有点简化因为电机在停止阶段输出应当为False而在运行阶段输出为True。更准确的实现可以这样写// 用状态机的方式 IF NOT #CycleActive THEN #IsRunState : FALSE; #MotorRun : FALSE; #TimerRun(IN : FALSE); #TimerStop(IN : FALSE); ELSE IF #IsRunState FALSE THEN // 当前停止状态经过4秒后切到运行 #TimerStop(IN : TRUE, PT : T#4S, Q #StopTimeUp, ET #StopTime); #MotorRun : FALSE; IF #StopTimeUp THEN #IsRunState : TRUE; #TimerStop(IN : FALSE); END_IF; ELSE // 当前运行状态经过8秒后切到停止 #TimerRun(IN : TRUE, PT : T#8S, Q #RunTimeUp, ET #RunTime); #MotorRun : TRUE; IF #RunTimeUp THEN #IsRunState : FALSE; #TimerRun(IN : FALSE); END_IF; END_IF; END_IF;这个写法把运行和停止两个定时器永远保持在“一个工作、一个待命”的状态代码逻辑很好跟踪。你在实际项目里可以多加一个“首次启动”逻辑让电机第一次启动不需要先等4秒停止这个留给需要的朋友自行扩展。3.3 定时器在FB内部的两个实现细节第一个细节SCL里定时器的调用格式必须是“名字(IN:..., PT:..., Q..., ET...)”其中Q和ET是输出必须用指针赋值到本地变量不能留空。如果你只关心Q不关心ET也要写Q某个变量否则编译会报错。第二个细节定时器变量在FB内部怎么声明。如果你在Static区声明了一个“TON类型”的变量它会被称为“定时器实例”。当你在SCL中调用它时编译器要求该实例不能重复出现在多个位置。如果你在LAD里拖了一个定时器后想改成SCL要注意那里的已经声明好的实例能否在SCL里直接沿用。不同语言之间调用IEC定时器实例的声明位置基本一致都在Local标签里。还有一点如果要在多个FB之间共享同一个定时器比如监控总时间你得把定时器放在全局DB里然后在FB里用“全局变量”的方式访问。不过这种做法会影响FB的封装性最好只在跨块状态同步的时候用。4. 常见报错与排查技巧实录4.1 编译报错“step 7 basic”的常见场景搜这个词的人多半是被TIA Portal的弹窗折磨过。这里提一个很多人忽略的基础知识博图软件的许可证和功能并不完全等同早期的TIA V13/V14分为“Step 7 Basic”和“Step 7 Professional”两个档次。Step 7 Basic只能用于S7-1200的编程而S7-1500以及部分高级功能需要Step 7 Professional。当你打开一个含有S7-1500 PLC的项目却只安装了Basic版本的软件就会看到类似“Step 7 Basic不支持该对象”的报错。另外即使是S7-1200项目如果你用了某些高级指令或者网络通信指令Basic版本编译时也可能弹出提示。解决思路分两步第一步检查你项目的设备版本是否匹配软件许可证第二步确认你使用的库指令是否包含在Basic版本内。还有一种比较容易踩坑的情况是跨版本兼容。比如用TIA V16建的项目下载到只装了V15的电脑上打不开报错内容通常是版本不兼容。这不算软件BUG而是西门子对项目版本向下兼容限制。最好的做法是项目建立之初就确定好团队使用的博图版本并尽量统一如果必须在老版本里打开新版本项目只能通过“项目归档”和“版本转换”功能但也不能保证所有对象都能顺利转换。4.2 定时器不动作时先查这三处定时器不动作我遇到过的原因十有八九是这三类第一类是定时器输入一直不满足。你检查代码一看TON的IN端确实是True但Q迟迟不变。这种情况十有八九是定时器实例没有真正被调用。在SCL里定时器调用必须写在扫描到的代码路径里如果你的定时器声明了但放在某个IF分支里没有执行到那它就一直不会被驱动。排查时可以加一个探针变量看程序有没有走到那个分支。第二类是定时器输入快速抖动。TON本身有“边沿触发后再计时”的行为如果IN在你设定的延时时间内发生闪断定时器会重新计时。这在现场表现为输出常常不满时间就复位。解决办法是在IN端前加上一个启动保持标志位比如自锁让信号一旦置位就一直保持直到流程主动清除。PLC扫描周期很短但抖动周期不稳定如果计时有严格要求需要用更快的信号同步方案比如用中断OB或者硬件输入滤波。第三类是Timer实例的检查尤其是你在FB里创建定时器实例时如果变量名重复或者块复制粘贴之后实例引用错乱会导致两个FB虽然界面一样但实际使用的是同一个背景数据块中不同的定时器实例表现为其中一个定时器永远被另一个块的调用周期干扰。解决办法是删除那个FB重新生成并确保背景DB重新分配。4.3 背景数据块与保持性设置FB块的背景数据块默认是非保持的也就是说PLC断电重新上电后背景DB里的变量会清零。如果你的FB内部有累计时间、故障计数需要断电保持需要单独在该DB中设置保持性。具体做法是在背景数据块的变量表里选中某个变量属性里勾选“保持”。注意只有断电保持才生效不代表热复位也会保持热复位时所有非保持变量会恢复启动值。定时器的保持性要特别注意IEC定时器并没有专门“断电保持”的选项。也就是说TON的剩余时间在断电后会丢失。如果你的项目需要断电后继续保持某个延时的剩余进度比如冷却时间还剩5分钟断电后来电继续从5分钟开始那是非常高的要求不能直接在TON上打勾实现。标准做法是在FB里增加一个保持型变量“剩余时间”在每次定时器运行时把ET存进去断电上电后把剩余时间写回TON的PT并置IN为True继续计时。这个逻辑不复杂但很多工程师第一次遇到时会觉得匪夷所思以为西门子产品功能缺陷——其实不是缺陷而是设计如此需要你用上层逻辑去保存定时器状态。我做过一个项目压缩机在断电后需要维持禁止启动30分钟就是用上述方法实现的。核心就是在背景DB里放一个保持变量KeepRemainTime每次停机时把TON的输出ET刷新到这个变量上电后做一个判断如果KeepRemainTime 0就启动TON并把PT设为KeepRemainTime。4.4 在线监控与调试技巧FB和定时器相关的问题在线监控是非常好用的排查手段。你可以在博图的“监控”模式下看定时器的IN、PT、ET、Q四个值。TON为例正常情况下IN为True后ET会从0开始增长增长到PT对应的毫秒数后Q会变成True。如果IN是True而ET一直为0说明这个定时器实例没有被正确调用或者它在当前扫描周期里根本没有被执行。如果IN是False而Q还是True说明你用了TOF或者忘记复位定时器。在线模式下修改定时器时间也很有用。如果你在FB里把PT写成死值运行中没法在线改如果你想临时改个延时做实验可以在监控界面直接右键定时器实例修改参数值这样可以避免为了改个时间就重新编译下载整个PLC程序。当然改了之后一旦掉电还是会回到原来的程序值这只是调试手段。5. 一点实操心得与收尾最后分享一个小习惯也算是我走过弯路之后的总结。我在每个FB块内部都会在Static区放一个“状态字”变量比如第一位是初始化完成、第二位是主流程使能、第三位是定时器启动条件。状态字这个变量看起来是多余的但它极大地方便了排查问题。遇到定时器不动作时先看这个状态字当前是哪一位是0就能迅速定位是“条件没够”还是“定时器本身坏了”。这个方法听起来很土但比抱着监控表翻一大堆临时变量快得多。另外博图的库功能值得好好用起来。把常见的FB比如电机控制、阀组控制、气缸控制做成库拖到项目里就可以复用前提是FB内部不引用全局DB和外部符号所有数据都通过接口传递。定时器也是一样把定时器做成FB内部的静态实例这样整个FB归档到库的时候定时器正好跟着背景DB走不需要再额外创建存储区。这个习惯养成之后新项目起步快很多而且不同项目之间的逻辑一致性也有了保障。博图这个东西说到底是熟能生巧。FB块和定时器是每天都要碰的基本功值得花一个下午的时间把两种调用方式、四种IEC定时器、背景DB的保持性规则都摸一遍。把基本功打扎实以后你再去看那些复杂的运动控制、PID调节、通信功能块会觉得它们也都是由这些基础块一层一层搭起来的。