首页 > 基础教程 > SCL基础教程 > 文章内容

SCL PLC 编程教程第八篇 FC、FB、DB 的关系与调用方法:程序为什么不能一直堆在主程序里

时间: 2026-04-28 13:44浏览量:82次


很多 PLC 工程师在项目初期写程序时,常见的一个习惯是:

想到什么功能,就往主程序里加。
加一个网络,写一段逻辑;
再来一个需求,再加一段;
又多一个报警,再塞进去;
再多一个模式切换,再接着写。

项目小的时候,这样还能撑住。
但只要项目开始稍微复杂一点,很快就会出现这些问题:

主程序越来越长,翻半天找不到对应逻辑
同样的控制逻辑在多个地方重复写
一个地方改了,另一个地方忘了改
某个功能到底归谁管,越来越模糊
变量满天飞,程序块之间边界不清
接手的人看一眼就头大
自己两个月后回来改,也觉得很痛苦

出现这些问题,往往不是因为你不会写 IF 或 FOR,
而是因为程序缺少“组织结构”。

所以,FC、FB、DB 这些概念,表面上看像是程序块知识,
但本质上它解决的是更大的问题:

程序要怎样分层、分块、分职责。

这一篇你要真正理解的,不只是“FC 是什么、FB 是什么”,
而是它们为什么存在,以及你什么时候该用谁。

一、先把最重要的一句话记住:FC、FB、DB 不是为了增加复杂度,而是为了让复杂程序不至于失控

很多初学者第一次接触这些概念时,会觉得它们有点绕:

为什么一个程序还要分这么多块
为什么有的地方要用 DB
为什么不能什么都写在 OB 里
为什么一个功能块还要配一个实例数据块

如果只是死背定义,确实容易越学越糊。
但如果你换个角度看,就会突然明白:

FC、FB、DB 本质上是在帮你把程序“按功能和数据关系拆开”。

你可以把它想成盖房子:

OB 像总入口、总调度
FC 像一个完成某种处理的工具房间
FB 像一个既能处理逻辑、又能保存自己内部状态的功能房间
DB 像存放数据和状态的专属储物间

如果没有这些分工,房子也能盖,但很快会乱成一团。

所以你不要把这些概念看成额外负担。
它们恰恰是程序越来越大之后,让你还能保持条理的关键。

二、为什么主程序不能无限堆逻辑

这一点一定要先讲清楚。
因为如果你不真正理解“为什么不能一直堆在主程序里”,后面学 FC、FB、DB 很容易只是背概念。

我们来看一个真实工程里很常见的过程。

一开始你写一个简单项目,主程序里只有:

启停逻辑
急停逻辑
几个输出控制
一个报警灯

这时候主程序很短,看起来挺清楚。

接着项目开始扩展:

加自动模式
加手动模式
加多个电机
加多个气缸
加报警系统
加配方
加计数统计
加通信
加工位管理
加 HMI 交互
加权限逻辑

如果这些东西都继续直接往主程序里塞,会发生什么?

第一,主程序职责失控

主程序本来应该更多承担“总调度”的角色,
结果最后它既管电机,又管气缸,又管报警,又管配方,又管扫码,又管通信。

这就像一个人既要当厂长、又要当电工、又要当质检、又要当仓管。
短期看还能干,长期一定会乱。

第二,功能边界模糊

例如某个电机控制逻辑,一部分写在主程序前面,一部分写在后面,故障处理又散在别处。
你会越来越说不清:

“这个功能到底归哪一块管?”

第三,复用性变差

你如果有 4 台类似电机、6 个类似气缸、12 个类似工位,
如果没有模块化结构,就只能不断复制粘贴,后期维护会非常累。

第四,调试和接手都痛苦

因为程序不是“功能块”,而是一大摊主流程混合体。
任何人接手都要从头翻。

所以主程序不能无限堆逻辑,核心原因不是“规范要求”,而是:

程序规模一旦上来,没有分块结构就很难维护。

三、OB、FC、FB、DB 可以先怎样整体理解

为了让你不乱,我们先用一种工程化、但不死板的方式理解它们。

1. OB:组织块

OB 可以理解成程序运行的入口或调度层。
它更像“什么时候执行什么”的总安排。

例如主循环组织块,你可以把它想成 PLC 每个扫描周期都会从这里开始往下走。

所以 OB 更像程序的“主干道”。

2. FC:功能块,偏处理型

FC 通常更适合做“有输入、有处理、有输出”的逻辑功能。
它像一个工具函数,拿到输入,做完处理,给出结果。
它本身通常不强调长期保存自己的内部状态。

3. FB:功能块,偏对象型、状态型

FB 不只是处理逻辑,它还很适合保存自己内部相关的数据和状态。
这使它特别适合:

电机模块
气缸模块
阀门模块
状态机模块
配方模块
设备单元模块

也就是说,FB 更像“一个带内部记忆的功能对象”。

4. DB:数据块

DB 是存数据的地方。
它可以是某个 FB 的实例数据存储,也可以是项目里用来存配方、参数、状态记录等的独立数据区。

简单点说:

FC 更像一个处理工具
FB 更像一个带内部状态的功能对象
DB 更像数据存储空间

你现在先不用急着扣最严谨的术语定义,
先把这个工程感觉建立起来最重要。

四、FC 到底适合干什么

FC 的价值,在于它很适合做“纯处理逻辑”或者“相对独立的功能计算”。

你可以把 FC 理解成:

给它一组输入,它按规则处理后,输出结果。

它特别适合这些场景:

1. 计算类功能

例如:

模拟量缩放
温度换算
滤波计算
限幅处理
偏差计算
平均值计算
2. 规则判断类功能

例如:

判断是否满足启动许可
判断是否触发某类报警
比较一组参数是否合格
3. 工具型逻辑

例如:

批量字符串拼接
数据格式转换
某些公共处理逻辑

这些功能往往有一个特点:

它们更关注“输入进来怎么处理”,而不是“我自己内部要长期记住什么状态”。

这就是 FC 很适合的地方。

五、FC 的一个很重要特点:它更像“函数工具”,而不是“设备对象”

这点你一定要有感觉。

例如你写一个“模拟量缩放”的逻辑。
给它原始值、上下限、工程量范围,它返回计算结果。
这种功能本身更像一个通用处理工具。

它不是一个“设备对象”,它没有那种“我要长期记住自己内部动作过程”的强烈需求。
所以这种场景下,FC 就很自然。

再比如“判断温度是否超上限”:

输入温度值
输入高限
输出报警状态

这类逻辑也很适合 FC。

所以你可以先记住一个判断原则:

如果这个功能更像一个处理器、计算器、规则工具,那通常优先想 FC。

六、FB 到底适合干什么

FB 和 FC 最大的差别,不在于“它也能写逻辑”,因为 FC 也能写逻辑。
真正关键的差别在于:

FB 非常适合那些既有逻辑处理、又需要保存自己内部状态的功能。

这句话特别重要。

例如一个电机控制模块,不只是“输入启动命令,输出运行命令”这么简单。
它很可能还要保存:

当前是否在运行
是否故障锁存
上一次启动状态
启动延时是否完成
停机延时是否完成
是否处于自动模式允许状态
当前步骤是否已经到达

这些都不是单次处理就完事的逻辑,
它们需要在多个扫描周期之间持续保持状态。

这时候,FB 的优势就非常明显。

七、FB 特别适合哪些场景
1. 设备对象控制模块

例如:

电机模块
气缸模块
阀门模块
输送线模块
加热区模块

这些对象通常都有:

输入命令
输出状态
内部条件
定时逻辑
故障逻辑
记忆状态
2. 状态机类模块

例如某个工艺流程控制器,里面有:

当前步骤号
上一步状态
定时等待状态
完成标志
错误状态

这些都需要“记住过去”,所以特别适合 FB。

3. 需要封装成可重复使用单元的功能

比如项目里有 8 个完全类似的工位。
每个工位都有占用、夹紧、完成、报警、复位等逻辑。
这种时候用 FB 非常有价值,因为它天然适合做“一个对象模板,多次实例化”。

八、FC 和 FB 最根上的差别,到底怎么理解

你可以用一句非常实在的话来区分:

FC 更像“做一件事”

例如:

算一下这个值
判断一下这个条件
处理一下这组输入
FB 更像“成为一个对象”

例如:

这是一个电机模块
这是一个气缸模块
这是一个工位模块
这是一个顺控模块

也就是说:

FC 更像动作工具,
FB 更像带状态的功能实体。

这个感觉一旦建立起来,后面很多选择就不会乱。

九、什么叫“内部状态”,为什么它决定了很多时候该用 FB

“内部状态”是很多初学者听过但没真正吃透的词。

你可以把它理解成:

不是只靠当前输入就能完全决定结果,还需要记住之前发生过什么。

例如:

情况一:纯计算

给一个原始值,换算成工程值。
这类逻辑通常不太依赖过去状态。

情况二:电机控制

如果一个电机启动后要保持运行,
你就要知道:

它之前有没有被允许启动
是否已经启动成功
故障有没有锁存
运行状态是否保持
上一次启动按钮是什么状态

这些就是内部状态。

再比如状态机控制:

当前在第几步
上一步是否完成
某一步是否刚进入
某个超时计时是否已经开始

这些也都是内部状态。

所以你以后只要看到某个功能明显依赖“过去发生过什么”,
就要警觉:

它很可能更适合 FB。

十、DB 到底是什么,为什么很多人一开始最容易对它模糊

DB 是数据块。
它最容易让人糊涂的原因是:它不是“执行逻辑的块”,而是“存放数据的块”。

很多初学者会下意识更关注程序逻辑,于是会觉得:

FC 是程序块
FB 是程序块
那 DB 好像只是个附属东西

其实 DB 非常重要。
因为程序不只是逻辑,还必须有地方存数据。

你可以把 DB 理解成“专门的数据仓库”。
里面存什么,取决于你怎么设计。

它可能存:

参数
配方
报警记录
工位状态
统计值
结构化数据
某个 FB 的内部实例数据

所以 DB 的核心作用不是“执行”,而是“承载数据”。

十一、DB 和 FB 为什么经常一起出现

这点是很多人必须真正搞懂的地方。

前面说过,FB 很适合带内部状态的功能。
但这些状态不能飘在空气里,总得有地方存吧。

这时候,就需要 DB。

也就是说,FB 里的那些内部数据、状态信息、参数值,往往需要有对应的数据存储区域。
这个数据存储区域,在很多工程平台和实践中,就是实例 DB。

你可以把它想成:

FB 是功能逻辑模板
DB 是这个模板某次实际使用时的数据仓库

比如一个电机控制 FB,你调用一次给 1 号电机用,就要有 1 号电机自己的数据存储区;
再调用一次给 2 号电机用,就要有 2 号电机自己的数据存储区。

否则,这两个电机的内部状态就会混在一起。

这就是为什么 FB 和 DB 常常是绑定思考的。

十二、实例 DB 这个概念,到底怎么理解才不绕

你不要一上来就把“实例 DB”理解成特别抽象的术语。
你可以这样想:

假设你写了一个“电机控制模块”,这个模块的逻辑是固定的。
但项目里有 4 台电机:

1 号电机
2 号电机
3 号电机
4 号电机

它们的控制规则相似,所以逻辑模板可以共用。
这就是 FB 的价值。

但每台电机自己的运行状态、故障状态、定时器状态、上次命令状态,必须各自独立保存。
这时候,每台电机就需要自己的“专属数据区”。

这个“专属数据区”,你就可以把它理解成实例 DB。

所以:

一个 FB 可以像模板一样重复使用,
每次实际用在某个对象上,都要有自己的数据实例。

这就是实例 DB 最实在的理解方式。

十三、FC 调用和 FB 调用,为什么在工程感觉上不一样

虽然两者都能“调用”,但它们给工程师的感觉确实不同。

调用 FC 时

你更像是在说:

“来,把这个计算做一下。”
“把这个条件判断一下。”
“把这个数据处理一下。”

它更像一个功能工具被拿来执行。

调用 FB 时

你更像是在说:

“来,让这个电机模块运行一下。”
“让这个工位模块执行一下。”
“让这个顺控对象更新一下自己的状态。”

它更像一个对象被周期性驱动。

所以两者的调用感很不一样。

一句话概括:

FC 更像调用一个动作;
FB 更像驱动一个对象。

这个感觉对你后面写模块化程序非常重要。

十四、什么时候优先考虑 FC,什么时候优先考虑 FB

这个判断非常实用。

优先考虑 FC 的时候

当你的功能更像下面这些:

数据计算
数值换算
通用判断
公共工具处理
不强依赖历史状态的逻辑
很适合被多个地方调用的“算法型”功能

例如:

模拟量缩放
数值限幅
均值计算
规则判断
某类报警条件组合
优先考虑 FB 的时候

当你的功能更像下面这些:

某个设备单元
某个动作对象
某个顺控模块
某个带内部记忆的控制器
某个会跨扫描周期保存状态的功能

例如:

电机模块
气缸模块
阀门模块
工位模块
自动流程模块
运动单元模块

所以以后判断时,你可以先问自己:

这段逻辑是像“计算工具”,还是像“控制对象”?

这个问题很有用。

十五、什么样的数据适合放在 DB 里

DB 不只是为了 FB 存内部状态。
在工程中,它还有很多非常实用的用途。

1. 配方数据

例如:

温度设定
时间设定
速度设定
压力设定
产品参数组

这些都非常适合集中放在 DB 里。

2. 设备参数

例如:

延时参数
上下限阈值
校准系数
控制常数
3. 状态记录

例如:

当前产品编号
当前工位状态
报警记录
累计产量
最近一次故障编号
4. 结构化对象数据

例如:

工位数组
报警数组
电机状态列表
配方结构体集合

所以你会发现,DB 并不是一个“只给 FB 配套”的东西。
它本身也是项目数据组织的重要载体。

十六、为什么很多工程项目一旦开始重视 DB,程序会明显更规整

因为程序不再只是逻辑散写,而开始真正有“数据层”的意识。

例如以前你可能到处写:

TempSP_1
TempSP_2
TempSP_3
TempSP_4

后来你开始把它们按配方放进 DB 里,就会慢慢变成:

当前配方
默认配方
工艺参数
设备参数
报警配置
工位信息

这时候你会明显感觉:

程序开始不像一堆散变量,而像一个有组织的数据系统。

这就是 DB 的价值之一。

十七、一个非常典型的项目演化过程:从“全写在主程序里”到“功能块加数据块”

很多工程师的成长过程都差不多。

第一阶段:全写主程序

逻辑都堆在一起。
优点是上手快。
缺点是项目一大就乱。

第二阶段:开始拆 FC

把一些公共计算、判断、处理逻辑抽出去。
这一步通常意味着你开始有“复用”意识。

第三阶段:开始写 FB

当你面对电机、气缸、工位、顺控对象这些带内部状态的功能时,开始用 FB 封装。
这一步意味着你开始有“对象”和“模块”意识。

第四阶段:开始系统使用 DB

把配方、参数、状态、结构化对象数据都整理进 DB。
这一步意味着你开始有“数据层”和“工程组织”意识。

走到这一步,程序通常就会和最初“主程序越堆越大”的状态明显不同。

十八、调用功能块时,最重要的不是“会不会调”,而是“边界清不清楚”

很多人学 FC、FB 调用时,容易把注意力放在:

参数怎么写
输入怎么接
输出怎么取

这些当然重要。
但工程上更重要的问题其实是:

这个功能块的职责边界清不清楚。

例如一个电机控制 FB,最好回答得很清楚:

它负责什么
不负责什么
输入有哪些
输出有哪些
内部状态有哪些
报警逻辑归不归它
手自动切换归不归它
延时逻辑归不归它

如果这些边界不清楚,哪怕你会调用,后面也容易乱。

所以真正好的模块化,不只是“把代码挪到另一个块里”,
而是“明确每个块到底管什么”。

十九、FC、FB、DB 不是越多越好,而是分工要合理

这点也很重要。

有些人学会分块后,会走向另一个极端:

什么都拆,拆得特别碎。
一个很小的判断也拆成一个 FC,
一个很小的赋值也想包成一个块,
结果程序虽然“看起来很模块化”,但实际上跳来跳去,反而难读。

所以模块化不是拆得越碎越高级,
而是要看:

这个功能是否独立
是否有复用价值
是否有明确输入输出
是否会反复用到
是否应该有自己的状态数据

换句话说:

块的划分不是越细越好,也不是越粗越好,而是要刚好形成清楚的职责边界。

二十、从工程维护角度看,为什么 FB 往往很适合做标准模块

因为标准模块通常都有这几个特点:

有明确接口
有重复使用价值
内部有一定状态逻辑
每个对象实例之间要相互独立

这几条几乎天然符合 FB 的特点。

例如你做一套包装设备,里面有 12 个相似工位。
如果每个工位都散着写,后面非常难维护。
但如果做成 FB,一个工位一个实例,逻辑统一,数据各自独立,程序结构就会清楚很多。

所以你以后做标准化设备时,会越来越能体会 FB 的价值。

二十一、一个非常实用的判断法:先问“我要不要记住自己的过去”

这个判断法非常适合初学者。

以后你在设计某个功能块前,先问自己一句:

这个功能只看当前输入就够了,还是必须记住过去发生过什么?

如果只看当前输入就够了

很多时候可以优先考虑 FC。

如果必须记住过去发生过什么

例如:

上一次状态
当前步骤
锁存标志
内部计时进度
边沿检测历史值

那就很可能更适合 FB。

这是一个非常实用的工程判断方法。

二十二、为什么“程序结构”其实比“单段逻辑写得漂亮”更影响后期质量

这一点特别值得你从现在就建立意识。

很多初学者会非常在意:

这段 IF 写得优不优雅
这段 FOR 精不精简
这段 CASE 好不好看

这些当然重要。
但项目真正跑起来之后,更决定质量的往往是:

功能有没有拆对块
数据有没有归对地方
主程序是不是只承担调度职责
模块之间边界是否清楚
重复逻辑有没有封装
状态型对象有没有独立实例数据

也就是说:

一段局部逻辑写得漂亮,解决的是“局部好看”;
程序结构组织得好,解决的是“整体不乱”。

而 FC、FB、DB,就是整体不乱的关键工具。

二十三、初学者在这一部分最容易犯的几个错误
错误一:什么都写在主程序里

这是最常见的起点型问题。
项目小还能撑,项目一大就乱。

错误二:把 FC 当成万能模块

有些本来明显带内部状态的对象,也硬写成 FC,后面状态管理会越来越别扭。

错误三:FB 用了,但没真正理解“实例独立”

结果多个对象逻辑看起来共用了一个模块,但数据却没有真正独立,后面容易混乱。

错误四:DB 只当“存几个参数的地方”

而没有把它当成整个项目数据组织的重要载体。

错误五:只会建立块,不会划定职责边界

程序虽然拆了块,但谁负责什么仍然不清楚,后面照样乱。

二十四、给初学者一个非常实用的结构化思路

以后你面对一个新功能时,可以这样想:

第一步:这是总调度,还是局部功能

总调度放在 OB 思维里。
局部功能考虑拆出去。

第二步:这个功能更像计算工具,还是控制对象

计算工具优先考虑 FC。
控制对象优先考虑 FB。

第三步:这个功能需不需要保存状态

如果需要保存跨扫描周期状态,FB 的可能性就明显提高。

第四步:相关数据应该放哪里
是放在功能块实例里
还是做成公共 DB
还是做成参数 DB、配方 DB、状态 DB
第五步:这个块的输入输出边界是否清楚

如果边界说不清,说明设计还没想透。

这套思路你以后越用越顺。

二十五、这一篇最后,给你一个最实在的工程理解

你可以这样想:

以前程序全堆在一起,就像把所有工具、零件、图纸、材料都扔在同一张工作台上。
短时间还能找到,时间一长一定乱。

而 FC、FB、DB 的作用,就是帮你开始建立真正的车间秩序:

主程序负责调度
工具型功能放进 FC
带状态的设备对象放进 FB
对应的数据放进 DB
每个模块有自己的职责边界

这样程序不只是“能跑”,而是“能持续维护、能扩展、能复用”。

这就是从“会写程序”走向“会做工程”的关键一步。

小结

这一篇你最应该记住这些核心点:

主程序不能无限堆逻辑,因为项目一复杂,职责会失控、边界会模糊、维护会变得很痛苦。
FC 更适合做计算型、处理型、工具型功能,它更像“做一件事”的模块。
FB 更适合做带内部状态、可重复实例化的功能对象,例如电机、气缸、工位、顺控模块。
DB 是数据块,负责承载参数、状态、配方、记录等数据,也常作为 FB 的实例数据存储区。
FC 和 FB 的根本差别,不只是语法形式,而是这个功能是否需要保存自己的内部状态。
FB 和 DB 经常一起出现,因为带状态的功能对象必须有地方保存自己的专属数据。
好的模块化不是把代码随便拆开,而是让每个块有清晰的职责边界。
真正好的 PLC 程序,不只是局部逻辑写得清楚,还要整体结构组织得合理。
下载资料前请先绑定手机号码
对不起,请登录后再发表评论!

触屏端
扫一扫手机也能发信息
明扬工控商城-工控网-工控自动化真品,一站式专业服务!