0

假设我有以下结构,其中填充了有关轴的信息:

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

4 回答 4

0

您是否尝试使用 MEMCPY 功能?那应该少得多……您可以以两种方式复制结构和字节数组。带有一些索引和偏移量指针。

于 2017-09-25T10:21:04.687 回答
0

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

结构声明:

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

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

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

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

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

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

在它之后复制下一个结构 MEMCPY(ADR(Buffer) + SIZEOF(AxisStatus), ADR(AxisStatus), SIZEOF(AxisStatus))

于 2017-10-02T06:34:01.990 回答
0

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

它不能很好地扩展。

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

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

AxisDevice将具有在axis其中操作所需的所有功能块。然后,您将传递一个AXIS_REFto并可以通过属性检索感谢AxisDevice的状态信息(例如:getStatus := AxisStatusStruct)。axis

通过这样做,您只需决定并实施有关轴的哪些信息是“公开的”。

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

于 2017-11-19T17:29:53.267 回答
-1

您不能保证字节位置和元素位置,因为编译器会根据硬件目标优化空间。你无法赢得这场战斗——你要对抗结构的全部意义。

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

缓冲区:= 轴信息的数组 [0..7];

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

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

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

于 2017-09-23T00:10:01.847 回答