找回密码
 立即注册
查看: 120|回复: 5

关于C语言如何实现PLC的FB功能

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:519
  • 最近打卡:2025-07-30 20:49:52

10

主题

79

回帖

137

积分

注册会员

积分
137
发表于 2025-7-6 11:21:13 | 显示全部楼层 |阅读模式
有没有C语言大佬,我想在C语言中实现一个PLC的TON功能应该如何实现  用typedef吗?
回复

使用道具 举报 送花

3

主题

252

回帖

-785

积分

等待验证会员

积分
-785
发表于 2025-7-6 11:23:00 | 显示全部楼层
关于C语言如何实现PLC的FB(功能块)功能,特别是实现TON(延时接通)功能,这是一个在工业控制领域中常见的需求。PLC(可编程逻辑控制器)通常使用结构化文本(ST)、梯形图(LAD)、功能块图(FBD)等语言进行编程,但若希望在C语言中模拟或实现类似的功能块行为,可以采用面向对象的思想和结构体(struct)结合函数指针的方式进行封装。

对于TON功能的实现,其基本逻辑是:当输入信号为真时,开始计时,经过设定时间后输出信号变为真。该功能块通常包含以下状态:
IN:输入信号
PT:预设时间(如10秒)
ET:已用时间(Elapsed Time)
Q:输出信号
BI:当前是否正在计时

在C语言中,可以通过定义一个结构体来表示这个功能块,并通过函数对其进行操作。下面是一个简单的示例实现:
  1. c
  2. include
  3. include  // 用于sleep函数(仅作演示)
  4. // 定义TON功能块结构体
  5. typedef struct {
  6.     int IN;         // 输入信号
  7.     int PT;         // 预设时间(单位:秒)
  8.     int ET;         // 已用时间
  9.     int Q;          // 输出信号
  10.     int BI;         // 是否正在计时
  11. } TON;
  12. // 初始化TON功能块
  13. void TONInit(TON ton) {
  14.     ton->IN = 0;
  15.     ton->PT = 0;
  16.     ton->ET = 0;
  17.     ton->Q = 0;
  18.     ton->BI = 0;
  19. }
  20. // 更新TON功能块状态
  21. void TONUpdate(TON ton, int input, int timeStep) {
  22.     if (input == 1) {
  23.         if (ton->BI == 0) {
  24.             ton->BI = 1;
  25.             ton->ET = 0;
  26.         }
  27.         ton->ET += timeStep;
  28.         if (ton->ET >= ton->PT) {
  29.             ton->Q = 1;
  30.         }
  31.     } else {
  32.         ton->BI = 0;
  33.         ton->ET = 0;
  34.         ton->Q = 0;
  35.     }
  36. }
  37. // 示例主函数
  38. int main() {
  39.     TON ton;
  40.     TONInit(&ton);
  41.     // 模拟输入信号变化
  42.     for (int i = 0; i < 15; i++) {
  43.         if (i < 5) {
  44.             ton.IN = 1;
  45.         } else {
  46.             ton.IN = 0;
  47.         }
  48.         TONUpdate(&ton, ton.IN, 1); // 每次更新时间为1秒
  49.         printf("Time: %d, IN: %d, ET: %d, Q: %d\n", i, ton.IN, ton.ET, ton.Q);
  50.         sleep(1); // 模拟实际运行中的时间间隔
  51.     }
  52.     return 0;
  53. }
复制代码

说明:
使用 typedef struct 定义了一个名为 TON 的结构体,用于保存TON功能块的状态。
TONInit 函数用于初始化功能块的各个成员变量。
TONUpdate 是功能块的核心逻辑,根据输入信号 IN 判断是否开始计时,并更新 ET 和 Q。
在 main 函数中,我们模拟了输入信号的变化,并通过 sleep 模拟时间步长,以展示功能块的行为。

进阶建议:
可以将 TONUpdate 封装为函数指针,实现更灵活的多任务处理。
若需支持多个TON实例,可以使用数组或链表管理多个功能块。
在嵌入式系统中,应避免使用 sleep,而改用定时器中断或硬件计时器来驱动更新。

综上所述,虽然C语言本身不直接支持PLC的FB语法,但通过结构体和函数封装,可以高效地实现类似功能块的行为。希望以上内容对您有所帮助。

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:252
  • 最近打卡:2025-07-30 08:55:29
已绑定手机

78

主题

2286

回帖

5206

积分

荣誉版主

无情的代码机器

积分
5206
发表于 2025-7-6 15:04:07 | 显示全部楼层
PLC没用过,能用大白话描述下需求吗。
延时触发?
简单搞个定时器设flag在main函数里执行?
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:519
  • 最近打卡:2025-07-30 20:49:52

10

主题

79

回帖

137

积分

注册会员

积分
137
发表于 2025-7-7 16:39:14 | 显示全部楼层
比如我新建一个子函数,但这个子函数可以被调用很多次,可以用不同的命名,命名完成后可以用之前命名的方式调用结构体。
截图202507071639036133.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:519
  • 最近打卡:2025-07-30 20:49:52

10

主题

79

回帖

137

积分

注册会员

积分
137
发表于 2025-7-7 16:40:54 | 显示全部楼层
erci*** 发表于 2025-7-6 15:04
PLC没用过,能用大白话描述下需求吗。
延时触发?
简单搞个定时器设flag在main函数里执行? ...

如楼下回复。想将下面的功能用C语言实现,不知道能否实现。

点评

就是C的结构体嘛?成员包含一般属性和函数指针。函数指针可以赋值同一个,也可以每个实例不同。  详情 回复 发表于 2025-7-7 16:57
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:252
  • 最近打卡:2025-07-30 08:55:29
已绑定手机

78

主题

2286

回帖

5206

积分

荣誉版主

无情的代码机器

积分
5206
发表于 2025-7-7 16:57:06 | 显示全部楼层
King*** 发表于 2025-7-7 16:40
如楼下回复。想将下面的功能用C语言实现,不知道能否实现。

就是C的结构体嘛?成员包含一般属性和函数指针。函数指针可以赋值同一个,也可以每个实例不同。
  1. #include <stdio.h>
  2. #include <math.h>
  3. // 定义函数指针类型
  4. typedef int (*MathOperation)(int, int);
  5. typedef void (*PrintFunction)(const char*);
  6. // 定义包含数字成员和函数指针的结构体
  7. struct Calculator {
  8.     int id;                 // 数字成员
  9.     float version;          // 数字成员
  10.     MathOperation operate;  // 函数指针成员
  11.     PrintFunction printer;  // 函数指针成员
  12. };
  13. // 各种数学运算函数
  14. int add(int a, int b) {
  15.     return a + b;
  16. }
  17. int subtract(int a, int b) {
  18.     return a - b;
  19. }
  20. int multiply(int a, int b) {
  21.     return a * b;
  22. }
  23. // 打印函数
  24. void fancyPrint(const char* text) {
  25.     printf("✨ %s ✨\n", text);
  26. }
  27. void simplePrint(const char* text) {
  28.     printf("%s\n", text);
  29. }
  30. int main() {
  31.     // 创建结构体实例并初始化
  32.     struct Calculator calc1 = {
  33.         .id = 101,
  34.         .version = 1.5f,
  35.         .operate = multiply,   // 指向乘法函数
  36.         .printer = fancyPrint   // 指向花式打印函数
  37.     };
  38.    
  39.     struct Calculator calc2;
  40.     calc2.id = 102;
  41.     calc2.version = 2.0f;
  42.     calc2.operate = add;        // 指向加法函数
  43.     calc2.printer = simplePrint; // 指向简单打印函数
  44.    
  45.     // 使用结构体成员
  46.     int result = calc1.operate(5, 3);
  47.     calc1.printer("Multiplication Result:");
  48.     printf("5 * 3 = %d\n", result);
  49.    
  50.     // 动态切换函数指针
  51.     calc2.printer("Switching to subtraction...");
  52.     calc2.operate = subtract;  // 改为指向减法函数
  53.    
  54.     result = calc2.operate(10, 4);
  55.     calc2.printer("Subtraction Result:");
  56.     printf("10 - 4 = %d\n", result);
  57.    
  58.     // 创建结构体数组
  59.     struct Calculator calcs[] = {
  60.         {201, 1.1f, add, simplePrint},
  61.         {202, 1.2f, multiply, fancyPrint}
  62.     };
  63.    
  64.     calcs[0].printer("Array Calculator:");
  65.     printf("7 + 8 = %d\n", calcs[0].operate(7, 8));
  66.    
  67.     return 0;
  68. }
复制代码




三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-7-30 23:41 , Processed in 0.115498 second(s), 83 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表