迭代Twincat PLC中的结构(结构化文本)

时间:2017-09-22 17:25:28

标签: automation plc twincat structured-text

假设我有以下结构,其中包含有关Axis的信息:

TYPE AxisInfo :
STRUCT
    AxisStatus : ARRAY [0..3] OF BYTE;
    DriveStatis : ARRAY [0..3] OF BYTE;
    FeedRate : ARRAY [0..3] OF BYTE;
    Inputs : BYTE;
    Outputs : BYTE;
    Extra : BYTE;
    CurPosW: UDINT;             
    CurPosX: UDINT;
    CurPosY: UDINT;
    CurPosZ: UDINT;
    CurVelX: UDINT;
    CurVelY: UDINT;
    CurVelZ: UDINT;
    ComPos : UDINT;
    SetVel : UDINT;
    DacVel : UDINT;
    WinchErrPos : UDINT;
    XYZErrPos : UDINT;
    EnFaults : UDINT;
    ActFaults : UDINT; 
    BpFaults : UDINT;
    BpTimeLeft : UDINT;

此结构总共包含 82个字节。我将一直运行 8 这些结构(因为我有8轴)。这相当于 656字节与所有结构相结合。

现在,我有一个名为Buffer的变量:

Buffer: ARRAY [0..1023] OF BYTE;

我希望能够按顺序用8个结构中的每一个填充此缓冲区。例如:

Buffer[0] := AxisStatus[0]; //this is for the 1st axis
Buffer[1] := AxisStatus[1]; //this is for the 1st axis
….
Buffer[78] := BpTimeLeft; //this is for the 1st axis
…
Buffer[648] := BpFaults;
Buffer[652] := BpTimeLeft; //this is for the 8th axis

PLC上的ST中是否有一种方法可以迭代结构的成员,然后将这些成员放入缓冲区并确保它们位于适当的位置?你知道有什么技巧吗?

我问这个是因为我可以用以下方法来做,

For axisIndex:=1 to 8 DO
    Buffer[0] := AxisStatus[0];
    Buffer[1] := AxisStatus[1];
    …
   Buffer[78] := BpTimeLeft; this is for the 1st axis
END_FOR

但是我必须输出缓冲区需要分配给的每一行,然后在用第一个轴填充缓冲区之后必须做一些技巧,以避免它覆盖前82个字节。如果我将来更改结构的成员,必须有一些方法自动执行。

4 个答案:

答案 0 :(得分:0)

您是否尝试使用MEMCPY功能?这应该是更少的努力...... 您可以通过两种方式复制Struct和字节数组。使用一些索引和偏移指针。

答案 1 :(得分:0)

我建议在结构声明中使用{attribute 'pack_mode' := '1'},然后您可以使用MEMCPY轻松复制数据。

结构声明:

{attribute 'pack_mode' := '1'}
TYPE AxisInfo :
STRUCT

现在您可以将整个结构复制到字节数组,例如,或者只是一些变量。例如,要将Inputs从结构复制到字节数组,可以使用类似

的内容

MEMCPY(ADR(Buffer[2]), ADR(AxisStatus) + 12, 1)

将一个字节(AxisStatus的地址+ 12个字节,等于Inputs)复制到缓冲区[2]。如果复制多个字节,它会将它们复制到缓冲区[2],缓冲区[3],缓冲区[4]等等。

memcpy在这种情况下非常有用。

要将整个结构复制到缓冲区的开头,您可以 MEMCPY(ADR(Buffer), ADR(AxisStatus), SIZEOF(AxisStatus))

复制后面的下一个结构 MEMCPY(ADR(Buffer) + SIZEOF(AxisStatus), ADR(AxisStatus), SIZEOF(AxisStatus))

答案 2 :(得分:0)

老实说,我会避免遍历结构只是为了检索你需要的状态信息。如果你有100轴怎么办?

它不能很好地扩展。

如果改变程序的设计会怎样?

您可以设计一个功能块(让我们称之为AxisDevice),例如为轴建模。

AxisDevice将拥有在其中运行axis所需的所有功能块。然后,您会将AXIS_REF传递给AxisDevice,并且可以通过属性检索axis的状态信息(例如:getStatus:= AxisStatusStruct)。

通过这样做,您只需要决定并实施一次关于轴的信息" public"。

您的所有8 axis都可以是AxisDevice类型,并在需要时在运行时提供信息。

答案 3 :(得分:-1)

您无法保证字节位置和元素位置,因为编译器将根据硬件目标优化空间。你无法赢得这场战斗 - 你会反对结构的全部内容。

1)。您可以手动打包自己的字节数组以保证位置而不是使用结构(但是您可能也可以用机器语言编程,因为您正在击败高级编程...

BUFFER:= AxisInfo的ARRAY [0..7];

BUFFER [0]将是0轴, BUFFER [1]将是轴1, 等

2)。您可以将缓冲区定义为结构数组,并停止访问特定的内存位置(这取决于硬件/平台!)

3)。如果要将数据发送到HMI或某些不知道结构但只知道字节的设备,则会手动将结构元素映射到字节数组中的位置。这是现场总线通信的常规解决方案,如ModbusTCP。