In Arrays und Strukturen denken

vollmi

Level-3
Beiträge
5.436
Reaktionspunkte
1.410
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi zusammen

Ich bin ja recht neu in Codesys und bin etwas am knorzen :)

HAbe mit Wago gerade eine Modbus verbindung aufgebaut und die funktioniert auch. Jetzt ist es aber so das Modbus ja 16 Bit wörter überträgt. Auf dem Slave aber wieder 32 Bit elemente verwendet werden. Also 2 Worte im Modbus ist ein Register im Slave. Und so möchte ich bei mir im Master auch drauf zugreifen.

Code:
TYPE typModbus_Slave :
STRUCT
    Write_Data            :    ARRAY[0..124] OF WORD; (* Maximum 125 Wörter pro Telegramm.*)
END_STRUCT
END_TYPE

Ich möchte jetzt gerne z.B. DATA was ein DWORD ist auf Das 10. Register schreiben was im Array ja das 20. WORD ist. Aber ohne das DWORD in WORD zu wandeln.

Wie gehe ich da am besten vor?

mfG René
 
Ob es der beste Weg ist, weiß ich nicht, aber folgender Vorschlag:

%MD0:=DATA; (* Zuweisung auf das Merkerdoppelwort 0 *)

Write_Data[20] :=%MW0; (*Merkerdoppelwort Null besteht aus Merkerwort0 ...*)

Write_Data[21] :=%MW1; (* ... und Merwort 1 *)


Gruß

KvT

P.S.: Kannst Dir ja ne Funktion daraus basteln...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn kein BYTE oder WORD Swapping benötigt wird, dann geht's vielleicht einfacher: auf die selbe Adresse wie die 125xWORD Eingangsvariable wird eine exakte Nachbildung der Daten Struktur des Slaves deklariert, also z.B.
Code:
ModbusSlave AT%IW0: typModbus_Slave;
ModbusSlaveRegister AT%IW0: ARRAY[1..64] OF DWORD;
Durch Memory Sharing sind die Daten im richtigen Format an der richtigen Stelle.

Gruß witkatz
 
Ist das %IW0 dann ein Instanzwort des Bausteins? Also von ausserhalb dem Funktionsbausteins nicht mehr zu überschreiben?
Würde mir besser passen als auf Merker zu schreiben welche dann wieder absolut adressen sind welche von Extern überschrieben werden können.

mfG René
 
Was ist ein Instanzwort?
"AT %IW0" ist eine Adressangabe in der Variablendeklaration: die Variable ist an Adresse 0 gebunden. Wenn beide Variablen an die selbe Adresse gebunden sind, dann teilen sie sich den Speicher.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
"Instanzwort" klingt nach Siemens. Ich nehme an, dass damit eine innerhalb des FB's deklarierte Variable gemeint ist, so dass jede FB-Instanz ihre eigene Variable hat. Das ist bei absolut adressierten Variablen im /I/Q/M-Bereich aber nicht so. Soll die Variable im FB untergebracht werden, bleibt eigentlich nur noch das Arbeiten mit einem Zeiger.
Code:
TYPE arWordData:
   ARRAY[0..124] OF WORD;
END_TYPE
 
TYPE arDWordData:
   ARRAY[0..61] OF DWORD;
END_TYPE
 
(* im FB *)
VAR
   WordData:arWordData;
   DWordData:POINTER TO arDWordData;
END_VAR
 
(* und im Code*)
DWordData:=ADR(WordData);
 
"Instanzwort" klingt nach Siemens. Ich nehme an, dass damit eine innerhalb des FB's deklarierte Variable gemeint ist, so dass jede FB-Instanz ihre eigene Variable hat. Das ist bei absolut adressierten Variablen im /I/Q/M-Bereich aber nicht so.

Genau den absoluten Adressen will ich aus dem Weg gehen. Ich will ja die Bausteine jederzeit in einem anderen Projekt hinterlegen können ohne auf absolute Adressbereiche aufpassen zu müssen.

Soll die Variable im FB untergebracht werden, bleibt eigentlich nur noch das Arbeiten mit einem Zeiger.
Code:
TYPE arWordData:
   ARRAY[0..124] OF WORD;
END_TYPE
Okay die Typdeklaration ist mir klar.

Aber das nächste noch nicht so richtig:

Was genau passiert hier?
Code:
(* im FB *)
VAR
   WordData:arWordData;  (*das ist mir nicht klar*)
   DWordData:POINTER TO arDWordData;  (*Und das*)
END_VAR
Und hier wird Die Wort Struktur auf Doppelwortstruktur kopiert?
Heisst also ich kann so in der wortstruktur werte ändern und die landen in der Doppelwortstruktur. Aber umgekehrt natürlich nicht oder?
Code:
(* und im Code*)
DWordData:=ADR(WordData);
Sorry im Codesys bin ich wirklich noch blutiger Anfänger. Ich war selbst in Siemens noch nicht so wirklich Pointerfest.

mfG René
 
Ok, dann etwas ausführlicher.
Du hast folgenden Typ definiert:
Code:
TYPE typModBus_Slave
STRUCT
   Write_Data:ARRAY[0..124] OF WORD;
END_STRUCT
END_TYPE
In einem FB legst Du eine Variable dieses Typs an.
Code:
VAR
   ModBus_Slave:typModBus_Slave;
END_VAR
Für einen DWORD-weisen Zugriff brauchst Du folgenden Datentyp:
Code:
TYPE typModBus_Regs
STRUCT
   Write_Data:ARRAY[0..61] OF DWORD;  (* das 125. Wort fällt hier unter den Tisch *)
END_STRUCT
END_TYPE
Im FB legst Du einen Zeiger auf ein "typModBus_Regs" an,
Code:
VAR
   ModBus_Regs:POINTER TO typModBusRegs;
END_VAR
der dann auf die Speicheradresse zeigen soll, an der "ModBus_Slave" steht:
Code:
ModBus_Regs:=ADR(ModBus_Slave);  (* hier werden nicht die Daten kopiert, sondern der Zeiger "ModBus_Regs" erhält die Speicheradresse von "ModBus_Slave" *)
(* Um auf die Daten zuzugreifen, muss der Zeiger dereferenziert werden (mit dem ^) *)
ModBus_Regs^.Write_Data[12]:=1;  (* schreibt in ModBus_Slave.Writ_Data[24] und [25] *)
 
Zurück
Oben