# Array Element über Variable auslesen.



## FriedelM (6 Dezember 2010)

Hallo,

Bisher habe ich nur in ST programmiert und soll mich nun in der  S7 einarbeiten deshalb habe ich zwei einfache Fragen:
Meine Steuerung ist  eine S7 315 DP.
Das Programm soll in AWL geschrieben werden.
Problem  1:
Ich habe im DB14 ein Array [0...15] of Int. in diesem möchte ich über eine  Variable ein einzelnes Element auslesen.
In ST wäre das  folgendermaßen:
Wertx:=Array[variable_X];

Mein zweites Problem ist  etwas komplexer. Hier habe ich ebenfalls ein Array [0...6] of Int. Dieses möchte  ich mit einer Schleife durchlaufen und Bitweise abfragen. Sollte ein Bit true  sein möchte ich die Bittnummer in einen anderes Array mit 16 Feldern schreiben.  
Beispiel:
Das Bit 5, 16, 25 ,33 und 36 ist true.
(0000 0100 0000 0000  1000 0000 0100 0000 0100 1000  ..........) 
Dann soll in einen Integer die ersten 5 bits true gesetzt  werden. (0000 0000 0001 1111) bei 6 Bits die true sind dem entsprechend die  ersten sechs.
Das Array soll dann so aussehen.
Array[0] := 5;
Array[1]  := 16;
Array[2] := 25;
Array[3] := 33;
Array[4] := 36;
Sollten mehr  als 16 Bits true sein, werden ab dem 16. Bit, diese nicht mehr  beachtet.

Vielen Dank für eure Hilfe im Voraus. Und denkt daran ich bin  nicht besonders fit beim S7 programmieren

.


----------



## Copyright (6 Dezember 2010)

Hallo,

Wenn du weißt, welches Element du auslesen willst würde ich das mit "lade" und "transferiere" machen. 

L db14.dbwx
T variable

Deiner zweiten Frage kann ich nicht folgen. Aber es hört sich für mich nach indirekter Adressierung mit Zeigern an, ...

Gruß Copy


----------



## PN/DP (6 Dezember 2010)

Suche mal in der Step7-Hilfe nach *Adressierung speicherindirekt*, das kommt der Array-Schreibweise schon ziemlich nahe, adressiert aber nicht ein Array-Element sondern eine Speicheradresse in Byte-Zählung. EDIT: *Bit-Zählung*.

Harald


----------



## Tigerente1974 (6 Dezember 2010)

Problem 1:
Das indirekte Adressieren des "Index" in der eckigen Klammer hätte ich auch schon x-mal mit AWL/KOP/FUP gebrauchen können... :?
Wie PN/DP schon geschrieben hat, kann man nur die Adresse aufrufen. Wenn dann mal ein Element eingefügt wird, passen die Adressen nicht mehr.

Problem 2:
Könnte man mit einer Schleife lösen (AWL kann "LOOP" ).
Bits mit einem Schiebebefehl durchschieben, das letzte Bit auf 1 abfragen und den Schleifenzähler benutzen, um einzutragen das wievielte bit an war.


----------



## Larry Laffer (6 Dezember 2010)

Hallo,
vielleicht noch ein anderer Ansatz :
das Pendant zu ST gibt es in der Siemens-Welt auch - nennt sich da SCL. Da solltest du dann alles so machen können wie gehabt. 
Unter Siemens AWL kannst du die Adressierung nur wie oben beschrieben über indirekte Adressierung lösen (also für jedes Array-Element einen neuen Pointer bauen). Du kannst hier (leider) nicht mit dem Index direkt arbeiten ... 

Gruß
Larry


----------



## FriedelM (7 Dezember 2010)

*Versuche zu Problem 1*

Hallo ich habe nach ein paar Versuchen folgenden Code erstellt der nciht funktioniert. Den habe ich mir aus anderen Forenbeiträgen zusammengesucht.


```
AUF   "Fehlerauswertung" //DB 14
      L     "Fehlerauswertung".FehlerDetailAnzeige //DB 14.dbw34
      T     #akt_dw 
      SLD   3
      LAR1  
      L     DBD [AR1,P#0.0]
      T     "Fehlerauswertung".FehlerDetailAnzeige //DB 14.dbw36
```
Dabei geht die CPU immer in Stopp.
Ich finde einfach nichts für die richtige Syntax. 
Ich habe ach andere Versuche gemacht, dabei kommen dann allerdings immer wirre Werte raus.
Leider habe ich hier nur die Möglichkeit in AWL zu programmieren. 
Und unter "*Adressierung speicherindirekt" *habe ich nichts gefunden. 

Gruß FriedelM


----------



## Larry Laffer (7 Dezember 2010)

Hallo,
schreib doch bitte mal in ST-Code hin, was du vorhast ...

Gruß
Larry


----------



## Verpolt (7 Dezember 2010)

FriedelM schrieb:


> Hallo ich habe nach ein paar Versuchen folgenden Code erstellt der nciht funktioniert. Den habe ich mir aus anderen Forenbeiträgen zusammengesucht.
> 
> 
> ```
> ...



Sollte da nicht ein 


```
L DBW (AR1.P#0.0)
```

rein?


----------



## FriedelM (7 Dezember 2010)

Hallo,

Ich habe da zwei ganz "dumme" Fehler gemacht. Jetzt funktioniert es *ROFL*
Hier der richtige Code. Woran ich nicht gedacht habe, ist dass ich bei der Adressierung ja nor jede 2. Adresse abfragen kann.

```
AUF   "Fehlerauswertung" //
      L     "Fehlerauswertung".FehlerDetailBild
      T     #akt_dw
      SLD   3
      LAR1  
      L     DBW [AR1,P#0.0]
      T     "Fehlerauswertung".FehlerDetailAnzeige
```
Zu Problem 2 komme ich dann noch einmal später. Vielen Dank an euch. Muss leider noch an einen anderen Projekt weiter machen. Der BL ruft.

Gruß FriedelM


----------



## PN/DP (7 Dezember 2010)

FriedelM schrieb:


> Ich habe im DB14 ein Array [0...15] of *Int*. in diesem möchte ich über eine  Variable ein einzelnes Element auslesen.
> In ST wäre das  folgendermaßen:
> Wertx:=Array[variable_X];





FriedelM schrieb:


> Hier der richtige Code. Woran ich nicht gedacht habe, ist dass ich bei der Adressierung ja nor jede 2. Adresse abfragen kann.
> 
> ```
> AUF   "Fehlerauswertung" //
> ...


SLD 3 adressiert byteweise, SLD 4 adressiert wordweise.

Mit SLD 4 entspricht das der Operation *"Fehlerauswertung".FehlerDetailAnzeige:=Array["Fehlerauswertung".FehlerDetailBild];* wenn Dein Array bei DB14.DBB0 beginnt. Wenn das Array nicht bei DBB0 beginnt, dann muß zwischen dem SLD 4 und dem LAR1 noch die Anfangsadresse des Arrays addiert werden.

Harald


----------



## StefanK (7 Dezember 2010)

*Schon etwas länger her...*

... aber ich hab mal so etwas gebastelt:


```
FUNCTION "READ_IND_ADR_ARRAY" : VOID
TITLE =
VERSION : 0.1


VAR_INPUT
  feld_nr : INT ;	//Gewünschtes Feld im INTEGER-Format.
  feld_laeng : INT ;	//Summe über die Länge aller Zellen  innerhalb eines Feldes Byte-Weise.  
END_VAR
VAR_OUTPUT
  aus_zelle1 : TIME ;	//Inhalt des ersten ARRAY-Elements, das  gelesen werden soll.  
END_VAR
VAR_IN_OUT
  feld : ARRAY  [1 .. 100 ] OF //Muß identisch sein mit dem ARRAY, auf dem indirekt zugegriffen werden soll!
  STRUCT 	
   feld1 : TIME ;	
  END_STRUCT ;	
END_VAR
VAR_TEMP
  dbnr : WORD ;	
  offset : DWORD ;	
END_VAR
BEGIN
NETWORK
TITLE =OFFSET ermitteln

//ermitteln des gewünschten Feldes, auf das zugegriffen werden soll
//nach folgendem Algorithmus: (feld_nr - 1) * feld_laeng 

      L     #feld_nr; // Gewünscht. Indize vom ARRAY z.B.: 1 - 4
      L     1; 
      -D    ; 
      L     #feld_laeng; // Länge des Feldes Byteweise in
      *D    ; // INT-Format z.B.: 4 da 2 mal INTEGER.
      SLD   3; // Um 3 Bit nach links schieben um
      T     #offset; // Pointer-Format zu erhalten.

NETWORK
TITLE =Lesen indirekt Impliziert ARRAY-Feld 


      L     P##feld; // Ermitteln der Anfangsadresse.
      LAR1  ; // Laden der Anfangsadresse in das Adressregister 1.
      L     W [AR1,P#0.0]; // Falls ein referenzierter Zugriff erfolgt: DB-Nr. ermitteln.
      T     #dbnr; // Sichern der DB-Nr.
      AUF   DB [#dbnr]; // DB öffnen.
      L     #offset; // Lade OFFSET.
      L     D [AR1,P#2.0]; // Laden der Anfangsadresse des ARRAYs.
      +D    ; // Verknüpfen mit Anfangsadresse des Feldes.laden der Adresse des indizierten Feldes
      LAR1  ; // in das Adressregister 1.
      L     D [AR1,P#0.0]; // Ausgabe des Inhaltes des gewünschten
      T     #aus_zelle1; // Feldes zur OUTPUT-Variablen.

END_FUNCTION

FUNCTION "WRITE_IND_ADR_ARRAY" : VOID
TITLE =
VERSION : 0.1


VAR_INPUT
  feld_nr : INT ;	//Gewünschtes Feld im INTEGER-Format.
  feld_laeng : INT ;	//Summe über die Länge aller Zellen  innerhalb eines Feldes Byte-Weise.  
  in_zelle1 : TIME ;	//Inhalt des ersten ARRAY-Elements, das  beschrieben werden soll.  
END_VAR
VAR_IN_OUT
  feld : ARRAY  [1 .. 100 ] OF //Muß identisch sein mit dem ARRAY, auf dem indirekt zugegriffen werden soll!
  STRUCT 	
   feld1 : TIME ;	
  END_STRUCT ;	
END_VAR
VAR_TEMP
  dbnr : WORD ;	
  offset : DWORD ;	
END_VAR
BEGIN
NETWORK
TITLE =OFFSET ermitteln

//ermitteln des gewünschten Feldes, auf das zugegriffen werden soll
//nach folgendem Algorithmus: (feld_nr - 1) * feld_laeng 

      L     #feld_nr; // Gewünscht. Indize vom ARRAY z.B.: 1 - 4
      L     1; 
      -D    ; 
      L     #feld_laeng; // Länge des Feldes Byteweise in
      *D    ; // INT-Format z.B.: 4 da 2 mal INTEGER.
      SLD   3; // Um 3 Bit nach links schieben um
      T     #offset; // Pointer-Format zu erhalten.

NETWORK
TITLE =schreiben indirekt impliziet ARRAY-Feld 


      L     P##feld; // Ermitteln der Anfangsadresse.
      LAR1  ; // Laden der Anfangsadresse in das Adressregister 1.
      L     W [AR1,P#0.0]; // Falls ein referenzierter Zugriff erfolgt: DB-Nr. ermitteln.
      T     #dbnr; // Sichern der DB-Nr.
      AUF   DB [#dbnr]; // DB öffnen.
      L     #offset; // OFFSET laden.
      L     D [AR1,P#2.0]; // Laden der Anfangsadresse des ARRAYs.
      +D    ; // Verknüpfen mit Anfangsadresse des Feldes. Laden der Adresse des indizierten Feldes
      LAR1  ; // in das Adressregister 1.
      L     #in_zelle1; 
      T     D [AR1,P#0.0]; // Ausgabe des Inhaltes des gewünschten

END_FUNCTION
```

Gruß

Stefan


----------



## FriedelM (15 Dezember 2010)

Hallo,

Endlich bin ich dazu gekommen, dass Programm fertig zu programmieren. 
Ich habe nur das Problem, dass High Byte und Low Byte vertauscht sind. Aber ich denke, dass ich dazu, noch eine Lösung finde. 


```
AUF   "DB55_HMI_Störmeldungen"
      L     #akt_dw_loop
      L     95
      >=I   
      SPBB  lasb                        //letztes Bit
//Abfrage der Bitposition
      L     #akt_dw_loop
      LAR1  
      U     DBX [AR1,P#0.0]
      SPBN  inc
//Abfrage ob das Letzte Anzeigefenster erreicht ist
      L     16
      L     #fehler_bit
      ==I   
      SPBB  inc
//Schreibe Fehlernummer ins Array
      AUF   "Fehlerauswertung"
      L     #fehler_bit
      SLD   4
      LAR1  
      L     #akt_dw_loop
      T     DBW [AR1,P#2.0]
      L     #fehler_bit
      LAR1  
      SET   
      =     DBX [AR1,P#0.0]
// fehlerbit +1
      L     1
      L     #fehler_bit
      +I    
      T     #fehler_bit
// akt_dw_loop +1
inc:  L     1
      L     #akt_dw_loop
      +I    
      T     #akt_dw_loop
// Fehler rücksetzten bei Reset
lasb: U     "DB52_HMI_Schalter".Fehler_zuruecksetzten
      SPBNB end
      L     0
      T     #akt_dw_loop
      T     #fehler_bit
      T     "Fehlerauswertung".FehlerSichtbar
end:  BE
```

Gruß und Vielen Dank für eure Hilfe

Friedel


----------



## Nordischerjung (15 Dezember 2010)

FriedelM schrieb:


> Ich habe nur das Problem, dass High Byte und Low Byte vertauscht sind. Aber ich denke, dass ich dazu, noch eine Lösung finde.



Moin,

dafür gibt es doch TAW


----------

