Step 7 Indirekte Adressierung

Junge

Level-2
Beiträge
226
Reaktionspunkte
17
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo liebe Gemeinde,

ich brauch mal wieder eure Hilfe.

Es soll alle 50ms ein Wert in einen DB abgespeichert werden.

Der Datentyp ist Real.

Zuerst habe ich ein DB10 mit einem Array[0..49] erstellt in Real.
Dann dachte ich an so etwas:

AUF DB10

L Z1
SLD3
LAR1
T MD 180 //Dword- Pointer hinterlegt

L DB1.DBD8 //Realtyp- Signalwert
T DBW[MD180] //Wert soll das entsprechende Array im DB10 hinterlegt werden



Der DB1.DBD8 verändert sich kontinuierlich und Z1 wird alle 100ms hochgezählt. Vorher im Programm ist noch eine Abfrage ob sich Z1 geändert hat, so dass nur bei einer Z1 Änderung der obige Programmabschnitt aufgerufen wird.

Irgendwie läuft es nicht bei mir, ich habe da eine Vermutung dass es mit den Datentypen zu tun hat.

Was mache ich falsch?


alternativ, Wenn ich es ganz einfach halte:

AUF DB 10

L 1
SLD 3
LAR1
T MD 180 //dword
L DB1.DBD 8 //real
T DBW [MD 180]

dann geht es auch nicht. irgendas mit den Datentypen stimmt nicht, aber bei mir dreht sich auch schon alles. Ich hoffe dass ihr mir ein paar gute Tipps geben könnt
 
Zuletzt bearbeitet:
Hallo Junge,

was mir auf Anhieb auffällt ist dass du:

T DBW [MD180] benutzt.

Besser wäre es

T DBD [MD180]

Der Real-Wert liegt in einem DoppelWort

L DB1.DBD 8

Also muss das Ziel auch ein DoppelWort sein!

Besser wäre es vielleicht das

AUF DB10 direkt vor
T DBD [MD180] zu schreiben.

Dadurch erkennt man besser wohin der Wert geschrieben wird...


Gruß
Guido
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
L Z1
SLD3
LAR1
T MD 180

AUF DB10
L DB1.DBD8
T DBD[MD180]

Ist es überhaupt möglich den Zähler als "indirekten Adresswert" zunehmen?
-Bzw. muss der Z1 Datentyp der gleiche sein wie MD180? (also DWord)

Oder andersrum gefragt muss MD180 zwingend Dword sein, es beinhaltet ja nur die Adresse und keinen real wert?
 
Zuerst habe ich ein DB10 mit einem Array[0..49] erstellt in Real.
Dann dachte ich an so etwas:
Code:
AUF DB10

L Z1
SLD3
LAR1
T MD 180                                          //Dword- Pointer hinterlegt  

 L DB1.DBD8                                      //Realtyp- Signalwert
 T DBW[MD180]                                 //Wert soll das entsprechende Array im DB10 hinterlegt werden

alternativ, Wenn ich es ganz einfach halte:

Code:
      AUF   DB    10
 
      L    1
      SLD   3
      LAR1  
      T     MD   180                          //dword
      L     DB1.DBD    8                    //real
      T     DBW [MD   180]

Du vermischt da ein wenig Äpfel mit Birnen.

Das mit dem SLD3 kommt von Register-indirekter Adressierung, wogegen das L DBW[MD180] von einer anderen Type der indirekten Adressierung kommt (korrekter Name fällt mir grad nicht ein)

In beiden Fällen musst du zuerst mal die Zieladresse korrekt ausrechnen.
Dann kannst du auf eine der Varianten zurückgreifen.
Code:
 L  #IndexNummer    //0-beginnend
 L  L#4            //Speicherbreite Real
 *D
 L  #DbOffset_Array    //Speicheradresse bei der das Array im DB beginnt.
 +D
 T  #DbAddr        //Byte-Adresse das gesuchten Elements im DB (am besten hier einen DINT-TEMP-Wert nehmen)


//--------------------- Variante 1
    
 AUF DB 10        //DB öffnen
 L   DBD[#DbAddr]    //Datendoppelwort mit variable Adresse laden


//--------------------- Variante 2 - Registerindirekte Adressierung (Zeiger)


L   #DbAddr        //StartAdresse im DB
SRD 3                   //Umwandeln in Pointer
LAR1            //In Adressregister laden
L DBD[AR1,p#0.0]        //Wert über Adressregister laden


//--------------------- Variante 3 - Einen kleinen SCL-FC schreiben und mit variablen Array-Indizes arbeiten
 
Zuletzt bearbeitet:
Ist es überhaupt möglich den Zähler als "indirekten Adresswert" zunehmen?
Wenn dein Zähler so zählt dann ja:
Startadresse im DB + 0
Startadresse im DB + 4
Startadresse im DB + 8
etc.

Mit einem Z1 alleine schaffst du das natürlich nicht. Siehe die Berechnung im vorigen Beirag

Das hier hat auch ein Problem....
Code:
AUF DB10        ​[COLOR=#FF0000]//Hier öffnest du den DB10[/COLOR]
L DB1.DBD8      [COLOR=#FF0000]//Hier wird aber der DB1 automatisch mitgeöffnet    [/COLOR]
T DB[U][B]D[/B][/U][MD180]​    [COLOR=#FF0000]//Hier lädst du also aus DB1 das Doppelwort mit der Byteadresse die in MD180 steht, welche bedingt durch das SLD3 wahrscheinlich Blödsinn ist.    [/COLOR]

Das letztere kannst du nur umgehen in dem zu entweder zwischendrin keinen anderern DB aufrufst oder Temp/Merkerwerte nimmst.
Code:
L DB1.DBD8 
AUF DB10           //Korrekten DB erst kurz vor indirektem Zugriff öffnen
T DB[U][B]D[/B][/U][MD180]​ 

oder

L DB1.DBD8 
T TEMP-Wert           //TEMP-Wert verwenden

AUF DB10
L TEMP-Wert           //TEMP oder Merkerwerte beeinflussen nicht den geöffneten DB im DB-Register
T DB[U][B]D[/B][/U][MD180]​
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
OH! Danke!! ich glaube das wird mir schon viel weiterhelfen! Kann es leider erst morgen auf der Arbeit ausprobieren.
@Ronin:

Aber ich hab immer noch ein paar Fragen :rolleyes:

Da ich ja etwas auf den DB schreiben möchte wäre es dann so richtig?

L #IndexNummer //0-beginnend
L L#4 //Speicherbreite Real Was bedeutet L#4, das sehe ich zum ersten mal.
*D
L #DbOffset_Array //Speicheradresse bei der das Array im DB beginnt. Also Bspw. L 0 oder L 40, wenn das array bei DB10.DbD0 oder DB10.DbD10 beginnt?
+D
T #DbAddr //Byte-Adresse das gesuchten Elements im DB (am besten hier einen DINT-TEMP-Wert nehmen)


AUF DB 10 //DB öffnen
L DB1.DBD8 // Der Datenwert in Real der abespeichert werden soll
T DBD[#DbAddr] //Datendoppelwort mit variable Adresse laden

So müsste es doch dann eigentlich funktionieren?!
 
Zuletzt bearbeitet:
Zu Rot 1:
4 ist eine Integer-Konstante, L#4 ist einen Doppelintegerkonstante.​
L 500000 geht nicht (INT zu klein)
L L#500000 geht schon

Sowohl Variante 1 (L DBD[DINT-Variable]) als auch Variante 2 (SLD DINT-Variable) erfordern Doppelinteger.
Durch das verwenden der korrekten Konstanten und Befehle (*D, +D) bleibt man immer schön im selben Format.


Zu Rot 2:
Ja Korrekt.
Unten muss einfach die richtige Adresse rauskommen.
Beispiel: Dein Array[0..49] startet bei DBD10 und du willst auf Array[10], dann lautet die Adresse dieses Reals im DB ja 50.
Genau das muss dann auch in #DbAddr stehen. Ist eigentlich nur einfache Mathematik

Zu Rot 3:
Problem. Lies dir Beitrag 5 nochmal durch.
 
Ja klar,....der Tag war schon lang ^^ gut das du mich nochmal drauf hinweist.

Zu Rot3: wäre es dann entsprechend

L DB1.DBD8 // Der Datenwert in Real der abespeichert werden soll
AUF DB 10 //DB öffnen
T DBD[#DbAddr] //Datendoppelwort mit variable Adresse laden

Danke nochmal für die vielen Tipps und den guten Erklärungen, hat mir schon viel weitergeholfen.








...Hier nochmal meine eigene Zusammenfassung. Vllt hilft es in Zukunft auch nochmal anderen! Kommentare sind von mir..ich übernehme dafür aber keine Verantwortung :ROFLMAO:

Aufgabe war: einen REAL Datenwert alle 100ms in ein Array in einem Datenbaustein (DB10) abzulegen, wenn das Startsignal E136.0 da ist.

DB10 ist erstellt. Array im DB10 auch erstellt mit Array[0..49] Datentyp REAL
Das heißt es gibt jetzt im DB10:
DB10.DBD0
DB10.DBD4
DB10.DBD8
...
..
.
Code:
                UN E136.0                   //Wenn kein Startsignal, Resete alle Laufvariablen
                SPB M001

                L Z1                            //Zähler Z1 startet, wenn E136.0 da ist und wird all 100ms vorwärts  gezählt
                LMW2                         // MW2 Hilfsmerke
                >I
                =M0.2                        //Wenn M0.2=1, dann wurde Z1 hochgezählt
    
                UN M0.2                     // Wenn Zähler noch nicht erhöht springe zu NOP 0
                SPB M002

                LZ1                            //Z1 und MW2 abgleichen
                T MW2

                L Z1                           //Bsp. Z1=1
                L L#4                         // L4 ist eine Integer-Konstante, L#4 ist einen Doppelintegerkonstante.
                *D                             // Datenformat muss beibehalten werden.
                L 0                             //Offsetwert (hier NULL, aber ich brauch den später noch), wenn zB.  Array im DB nicht bei DB10.DBD0 sondern bei zB. DB10.DB4  anfängt-> L 4
                +D
                SLD 3
                T #DB_Addr               //  #DB_Addr. ist eine Temporäre Variable wird im FC Baustein in der oberen  Leiste eingetragen und gilt nur für diesen Baustein (Quasi  lokale Variable) In dieser steht jetzt die Datenbausteinadresse!
    
                L DB1.DBD8                // Hier steht der zu speicherne Messwert
                AUF DB10                  //Ruft den DB10 auf, somit weiss der #DB_Addr auf welchen DB sich die  Adresse beziehen soll
                T DBD[#DA_Addr]      //  Tranferiert den Wert aus DB1.DBD8 in den DB10 mit der  Datenbausteinadresse aus #DA_Addr

M001:       L 0
                T MW2

M002: NOP 0
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Auch bei der speicherindirekten Adressierung muß die Adresse im Doppelwordformat als Bitadresse angegeben werden. Nach dem "+D" fehlt noch ein "SLD 3" (oder mit 8 multiplizieren)
Code:
L Z1 //Bsp. Z1=1 
L L#4 // L4 ist eine Integer-Konstante, L#4 ist einen Doppelintegerkonstante. 
*D // Datenformat muss beibehalten werden. 
L 0 //Offsetwert (hier NULL, aber ich brauch den später noch), wenn zB. Array im DB nicht bei DB10.DBD0 sondern bei zB. DB10.DB4 anfängt-> L 4 
+D 
SLD 3 // Byteoffset --> P#x.0
T #DB_Addr // #DB_Addr. ist eine Temporäre Variable wird im FC Baustein in der oberen Leiste eingetragen und gilt nur für diesen Baustein (Quasi lokale Variable) In dieser steht jetzt die Datenbausteinadresse! 

L DB1.DBD8 // Hier steht der zu speicherne Messwert 
AUF DB10 //Ruft den DB10 auf, somit weiss der #DB_Addr auf welchen DB sich die Adresse beziehen soll 
T DBD[#DA_Addr] // Tranferiert den Wert aus DB1.DBD8 in den DB10 mit der Datenbausteinadresse aus #DA_Addr

Harald
 
Ja stimmt, hab es heute morgen auf der Arbeit, zum Glück rechtzeitig noch gemerkt ;)

Werde es ín meiner Zusammenfassung korrigieren!
 
Zurück
Oben