Step 7 Variabler Array Index in AWL

Lyrim

Level-1
Beiträge
3
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute
Ich habe schon Verschiedenes zum Thema gelesen inkl. der Step7 Hilfe, jedoch werde ich nicht recht schlau.
Wie bereits zu erkennen möchte ich auf ein Array mit variablem Index zugreifen... und zwar schreibend.

Konkret:
Ich habe ein DB20 mit einem Array[1..8] of BYTE. Das Array trägt den Namen "Formnest" und beginnt bei der Adresse 10.0
Aus dem MB23 hol ich mir die Index-Nr. also je nach Zustand der Anlage 1-8. Wenn nun der Index 3 ist, soll das Array-Element 3 (Formnest[3]) mit 0 überschrieben werden. Wie stelle ich das an, dass dies mit dem variablen Index funktioniert?
Scheinbar muss das ja mit indirekter Adressierung gelöst werden. Aus den Beiträgen der Step7-Hilfe und im Forum werde ich aber nicht recht schlau. Kann mir jemand helfen?

Besten Dank und Gruss

Lyrim
 
Hallo Lyrim,

den Index eines Array's als Variable zu übergeben geht leider nicht in Step7 (Im TIA Portal mit S7-1500 geht es).

Indirekt:
Code:
Auf DB20
L MB23                              
SLW 3 
LAR1 

+ar1 P#10.0 

L DBB [AR1,P#0.0] 
T Ziel


Stefan
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für die schnelle Antwort!

Ja direkt geht es eben nicht, darum ja die Frage :)

Solch ähnliche Lösungen wie die deine habe ich eben auch öfters gesehen, verstehe sie aber nicht wirklich.
Weshalb das schieben nach links um 3 Stellen?
Was wird nun mit LAR1 geladen? Verstehe die Step7-Hilfe leider echt nicht.

Und was passiert beim zweiten Ladebefehl? Was bedeutet der Pointer P#0.0 ?

Verstehe glaube das Konzept der indirekten Adressierung nicht :(
 
Solch ähnliche Lösungen wie die deine habe ich eben auch öfters gesehen, verstehe sie aber nicht wirklich.
Weshalb das schieben nach links um 3 Stellen?

Weil du mit dem Index ja den Byteoffset angeben willst. die drei rechten bit sind für den Bitoffset pro Byte zuständig.

Was wird nun mit LAR1 geladen? Verstehe die Step7-Hilfe leider echt nicht.
In dem Beispiel der Inhalt von MB23. Also sozusagen der index.

Verstehe glaube das Konzept der indirekten Adressierung nicht :(

Da hats gute beispiele für AWL
http://www.sps-forum.de/faq/8887-pointer-zeiger-fifo-lifo.html

Aber ich sags dir. In SCL ist das ganze so viel einfacher das ich oft genau nur dafür schnell n FC in SCL bastel den ich in AWL aufrufen kann. :)

mfG René
 
Indirekte Adressierung direkt über Array-Index geht nicht. Du mußt die Zugriffsadresse berechnen.
(Siehe Hilfe zu AWL > Index > indirekte Adressierung)

Adresse = (Array_Index * 8) * Element_Größe + Anfangsadresse

Array_Index: 0 ... (muß * 8, weil Bit-Adressen adressiert werden, wir aber die Byte-Adresse brauchen)
Element_Größe: 1 = Byte / 2 = Word / 4 = DWord

Code:
L #index    // 1..8 (aus MB23)
+ -1        // --> 0..7
SLD 3       // * 8 --> Byteadresse.0

// * 1 für Byte-Array rechnen nicht nötig

L P#10.0    // Anfangsadresse des Array in DB20
+ D
T #temp_dw_ArrayAdr  // DWord für Adresse

AUF DB20
L DBB [#temp_dw_ArrayAdr]  // Byte aus DB20.myArray[#index]
T #myByte

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Zwei Dinge würde ich aber sicherheitshalber ändern
Code:
L MB23                              
SL[B][COLOR=#ff0000]D[/COLOR][/B] 3  //Falls mal was anderes als MB23 genommen wird und dessen Wert > 4096 ist
LAR1 

+Ar1 P#10.0 

[B][COLOR=#ff0000]Auf DB20  [/COLOR][/B]//Falls der Index mal nicht aus einem Merkerbereich sondern DB-Bereich kommt
L DBB [AR1,P#0.0] 
T Ziel

Wenn man so etwas macht würde ich aber eher in die Richtung gehen
Code:
//--------------------------------------------------------- Konstanten die einmal zugewiesen werden
L   20
T   Db20.DbNum           //DB-Nummer
L   10
T   Db20.ArrayOffsetinDB   //Startadresse des Array im DB
L   8
T   Db20.ArrayMemCnt       //Anzahl Array-Member
L   1
T   Db20.ArrayMemLEN       //Länge es ArrayMember in Byte


//--------------------------------------------------------- Variabler Zugriff
L   #ArrayIndex           //Index prüfen
L   1
>=I
U(
L   #ArrayIndex
L   Db20.ArrayMemCnt
<=I
)
SPBN Error


L   #ArrayIndex
+   -1                    //Weil Array[1] = Offset 0
L   Db20.ArrayMemLEN
*D
L   Db20.ArrayOffsetinDB
+D                         //Ab hier hat man die Startadresse von Array[x]
SLD 3                      //Pointerformat
LAR1                      //Adressregister

L     Db20.DbNum    
T     #DbNr_TEMP           //Variable im Temp-Bereich
AUF   DB[DbNr_TEMP]        //DB zum lesen öffnen
L     DBB[AR1,P#0.0]       //Von Array[x] lesen
T     #ZIEL                //Auf Ziel schreiben
Wenn man sich seine Offsets und die nötigen Beschreibungen seines Arrays 1x (am besten im selben DB) auf ein paar Werte schreibt, dann kann man später mal (vor allem wenn der indirekte Zugriff an mehreren Stellen im Programm steht) sein Array verschieben/erweitern und muss nur die "Konstanten" anpassen. Dann funktionieren diese Zugriffe auch wenn sich die Adresse/Länge oder gar DbNummer in dem das Array liegt ändert.
 
Zuletzt bearbeitet:
Vielen Dank für all eure Beispiele und Ausschweifungen!

Hat mir geholfen und jetzt hab ich's (denke ich) verstanden. Und sonst greife ich gerne auf den Link von "vollmi" zurück.

Einen schönen Abend euch allen!


EDIT: eine Frage noch, warum funktioniert das nicht wenn ich die komplette DB-Adresse verwende, sondern nur mit dem AUF Befehl?
 
Zuletzt bearbeitet:
EDIT: eine Frage noch, warum funktioniert das nicht wenn ich die komplette DB-Adresse verwende, sondern nur mit dem AUF Befehl?

Weil die CPU das im Endeffekt auch nicht anders macht. Diese hat ein Adressregister und ein DB-Register.
Wenn du also im Code also "L DB20.DBB10" schreibst lädt die CPU den Wert 20 ins DB-Register und den Offset p#10.0 ins Adressregister. Über die Kombination aus beiden passiert dann der Zugriff.

Der AUF-Befehl lädt eine Db-Nummer ins DB-Register und sorgt damit dafür das der Adressregister-basierende Ladebefehl "L DBB[AR1,P#0.0], der ja keine Information über die Datenbaustein-Nummer enthält, auch
auch auf den richtigen Datenbaustein zugreift.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
warum funktioniert das nicht wenn ich die komplette DB-Adresse verwende, sondern nur mit dem AUF Befehl?
Weil Siemens für die S7-300/400 Anweisungen wie "L DB[dbnr].DBB[adresse]" oder "L DB20.DBB[adresse]" nicht vorgesehen hat. Die DB-Nummer kann nur bei direkt angegebener DB-Adresse (oder Symbol) in der Anweisung mit angegeben werden, nicht bei indirekt angegebener DB-Adresse.
Genaugenommen gibt es noch nichtmal eine Anweisung wie "L DB20.DBB10" - weil die wird nur vom Editor freundlicherweise so zusammengezogen angezeigt. In Wirklichkeit besteht die Anweisung aus einer DB-losen L-Anweisung mit vorgeschalteter AUF-Anweisung:
Code:
L DB10.DBB0
L DB10.DBB1
L DB20.DBB2

//ist tatsächlich:

AUF DB10
L DBB0    //lädt DB10.DBB0

AUF DB10
L DBB1    //lädt DB10.DBB1

AUF DB20
L DBB2    //lädt DB20.DBB2

//indirekte Varianten:

AUF DB20
L DBB [#adresse]

AUF DI20
L DIB [#adresse]

AUF DB20
L DBB [AR1, P#0.0]

Ist in den DB-Zugriffs-Anweisungen keine DB-Nummer angegeben, dann beziehen sie sich auf die zuvor im DB1-Register (DBNO) oder im DB2-Register (DINO) hinterlegte DB-Nummer:
Code:
AUF DB10  //lädt die Nummer 10 ins DB1/DBNO-Register
AUF DI20  //lädt die Nummer 20 ins DB2/DINO-Register

L DBB1    //lädt DB10.DBB1 ~ entspricht quasi DB[DBNO].DBB1
L DIB2    //lädt DB20.DBB2 ~ entspricht quasi DB[DINO].DBB2

L DBNO    //lädt die Nummer aus dem DB1/DBNO-Register
L DINO    //lädt die Nummer aus dem DB2/DINO-Register

Harald
 
Zurück
Oben