E/A Mapping von/ zu Array of DWORD, Problem bei Offset Ermittlung

Jochen Öhler

Level-1
Beiträge
5
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

als Quereinsteiger aus S7, sitze ich aktuell an einem Programmteil
welcher mir SPS-Eingänge auf ein Array of DWORD und
Daten aus einem Array of DWord auf Ausgänge schreiben soll.

Nach einigen Selbstversuchen / Online-Suchvorgängen bin ich beim unten aufgeführten Code angekommen.
Dieser kopiert mir zwar das erste DWord (%ID500) auf das Read_SPS_Array[0], jedoch hapert es
anschließend am Offset für den 2ten Lesevorgang in der Schleife ( %ID 501 auf Array [1].
(Rot markiert)

Variablendeklaration:
VAR
Read_SPS_Loop: INT;
END_VAR
VAR_IN_OUT
Read_SPS_Array: ARRAY[0..25] OF DWORD;
END_VAR
VAR
Read_SPS_Offset: Pointer to DWORD;
END_VAR
VAR_INPUT
Read_SPS_Startadresse: DWORD; <-- anparametriert mit "%ID500"
END_VAR

Programm:

// Lese 16 DWord Eingänge ab Startadresse und übertrage in Array 0-15
Read_SPS_Offset:= ADR (Read_SPS_Startadresse);

FOR Read_SPS_Loop:= 0 TO 15 DO
Read_SPS_Array[Read_SPS_Loop]:= Read_SPS_Offset^;
Read_SPS_Offset:= Read_SPS_Offset + SIZEOF(DWORD);
END_FOR


// Test Ausgangswert schreiben
Write_SPS_Array[0]:= 5;

// Lese Array 0-15 und schreibe 16 DWORD Ausgänge ab Startadresse
Write_SPS_Offset:= ADR (Write_SPS_Startadresse);

FOR Write_SPS_Loop:= 0 TO 15 DO
Write_SPS_Offset^:= Write_SPS_Array[Write_SPS_Loop];
Write_SPS_Offset:= Write_SPS_Offset + SIZEOF(DWORD);
END_FOR

Würde mich freuen, wenn mir hier jemand mit dem Offset weiterhelfen könnte
 
Zuletzt bearbeitet:
Was genau hast Du den im Einatz (TwinCAT 2/3, Wago e!Cockpit, Codesys)?
Wieso möchtest Du direkt mit der Adresse arbeiten? In Codesys und seinen Derivaten kann man doch schön mit %I* oder %Q* arbeiten und das ganze dann bei der Hardware einer Variable zuweisen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Im Einsatz habe ich Codesys (Control WinV3).
Der Baustein soll später multiinstanzfähig sein und für jedes Gerät 1mal aufgerufen werden.
Die zugehörigen E/As werden nicht über HW-Teilnehmer geschrieben.

BSP. 01R01
Lese ab %IX 2000.0 bis 2063.7 in E_Array [0..16]
Schreibe "A_Array[0..16] auf Ausgang %QX 2000.0 bis 2063.7.

Daher der Ansatz mit Startadresse und DWORD-weise übertragung
 
Hallo Jochen,

für den Fall dass du noch fest steckst:

SIZEOF(DWORD) führt bei mir unter anderem zur Fehlermeldung "Operand wird erwartet". Erwarten würde ich als Wert 4 Byte. Erfolg in der Hinsicht bringt vielleicht SIZEOF(Write_SPS_Offset^), in der Form habe ich zumindest das Offset ermitteln können.
 
Hallo Jochen,
irgendwie blicke ich immer noch nicht ganz durch was Du vor hast.
Soweit ich das richtig verstehe möchtest Du einen FB erzeugen von dem Du mehrere Instanzen aufrufst. In diesem FB möchtest Du lesend und schreibend auf Teile des Prozessabbildes zugreifen, aber wenn das nicht an Hardwareteilnehmer gehen soll, warum soll es dann ins Prozessabbild?
 
@ MaReKa: Habe den Code dementsprechend angepasst, aber am Ergebniss selbst hat sich nichts geändert. Der Code kopiert weiterhin nur das erste DWORD.
 
Mein Codesys Unterbau ist wacklig also möge man mich aufklären wenn ich falsch liege:

Kann es sein dass dein Pointer auf den Speicher der Variable "Read_SPS_Startadresse" zeigt und nicht das eigentliche Eingangsdoppelwort %ID500?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
DING DING DING

Hattest Recht MaReKa, es lag an der internen Variable.
Mit %ID 500 bzw. %QD500 direkt im code funktioniert es

// Lese 16 DWord Eingänge ab Startadresse und übertrage in Array 0-15
Read_SPS_Offset:= ADR (%ID500);

FOR Read_SPS_Loop:= 0 TO 15 DO
Read_SPS_Array[Read_SPS_Loop]:= Read_SPS_Offset^;
Read_SPS_Offset:= Read_SPS_Offset + SIZEOF(DWORD);
END_FOR


Zufällig eine Idee wie ich das mit der In Variable als Startadresse trotzdem hinbekomme?
Eventl. Vorgabe als INT-Wert, addieren zu %ID0 o.ä. ?
 
Beim Aufruf den Pointer übergeben?

VAR_INPUT
Read_SPS_Startadresse: PONTER TO DWORD;
END_VAR

Bin mir nicht sicher ob das "sauberer" Code wäre, vielleicht findet sich noch eine andere Lösung.
 
Ok, zum Abschluss nocheinmal der fertige Code inkl. Aufruf


Aufruf.PNG
VAR
Read_SPS_Loop: INT;
END_VAR
VAR_IN_OUT
Read_SPS_Array: ARRAY[0..30] OF DWORD;
END_VAR
VAR
Read_SPS_Offset: Pointer to DWORD;
END_VAR
VAR_INPUT
Read_SPS_Startadresse: POINTER TO DWORD;
END_VAR


VAR
Write_SPS_Loop: INT;
END_VAR

VAR_IN_OUT
Write_SPS_Array: ARRAY[0..30] OF DWORD;
END_VAR

VAR
Write_SPS_Offset: Pointer to DWORD;
END_VAR

VAR_INPUT
Write_SPS_Startadresse: POINTER TO DWORD;
END_VAR
_____________________________
// Lese 16 DWord Eingänge ab Startadresse und übertrage in Array 0-15
Read_SPS_Offset:= Read_SPS_Startadresse ;

FOR Read_SPS_Loop:= 0 TO 15 DO
Read_SPS_Array[Read_SPS_Loop]:= Read_SPS_Offset^;
Read_SPS_Offset:= Read_SPS_Offset + SIZEOF(DWORD);
END_FOR


// Lese Array 0-15 und schreibe 16 DWORD Ausgänge ab Startadresse
Write_SPS_Offset:= Write_SPS_Startadresse;

FOR Write_SPS_Loop:= 0 TO 15 DO
Write_SPS_Offset^:= Write_SPS_Array[Write_SPS_Loop];
Write_SPS_Offset:= Write_SPS_Offset + SIZEOF(Write_SPS_Offset^);
END_FOR

Danke für die Hilfe
 
Zurück
Oben