Adressoperator in AWL ?

kiestumpe

Level-1
Beiträge
726
Reaktionspunkte
84
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,


ich versuch gerade die Adresse einer Variablen innerhalb eines DB's zu ermitteln:

Wenn ich den Wert in den Akku lade und anschliessend das AR1 auslese erhalte ich diesen Wert nicht (kommt immer 0)

Gibt es sowas wie einen Adress-Operator ?

Bei dem Versuch:
Code:
 L     DB100.DBB    0
      TAR1  #PTR_DbAnfang
      L     DB100.DBB   10
      TAR1  #PTR_DbStatus
      L     #PTR_DbAnfang
      L     #PTR_DbStatus
      -D    
      T     #PTR_DbTimer
erhalte ich alles andere blos nicht den Offset zwischen den beiden.
Es muss doch irgend eine Möglichkeit geben aus der Symbolik auf die Adresse zu kommen, oder ?

MfG
kiestumpe
 
Folgendes lief hier mal im Forum, müßte eigentlich auch für deinen Fall zutreffen:

Beispiel: #E_Var ist P#DB10.DBX12.5 BOOL 27. Dies bedeutet: Zeiger auf 27 Bits
ANY-Aufbau
1 BYTE 0x10 (S7) (Offset 0.0)
1 BYTE Datentyp BOOL (1) (Offset 1.0)
1 WORT Wiederholungsfaktor (27) (Offset 2.0)
1 WORT DB-Nummer (10) (Offset 4.0)
1 DWORT Bereichsübergreifender Zeiger (P#DBX12.5) (Offset 6.0)
eigentliche Antwort:
L D[AR1,P#6.0] lädt den bereichsübergreifenden Zeiger (P#DBX12.5 an Offset 6.0) auf den adressierten Bereich in AKKU1.
ABER: vor dem Zugriff mit dem geladenen Zeiger den entsprechenden DB aufmachen sonst wird die SPS böse und rot. Dies geschieht z.B mit
Code:
L W[AR1,P#4.0]
T LW<ein freies Lokaldatenwort>
AUF DB[LW<...>]

Wenn der ANY-Zeiger nicht auf einen Datenbereich zeigt, dann steht bei der DB-Nummer 0, es passiert also kein Fehler. Vorausgesetzt, der ANY-Zeiger wurde von jemandem erzeugt, der weiß wie's sein soll.
(BOOL) in DB 10 ab Adresse DBX12.5
----------------------------------------
Anonymous hat folgendes geschrieben:
Demnach müsste ich in folgendem Beispiel das ED6 in meinen Akku 1 laden? Stimmt das?
L P##E_Var
LAR1
L D[AR1,P#6.0]
Die Variable E_Var ist vom Typ ANY und zeigt auf den E0.0.
Es wird ED 0 geladen. Der Offset 6 ist notwendig um auf den Zeiger in der Any-Struktur zuzugreifen (s.o. Strukturaufbau).
Code:
L P##E_Var
LAR1
AR1 zeigt auf Any-Struktur
P#6.0 ergibt den Offset
Code:
L D[AR1,P#6.0]
lädt somit das Doppelwort auf das der Zeiger in der Any-Struktur zeigt (blöde Formulierung).

Weiß leider nicht mehr, wer das gepostet hatte:rolleyes: .
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Ralle,

sorry ich kann dem leider nicht ganz folgen. Was in diesem Beispiel ja bereits ist, dass E_Var schon auf E0.0 zeigt.

Code:
Demnach müsste ich in folgendem Beispiel das ED6 in meinen Akku 1 laden? Stimmt das? 
L P##E_Var 
LAR1 
L D[AR1,P#6.0] 
Die Variable E_Var ist vom Typ ANY und zeigt auf den E0.0. 
Es wird ED 0 geladen. Der Offset 6 ist notwendig um auf den Zeiger in der Any-Struktur zuzugreifen (s.o. Strukturaufbau). 
Code: 
L P##E_Var 
LAR1 
AR1 zeigt auf Any-Struktur 
P#6.0 ergibt den Offset 
Code: 
L D[AR1,P#6.0] 
lädt somit das Doppelwort auf das der Zeiger in der Any-Struktur zeigt (blöde Formulierung).

In meinem Fall steht jedoch das entsprechende Symbol zur Verfügung, dess Adresse im DB ich ermitteln muss und danach in ein DW schreiben will.

Also Ausgehen z.B. :
Adresse von (DB100.MeineVariable)
- Adresse von (Db100.Dbb0)
= OffsetAdresse
 
Wenn ich Zeiger baue mache ich das wie folgt:

#Adr ist ein DWORD
Code:
      L     P#0.0
      L     #Adr
      SLD   3
      +D    
      LAR1                              //Adresse des Datenwortes mit dem Wert für Pos_Nr
      L     DBD [AR1,P#0.0]
      T     #Pos                        //Anzufahrende Position wird ausgegeben

Probier doch mal zum Errechnen des Offset bei jedem Zeiger vorher SRD 3 um damit die Bitadresse rauszuschieben, die in den letzten 3 Bit steckt. Dann subtrahieren.

In dem Any-Zeiger steckt doch der nötige Zeiger.
 
Zuletzt bearbeitet:
Ralle schrieb:
Wenn ich Zeiger baue mache ich das wie folgt:

#Adr ist ein DWORD
Code:
      L     P#0.0
      L     #Adr
      SLD   3
      +D    
      LAR1                              //Adresse des Datenwortes mit dem Wert für Pos_Nr
      L     DBD [AR1,P#0.0]
      T     #Pos                        //Anzufahrende Position wird ausgegeben

Hallo Ralle,

Voraussetzung ist jedoch, dass dir die Adresse bekannt ist - das ist aber nicht das was ich brauch.
Bekannt ist das Symbol, z.B
"DB_Beispiel".ElementXY

Gesucht:
Adresse von ElementXY im DB.

Bei der Anweisung:
L P## "DB49".DBB0
bzw.
L P# "DB49".DBB0

bekommt ich nur Fehlermeldungen.

Die imho schlechte alternative - die Adresse im DB selbst nachschlagen und Eintragen - aber das ist bei über 50 Elemente fehleranfällig.
Irgendwie muss das doch auch anders gehen, oder steh ich so auf dem Schlauch ?
(Kopfgratz ...)

MfG
Kiestumpe
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Falsche Annahme !

Hallo kies..,

es gibt in S7 keinen Adressoperator! Deine Versuche gehen von der
Annahme aus, dass S7 bei der Adressierung eines DB-Operanden
auch das AR1 einsetzt. Das ist aber nicht so.

Die S7 adressiert normalerweise absolut, d.h. dein schöner Variablen-
Name des DB-Operanden ist gar nicht im AG, wie im übrigen auch keines
der schönen Symbole in der Symboltabelle.

Das AR1 wird standardmäßig nur verwendet, um auf Bausteinparameter
zuzugreifen, das AR2 dient als Basisadressregister bei Multiinstanzen.
Bei normalen DB-Zugriffen steht die absolute Adresse durch den
Programmcode eindeutig fest, also ist keine Registeradressierung mehr
nötig. Das würde ja auch nur unnötig Rechenzeit kosten.

Aber sag mal, was du eigentlich vor hast, vielleicht gibt es ja einen
anderen Weg.

Gruß G.
 
L DB100.DBB 0
TAR1 #PTR_DbAnfang
L DB100.DBB 10
TAR1 #PTR_DbStatus
L #PTR_DbAnfang
L #PTR_DbStatus
-D
T #PTR_DbTimer

Ich kanns grad nicht testen, was bekommst du denn raus wenn du nach
-D noch SRD 3 einfügst (Ist dann natürlich kein Pointerformat mehr, sonder ein DWord mit dem Offset?)
 
Noch ein Gast schrieb:
Hallo kies..,

es gibt in S7 keinen Adressoperator! Deine Versuche gehen von der
Annahme aus, dass S7 bei der Adressierung eines DB-Operanden
auch das AR1 einsetzt. Das ist aber nicht so.

Die S7 adressiert normalerweise absolut, d.h. dein schöner Variablen-
Name des DB-Operanden ist gar nicht im AG, wie im übrigen auch keines
der schönen Symbole in der Symboltabelle.

Das AR1 wird standardmäßig nur verwendet, um auf Bausteinparameter
zuzugreifen, das AR2 dient als Basisadressregister bei Multiinstanzen.
Bei normalen DB-Zugriffen steht die absolute Adresse durch den
Programmcode eindeutig fest, also ist keine Registeradressierung mehr
nötig. Das würde ja auch nur unnötig Rechenzeit kosten.

Aber sag mal, was du eigentlich vor hast, vielleicht gibt es ja einen
anderen Weg.

Gruß G.

Hallo,

ich habe einen FC vorgegeben, den ich folgendermassen aufrufen muss:

Code:
      CALL  "Ventilsteuerung"
       NotAus_OK          :="Not_Aus_OK"
       Verriegelung       :=FALSE
       Rueckmeldung_ZU    :="RMZ_A4-V02"
       Rueckmeldung_AUF   :="RMA_A4-V02"
       Ueberwachung_EIN   :=#watch
       Zeitbasis          :="Sek_Flag"
       DB_Nummer          :=W#16#6E     // DB-Nr.
       DB_Adressbereich_SB:=DW#16#8     // Adressber.SB Ventil2
       DB_Adressbereich_T :=DW#16#1A0   // Adressber.Timer Ventil2
       MW_Adressbereich   :=DW#16#4B0   // Vergleichsvar.Adresse
       Ausgang_Ventil     :="A4-V02"

Besonders bei den Parametern "...Adressbereich" käme mir die Symbolik erheblich entgegen, anstatt hier mit absolutwerten zu arbeiten.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Irgendwie kann ich dir jetzt nicht mehr folgen, deklariere die Variablen als Bool, Word, Timer, DWord und schreib dann deine Variablen ran.
Wozu willst du denn in diesem Fall mit Zeigern und Offsets rumopern?

Code:
CALL  "SYSTEM_BI_VALVE"
       FRG                 :=#Freigabe
       FRG_STEP_AUTO       :=#FRG_STEP
       SK_EIN              :="DATA_STATION_09".MSG_OUT_05_SET
       SK_AUS              :="DATA_STATION_09".MSG_OUT_05_RES
       HAND_EIN            :="DATA_STATION_09".HAND_AST_05
       HAND_AUS            :="DATA_STATION_09".HAND_GND_05
       STATUSANZEIGE_AKTIV :=#Statusanzeige_Ein
       GRUNDBEDINGUNG      :=#GRUND_BEDINGUNG
       GRUNDFAHRT          :="DATA_STATION_09".MOVE_HOME
       HARDWARE_o_k        :="M0.0 Steuerung ein"
       QUITT_ERROR         :="M1.7 ACK"
       ZEIT_IMPULS_100ms   :="M1001.0 Imp. 100ms"
       WERT_LAUFZEIT_100ms :=300
       ENDLAGEN_WACHE_AKTIV:=TRUE
       ENDLAGE_G           :="E_s9_Prüfdorn_GST"
       ENDLAGE_A           :="E_s9_Prüfdorn_AST"
       ENDLAGE_G_AUS       :=FALSE
       ENDLAGE_A_AUS       :=FALSE
       STATUS              :="DATA_STATION_09".EL_05
       AUSGANG_G           :="A_s9_HD_Zyl_GST"
       AUSGANG_A           :="A_s9_HD_Zyl_AST"
       AKKU_LAUFZEIT       :="DATA_GLOBAL_AKKU".STM205
       STOERMELDUNG        :="DATA_STATION_09".STG_05
       STOERBIT            :="STOERMELDUNGEN DB".SPS_SM_205
       QUITTIERBIT_OP      :="STOERMELDUNGEN DB".OP_QUIT_205
       QUITTIERBIT_SPS     :="STOERMELDUNGEN DB".SPS_QUIT_205
 
Besser mit FB ...

Hallo kies...,

wenn ich das richtig verstehe, möchtest du die Ventilbewegungen
für mehrere Ventile überwachen. Dazu solltest du am besten aus
dem FC einen FB machen und ihn für jedes Ventil als Multiinstanz
aufrufen.

Dann kannst du deine Zeiten in internen statischen Variablen
speichern. Die liegen dann im Instanz-DB und die absolute Adresse
ist nicht mehr wichtig.

Gruß G.
 
Ralle schrieb:
Irgendwie kann ich dir jetzt nicht mehr folgen, deklariere die Variablen als Bool, Word, Timer, DWord und schreib dann deine Variablen ran.
Wozu willst du denn in diesem Fall mit Zeigern und Offsets rumopern?

Hallo

@Ralle,

wollen ist übertrieben - freiwillig gewzungen, da dieser FC nicht verändert werden soll- daher hat es sich auch mit dem Umwandeln in einen FB.
Dieser FC macht dann aus der Übergebenen Adresse wieder einen Zeiger in den Zugehörigen.

Mit dieser Adresse wird in dem FC ausser dem Zeitzähler noch eine Liste verarbeitet, die gleich im Anschluss im DB steht, einschliesslich Index und variabler Länge.
Nur wenn ich das obige lese, gehts schlicht und einfach nicht, oder?

MfG

Kiestumpe
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Tut mit leid kiestumpe, ich versteh jetzt absolut nicht mehr, was du überhaut machen willst. Willst du diesen FC in einen eigenen FC verpacken? Wenn du ihn nicht ändern darfst, mußt du ihn so aufrufen wie er ist, geht dann ja nicht anders. Wenn du einen eigenen FC drumherumbauen willst, der die Parameter symbolisch entgegenmimmt, dann nimm Any-Zeiger, die werden als Zeiger übergeben und sind dann wieder auseinanderzunehmen.
 
Hallo Ralle,

verpacken will ich den FC- Ventilsteuerung nicht nochmal, lediglich aufrufen.
Weg wollte ich von
DB_Adressbereich_T := DW#16#150,// Adressber.Timer Ventil1
im call Aufruf, zu Symbolik und Adressoperator.

Aber es scheint so, dass ich diese Adresse nirgends her bekomme.

Trotzdem danke für eure Bemühungen.

Gruss
 
Ach so, jetzt wird es etwas klarer, du wolltest die symolische Adresse auseinanderbauen und dann die "Einzelteile" an den FC schreiben?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

Code:
      CALL  "Ventilsteuerung"
       NotAus_OK          :="Not_Aus_OK"
       Verriegelung       :=FALSE
       Rueckmeldung_ZU    :="RMZ_A4-V02"
       Rueckmeldung_AUF   :="RMA_A4-V02"
       Ueberwachung_EIN   :=#watch
       Zeitbasis          :="Sek_Flag"
       DB_Nummer          :=W#16#6E     // DB-Nr.
       DB_Adressbereich_SB:=DW#16#8     // Adressber.SB Ventil2
       DB_Adressbereich_T :=DW#16#1A0   // Adressber.Timer Ventil2
       MW_Adressbereich   :=DW#16#4B0   // Vergleichsvar.Adresse
       Ausgang_Ventil     :="A4-V02"

Schreibe dir doch eine FC der du die Adressbereiche als Pointer symbolisch übergibst. In dieser FC liest du aus den Pointern die Adressen aus und legst sie auf Ausgänge der FC. Mit diesen wiederum versorgst du obigen Baustein "Ventilsteuerung". Müsste eigentlich gehen, oder?


Gruß, Onkel
 
Zuletzt bearbeitet:
Hallo,

ich versuch gerade die Adresse einer Variablen innerhalb eines DB's zu ermitteln:
Wenn ich den Wert in den Akku lade und anschliessend das AR1 auslese erhalte ich diesen Wert nicht (kommt immer 0)
MfG
kiestumpe

Hallo,
etwas spät aber ich hatte gerade das gleiche Problem und wusste nicht mehr wie ich die Byte Adresse eines Arrays des InstanzDB in den Akku laden. Im Web habe ich nichts gefunden nur die Enttäuschenden üblichen Antworten: Sage doch mal was du machen willst! Ätz.
Naja jedenfalls kann man die Adresse sehrwohl erfahren und in den Akku laden.
Habe ein Array im Stat eines FB angelegt: Wert Array[1..90] of Byte
Ersteinmal auf den ersten Wert des Arrays Zeigen und dann sie adresse auslesen. Eigendlich sau Easy.
LAR1 P##Wert
TAR1
SLD 16
SRD 16
SRD 3

Und da ist er im Akku1, der Byte Versatz zum ersten Byte des Arrays.

Machnmal sind die Probleme doch echt zäh bis man die einfache Lösung sieht.
 
Zurück
Oben