IEC 61131-3(ST)与C/C++混合调用
IEC 61131-3(ST)程序可以调用 C/C++ 用户库中的函数或功能块,C/C++ 用户库也可以通过 IEC 符号接口访问 ST 侧定义的全局变量、结构体、程序实例和功能块实例。
本文以一个混合调用工程为例,说明如何搭建 ST -> C/C++ 功能块 -> IEC 符号/IEC 功能块 的调用链,并说明接口更新、构建、调试和常见问题处理方式。
适用场景
| 场景 | 说明 |
|---|---|
| ST 调用 C/C++ 算法 | 在 ST 主程序中调用 C/C++ 用户库函数或功能块 |
| C/C++ 读取 PLC 数据 | 在 C/C++ 中读取 GVL、结构体或程序实例数据 |
| C/C++ 回调 IEC POU | 在 C/C++ 中调用 ST 实现的功能块或程序入口 |
| 跨语言调试 | 在 ST 与 C/C++ 源码之间设置断点并查看调用栈 |
注意
混合调用适合封装清晰的算法或底层逻辑。建议将跨语言访问集中在少量 C/C++ 功能块中,避免在多个模块中分散读写同一批 IEC 符号。
工程组成
混合调用工程通常包含 IEC 程序、IEC 类型定义、C/C++ 用户库和自动生成的 IEC 符号接口。
示例工程结构如下:
| 目录或文件 | 作用 |
|---|---|
PROGRAM/ | IEC 程序、功能块和数据类型定义 |
MODULES/clib1/ | C/C++ 用户库,示例中提供 Cfb1 功能块 |
MODULES/clib2/ | C/C++ 用户库,示例中提供 FB_CALLER 功能块 |
MODULES/iec_interface.h | IDE 自动生成的 IEC 符号映射头文件 |
CONFIG/tasks/ | 任务配置,决定 ST 主程序的周期执行方式 |
推荐操作顺序
混合调用涉及 ST、C/C++ 用户库、全局变量和自动生成头文件。建议先把参与调用的 POU 和变量准备完整,再编写 ST 主程序调用语句。这样可以避免在程序中写完调用后,因为类型、接口或实例缺失而反复修改。
推荐顺序如下:
- 创建或确认 C/C++ 用户库。
- 在 C/C++ 用户库中创建需要导出的函数或功能块 POU,并选择实现语言。
- 创建 ST 侧需要被 C/C++ 回调的 IEC POU。
- 创建 GVL 全局变量或程序变量,用于保存要访问的 IEC 对象和功能块实例。
- 生成 C/C++ 用户库接口代码。
- 生成或刷新
iec_interface.h。 - 在 ST 主程序中声明实例并编写调用语句。
- 在 C/C++ 实现代码中引用
iec_interface.h并访问 IEC 符号。 - 编译 C/C++ 用户库和 PLC 工程。
- 连接目标 PLC 或模拟器进行调试验证。
示例中 涉及的 POU 和变量如下,用户可以按自己的业务名称替换:
| 对象 | 类型 | 实现语言 | 用途 |
|---|---|---|---|
DEMO_PLC_PRG1 | PROGRAM | ST | 周期任务入口,负责调用 C/C++ 功能块 |
FB_CALLER | FUNCTION_BLOCK | C++ | 被 ST 调用,并在内部访问 IEC 符号 |
ST_POU1 | FUNCTION_BLOCK | ST | 被 C/C++ 通过 IEC 调用入口回调 |
Cfb1 | FUNCTION_BLOCK | C 或 C++ | 被另一个 C/C++ 功能块调用 |
GVL_var3 | 全局变量 | IEC | 示例中类型为 ST_POU1,供 C/C++ 访问和调用 |
GVL_var5 | 全局变量 | IEC | 示例中类型为 Cfb1,供 C/C++ 调用另一个 C/C++ FB |
提示
先准备 POU 和全局变量,再写 ST 主程序调用,可以让编辑器补全、接口生成和编译检查更早发现问题。