博途的多重背景数据块, 类似于C# 中的单例模式. 通过一个静态变量即可访问到目标对象的所有方法.
UDT为用户定制数据类型, 可以使用结构体等方法, 使编程结构化和简单化.
以电机控制为例.
1, 先做一个电机控制的模版…
Input
IStartBtn Bool false 非保持
IStopBtn Bool false 非保持
IResetBtn Bool false 非保持
IEmergencyBtn Bool false 非保持
IContact Bool false 非保持
IAi1 Int 0 非保持
Output
QRunning Bool false 非保持
QMonitorStatus Int 0 非保持
QAo1 Real 0.0 非保持
Static
StRunFlag Bool false 非保持
StAlarmFlag Bool false 非保持
StMotorStatus Int 0 非保持
IEC_Timer_0_Instance TON_TIME 非保持
UpperiLimit Real 0.0 非保持
LowLimit Real 0.0 非保持
IEC_Timer_0_Instance_1 TON_TIME 非保持
Temp
Temp1 Real
REGION 电机启动信号
#StRunFlag := (#IStartBtn OR #StRunFlag) AND NOT #IStopBtn AND NOT #IEmergencyBtn AND NOT #StAlarmFlag;
//(启动按钮 或者 正在运行(自锁)) 且 没有按下停止 且没有按下急停 且没有报警
END_REGION
REGION 电机故障
#IEC_Timer_0_Instance_1(IN:=#StRunFlag AND #IStopBtn,
PT:=t#3s);
IF #IEC_Timer_0_Instance_1.Q THEN
#StAlarmFlag := 1;
END_IF;
#IEC_Timer_0_Instance(IN := (#StRunFlag AND NOT #IContact) OR (NOT #StRunFlag AND #IContact),
PT := t#3S); // 正在运行且接触器未吸合 或者 (没有正在运行且接触器吸合)
IF #IEC_Timer_0_Instance.Q THEN
#StAlarmFlag := 1;
END_IF;
END_REGION
REGION 电机状态
IF #StRunFlag AND NOT #StAlarmFlag AND #IContact THEN
#StMotorStatus := 1; //发出了启动信号, 而且没有报警, 且接触器吸合
ELSIF (#StRunFlag AND NOT #IContact) OR (NOT #StRunFlag AND #IContact) AND NOT #StAlarmFlag THEN
#StMotorStatus := 2; // 1,发出了启动信号, 但接触器没有吸合 2,没有发出启动, 且接触器吸合,且报警
ELSIF #StRunFlag AND NOT #IContact AND NOT #StAlarmFlag THEN
#StMotorStatus := 4; //启动了, 且 接触器没有吸合 且没有报警
ELSIF #StAlarmFlag THEN
#StMotorStatus := 8; //出现报警 停止发出启动信号
#StRunFlag := 0;
ELSE
#StMotorStatus := 0;
END_IF;
END_REGION
REGION 复位
IF #IResetBtn THEN
#StMotorStatus := 1;
#StAlarmFlag := 0;
END_IF;
END_REGION
REGION io映射
#QRunning := #StRunFlag;
#QMonitorStatus := #StMotorStatus;
END_REGION
REGION 模拟量转化
#Temp1 := NORM_X(MIN := 0, VALUE := #IAi1, MAX := 27648);
#QAo1 := SCALE_X(MIN := #LowLimit, VALUE := #Temp1, MAX := #UpperiLimit);
END_REGION
2, 再建一个电机控制集合FB2, 拖动FB1的电机控制结构进入, 选择多重背景数据块
这时, 3个电机的数据会出现在FB2的静态变量中, 而不是新建DB块.
3, 在PLC数据类型中, 建立一个UDT变量MotorUDT1
MotorUDT1使用结构体定义输入和输出变量:
I Struct
IStartBtn Bool false
IStopBtn Bool false
IResetBtn Bool false
IEmergencyBtn Bool false
IContact Bool false
IAi1 Int 0
Q Struct
QRunning Bool false
QMonitorStatus Int 0
QAo1 Real 0.0
4, 再在程序块中建立DB9: 电机控制集合1DB, 实现对UDT的实例化. 这里可以使用array of “motorUDT1”
在OB1中引用FB2 则 OB1会自动生成DB块 DB9
总结: 面向对象的三大特征是 继承 封装 多态 , 博途很好的完成了封装, 继承目前只有单例模式(背景数据块), 多态还做的很不好. 但是可以将字段定义为static, 用In和Out 做get set 将字段暴露出来. PLC编程的发展, 离主流面向对象语言还有很大的差距.
#include "pch.h"
extern "C" _declspec(dllexport) int Add(int a, int b)//extern 外部引用入口 dllexport 可以导出
{
return a + b;
}
public class CPPTest
{
[DllImport("MyFirstCPPDll.dll",EntryPoint="Add",CharSet =CharSet.Ansi,CallingConvention =CallingConvention.Cdecl)]
public static extern int Add(int a, int b);
}