Indirekte Adressierung von Eingängen

Bubi

Member
Beiträge
10
Punkte Reaktionen
0
Zuviel Werbung?
->Hier kostenlos registrieren
Hallo, ich würde gerne wissen ob es möglich ist eingänge indirekt zu adressieren.

Ich bin in einem FC und habe eine Temp Vari

VAR_TEMP
EADR : WORD ;
END_VAR

und wie ich es kenne müsste es so aussehen :

L EW[#EADR]

Dieß geht aber nicht, kann mir jemand sagen wie es genau geht, bzw ob es geht ?
 
OP
B

Bubi

Member
Beiträge
10
Punkte Reaktionen
0
Ich will ganz schlicht zum beispiel 20 Eingangswörter in ein Array im db schreiben :D

AUF DB 56
L 0.000000e+000
T #DBADR
L 0.000000e+000
T #EADR
M001: NOP 0
L EW [#EADR]
T DBW [#DBADR]
L #EADR
L 2.000000e+001
>R
BEA
L #EADR
L 2.000000e+000
+R
T #EADR
L #DBADR
L 2.000000e+000
+R
T #DBADR
SPA M001




EADR ist ein DWORD (Eingangsadresse)
DBADR ist ein DWORD (DBadresse)
 
Zuletzt bearbeitet:

borromeus

Well-known member
Beiträge
2.270
Punkte Reaktionen
329
1. mit einer REAL-Zahl geht das nicht.... DINT ist geboten
2. Du musst vor
L EW [#EADR]
die Adresse um 3 Bits nach links schieben, da die Adressierung in Step7 bitgranulat ist.
3. Dein Vorhaben geht mit dem SFC20, BLOCK_MOVE, einfacher.
 

borromeus

Well-known member
Beiträge
2.270
Punkte Reaktionen
329
Das in der Klammer [ ] darf keine Realzahl sein.
Das ist ja die Adresse, und die hat "intern" das Format ADRESSBYTE.BIT

L P#3.2
LAR1
U E [AR1, P#0.0]

"lädt" E3.2

Die Bitadresse steht in den letzten drei Bits des Zeigers. Darum muss man wenn man eine Byteadresse lädt diese um 3 Bits nach links verschieben!
Klar?
 
OP
B

Bubi

Member
Beiträge
10
Punkte Reaktionen
0
Ah danke :) Hatte auch noch einen fehler drin, BEA statt BEB :D

AUF DB 56
L 0
SLW 3
T #DBADR
L 0
SLW 3
T #EADR
M001: NOP 0
L EW [#EADR]
T DBW [#DBADR]
L #EADR
SRW 3
L 38
>I
BEB
L #EADR
SRW 3
L 2
+I
SLW 3
T #EADR
L #DBADR
SRW 3
L 2
+I
SLW 3
T #DBADR
SPA M001


So geht es nun :)
Wobei ich noch am versuchen bin ob ich es einfacher hinbekomme.
 

Flux

Well-known member
Beiträge
314
Punkte Reaktionen
11
Zuviel Werbung?
->Hier kostenlos registrieren
Nimm doch LOOP, der prüft automatisch ob dein Schleifenzähler <> 0 ist und dekrementiert diesen, und springt danach zurück an den Schleifenanfang.

Folgender Code überbügelt einen DB mit Nullen
Code:
      AUF   "MyDB"

      L     P#0.0
      T     #MyDB_INDEX_DW

      L     20                          //beliebig
back: T     #MyDB_ANZ_DW

      L     0
      T     DBD [#MyDB_INDEX_DW]

//Index erhöhen
      L     #MyDB_INDEX_DW
      L     P#4.0
      +D    
      T     #MyDB_INDEX_DW

      L     #MyDB_ANZ_DW
      LOOP  back //Schleifenzähler dekrementieren, <> 0?, dann springe zu [I]back[/I]
 
OP
B

Bubi

Member
Beiträge
10
Punkte Reaktionen
0
Flux ja mit einem LOOP geht es auch.

Meine derzeitige Version sieht so aus :
FUNCTION FC 1 : VOID
TITLE =
//Baustein zum Einlesen von Eingangswörtern und Speichern in einem Datenbaustein.
//Die Nummer des DB´s, das erste Eingangswort, die Anzahl der einzelesenden Wörter
//und das erste Speicherwort werden im INT Format von aussen bestimmt.
VERSION : 0.1


VAR_INPUT
StartWORD_EINGANG : INT ; //Ab (inklusive) diesem Eingangswort werden die Eingänge eingelesen.
StartWORDinDB : INT ; //Ab (inklusive) diesem Word werden die Eingänge im Datenbaustein gespeichert.
DB_Nummer : INT ; //In diesen Datenbaustein werden die Eingangswörter geschrieben.
Anzahl_WORD : INT ; //Die Gesamtanzahl der Einzulesenden Eingangswörter.
END_VAR
VAR_TEMP
DBADR : DWORD ;
EADR : DWORD ;
DBNRW : WORD ;
Anzahl : INT ;
END_VAR
BEGIN
NETWORK
TITLE =


L #DB_Nummer;
T #DBNRW;
AUF DB [#DBNRW];
L #StartWORDinDB;
SLW 3;
T #DBADR;
L #StartWORD_EINGANG;
SLW 3;
T #EADR;
M001: NOP 0;
L EW [#EADR];
T DBW [#DBADR];
L #Anzahl_WORD;
+ -1;
L 2;
*I ;
L #StartWORD_EINGANG;
+I ;
T #Anzahl;
L #EADR;
SRW 3;
L #Anzahl;
>=I ;
BEB ;
L #EADR;
SRW 3;
L 2;
+I ;
SLW 3;
T #EADR;
L #DBADR;
SRW 3;
L 2;
+I ;
SLW 3;
T #DBADR;
SPA M001;

Nachteil ist ich kann nur Wörter einlesen, keine Doppelwörter.
Entweder erstelle ich mir noch einen der nur doppelwörter einließt oder ich lege noch eine in var an über die ich bestimme ob ich word oder doppelwort habe.
 

hovonlo

Well-known member
Beiträge
242
Punkte Reaktionen
78
Warum das so ist, das kann nur Siemens beantworten. Aber dieses Forum und die Hilfe des Simatic Managers helfen weiter:

Forum: http://www.sps-forum.de/showthread.php/12923-Any-Zeiger-f%FCr-Datentypen

Und aus der Simatic Hilfe:
Speicherindirekte Adressierung
Programmanweisungen, die mit der speicherindirekten Adressierung arbeiten, setzen sich zusammen aus einer Operation, einem Operandenkennzeichen und einer [Adresse] (die Adresse muß in eckigen Klammern angegeben werden). Je nach Operandenkennzeichen wertet die Operation die Daten, die an der angegebenen Adresse abgelegt sind, als Pointer im Wort- bzw. im Doppelwortformat aus. Das zu wählende Pointerformat ist abhängig von dem verwendeten Operanden. Der vollständige Operand der Daten besteht aus einem Operandenkennzeichen und einem Pointer (siehe folgende Beispiele). Der Vorteil der indirekten Adressierung ist, daß Sie den Operanden der Anweisung während der Programmbearbeitung dynamisch modifizieren können.

Bei der speicherindirekten Adressierung besteht der Operand aus den beiden folgenden Teilen:

1. Operandenkennzeichen

· Bei Bits, die von Bitverknüpfungsoperationen angesprochen werden, können Sie die Operandenkennzeichen E, A, M, L, DIX oder DBX verwenden.

· Bei Bytes, Wörtern und Doppelwörtern, die von Ladeoperationen angesprochen werden, können Sie die Speicherbereiche E, A, M, L, D und PE verwenden, um die folgenden Operandenkennzeichen anzugeben: EB, EW, ED, DBB, DBW, DBD, DIB, DIW, DID, PEB, PEW, PED, etc.

· Bei Bytes, Wörtern und Doppelwörtern, die von Transferoperationen angesprochen werden, können Sie die Speicherbereiche E, A, M, L, DB, DI und PA verwenden, um die folgenden Operandenkennzeichen anzugeben: EB, EW, ED, DBB, DBW, DBD, DIB, DIW, DID, PAB, PAW, PAD, etc.

· Zum Adressieren von Zeiten, Zählern oder Bausteinen verwenden Sie die Bereichskennungen T, Z, DB, DI, FB, FC.

2. Die Adresse von Pointern im Wort- oder Doppelwortformat wird in eckigen Klammern "[ ]" angegeben:

· Pointer im Wortformat - Ein Wort, das die Nummer einer Zeit (T), eines Zählers (Z), eines Datenbausteins (DB, DI) oder eines Codebausteins (FC, FB) angibt. Bei einem Pointer im Wortformat handelt es sich um eine Dezimalzahl.

· Pointer im Doppelwortformat - Ein Doppelwort, das in diesem Fall die genaue Adresse eines Bits, Bytes, Worts oder Doppelworts angibt. Ein Doppelwort hat folgendes Pointerformat: P#Byte.Bit.

· Der Pointer muß für die speicherindirekte Adressierung in einem der folgenden Bereiche gespeichert werden:

· M - Merker

· L - Lokaldaten

· D - Datenbaustein (DB oder DI)

· STAT - Statische Daten (nicht bei multiinstanzfähigen Bausteinen)

Hinweis

Wenn Sie auf ein Byte, Wort oder Doppelwort zugreifen möchten, das über speicherindirekte Adressierung angesprochen wird, vergewissern Sie sich zunächst, daß die Bitnummer des Pointers im Doppelwortformat 0 ist.

Beispiel für einen Pointer im Wortformat:

L 5 //Lade den Wert des Pointers in AKKU 1.
T MW2 //Transferiere den Pointer nach MW2.
L T [MW2] //Lade den aktuellen Wert der Zeit T5 in AKKU 1.
Beispiel für einen Pointer im Doppelwortformat:

L P#8.7 //Lade den Wert des Pointers in AKKU 1.
T MD2 //Transferiere den Pointer nach MD2.
U E [MD2] //Frage den Signalzustand an Eingang E 8.7 ab
= A [MD2] //und weise den Signalzustand Ausgang A 8.7 zu.
Beispiele für speicherindirekte Adressierung Beschreibung
U E [MD 2] Führe eine UND-Verknüpfung mit dem Eingangsbit aus. Die Adresse befindet sich in Merkerdoppelwort MD2.
= DIX [DBD 2] Weise den Signalzustand des VKE-Bits dem Instanz-Datenbit zu. Die Adresse befindet sich im Datendoppelwort DBD2.
L EB [DID 4] Lade das Eingangsbyte in AKKU 1. Die Adresse befindet sich im Instanzdoppelwort DID4.
AUF DB [LW 2] Öffne den Datenbaustein. Die Nummer des Datenbausteins befindet sich im Lokaldatenwort LW2.
 
OP
B

Bubi

Member
Beiträge
10
Punkte Reaktionen
0
Warrum machen Sie dass nicht mit Blockmove (SFC20), hiermit kann du ein bereich von x byte eingangen in block uberdragen nach z.b. ein DB bereich. Und wenn sie dass variabel machen must du die any pointers zu sammen basselen , in forum is er bei die FAQ ein beitrag mit beispiele dafur http://www.sps-forum.de/showthread.php/12923-Any-Zeiger-für-Datentypen

Joop

ICh habe bisher nie mit pointer gearbeitet, aber danke, habe es mir durchgelesen und diese Lösung wäre auch gut.

Warum ist das so und was bedeutet das?

Das "Format" der Var in der klammer verlangt das so.
Beispiel:
L EW2
Will ich das Vareabel gestalten also mit "L EW[#Var]" , kann ich nicht einfach :
L 2
T #Var
L EW[#VAR] da käme quasi raus " L EW[0000.002]"

Deswegen :
L 2
SLW
T #Var
L EW[#VAR]
dann läd er wirklich das EW2
 
Zuletzt bearbeitet:
Oben