2017-09-22 94 views
0

說我有填充有信息繞軸線以下結構:迭代中的TwinCAT PLC(結構化文本)結構

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軸)的。這相當於656字節與所有結構相結合。

現在,我有一個叫緩衝區變量:

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 

是否有ST PLC上的,這是一種迭代一個結構的成員,然後這些成員放入一個緩衝,並確保他們在正確的地方呢?你知道這樣做的任何技巧嗎?

我問這個,因爲我可以在下面的方法去做,

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個字節。如果我在將來更改結構體的成員,必須有一些方法來自動執行

+1

提示給你:指針,尺寸和Memcpy –

回答

-1

由於編譯器會根據硬件目標優化空間,因此無法保證字節位置和元素位置。你無法贏得這場戰鬥 - 你反對什麼是結構。

1)。你可以手動打包你自己的字節數組來保證位置,而不是使用結構(但是你也可以用機器語言編程,因爲你正在擊敗高級編程...

BUFFER:= ARRAY [0..7 ] AxisInfo作者;

BUFFER [0]將是軸0, 緩衝液[1]。將軸1, 等

2)。您可以將緩衝區定義爲您的結構陣列並停止訪問特定的內存位置(這將變成硬件/平臺相關的!)

3)。如果您要將數據發送到HMI或某個不知道結構但僅包含字節的設備,則會手動將結構元素映射到字節數組中的位置。這是現場總線通訊(如ModbusTCP)的常規解決方案。

+0

你可以保證結構中的字節位置。編譯器沒有對硬件進行優化。只有一個屬性「包裝模式」。您可以像規則一樣看到結構中的變量如何排列 –

+0

如果您從摩托羅拉切換到英特爾平臺,則可以進行字節交換。此外,編譯器會對齊你的字節,並可能會引入死亡字節,具體取決於你如何定義你的結構(DWORDS必須對齊到可被4整除的內存位置等)。 – Scott

+0

是的,這是TwinCat中的打包模式。 –

0

您是否嘗試使用MEMCPY功能?這應該是更少的努力... 您可以通過兩種方式複製Struct和Byte數組。用一些索引和偏移量指針。

+0

「如果我將來更改結構體的成員,必須有一些方法可以自動完成。?」 或者您甚至可以嘗試使用顯式內存功能將ARRAY OF STRUCT放置在同一內存(如字節陣列)中。 (%MB0,%MB *,...)(https://infosys.beckhoff.com/english.php?content=.../content/1033/tc3_plc_intro/18014398645980299.html&id=) – Tost

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))

0

老實說,我會避免通過結構循環只是檢索您需要的狀態信息。如果你有100軸?

它不好。

如果改變程序的設計,該怎麼辦?

您可以設計一個模擬軸的功能塊(我們稱之爲AxisDevice)。

AxisDevice將具有在其內部操作axis所需的所有功能塊。然後,您將通過AXIS_REFAxisDevice,並且可以通過屬性(例如:getStatus:= AxisStatusStruct)檢索axis的狀態信息。

通過這樣做,您只需決定並實施一次關於軸的哪些信息是「公開」的。

您所有的8 axis可能是AxisDevice類型,並在需要時在運行時提供信息。

+0

謝謝格式化Himanshu ;) –