TIA Dynamische symbolische Adressierung

JanB1

Well-known member
Beiträge
376
Punkte Reaktionen
55
Zuviel Werbung?
->Hier kostenlos registrieren
Hallo zusammen

Da man ja mit der Zeit gehen will und bei Siemens im Programmierleitfaden schon seit längerem empfohlen wird, dass man symbolisch Adressieren und von der Verwendung von Zeigern absehen soll (und dass man kein AWL mehr verwenden soll, aber das ist ein anderes Thema), bin ich dran unsere Datenstruktur für neue Projekte Stück für Stück anzupassen (Rom wurde ja auch nicht an einem Tag gebaut und alte Gewohnheiten halten sich hartnäckig).

Ich habe nun aber folgenden Anwendungfall, bei dem ich nicht weiss, wie ich das mit symbolischer Adressierung ordentlich lösen soll.

Wir haben immer mehrer Förderpositionen in einem DB abgelegt, pro Förderbereich ein Positions-DB.
Nun hatten wir bisher Funktionen, welche indirekt über einen Index-DB geprüft haben, in welchen DB eine Position abgelegt ist. Danach wurde der entsprechende DB nach der Position durchsucht. Wurde die Position gefunden, so wurde der Zeiger für die weitere Verwendung weitergegeben.
Kommt zum Beispiel für den Handbetrieb von einem MoPa zur Anwendung, da ich das MoPa ja irgendwo einstecken kann und auf jede Position der Anlage zugreifen will.

Im Positions-DB hab ich jetzt bereits alle Positionen in ein Array gepackt. Dahingehend also bereits kein Zeiger mehr nötig.
Aber: wie realisiere ich jetzt den Schritt vom Index-DB in den Positions-DB? Kann ich irgendwie eine symbolische Adressierung, bestehend aus DB und Variable zusammensetzen?
 

JSEngineering

Well-known member
Beiträge
855
Punkte Reaktionen
189
Funktioniert es nicht, statt mehrerer DBs mit der gleichen Datenstruktur ein großes Array in einem großen DB anzulegen? Und dieses Array enthält dann den Positions-DB-Inhalt als Struktur/UDT.
 
OP
JanB1

JanB1

Well-known member
Beiträge
376
Punkte Reaktionen
55
Zuviel Werbung?
->Hier kostenlos registrieren
Dann hätte ich bei grösseren Anlagen einen DB, welcher zu gross wird.
Wir haben pro Position ca. 600Bytes, mit Reserve 1000 Bytes.
Alleine auf einer kleinen Anlage habe ich bereits 65 Positionen, dann wären wir bereits auf 65'000 Bytes...
 

JSEngineering

Well-known member
Beiträge
855
Punkte Reaktionen
189
 

TP-Inc

Well-known member
Beiträge
515
Punkte Reaktionen
98
Ich kann dir nicht ganz folgen was du mit Index-DB meinst. Was zeigt der Index an? Optimierte DBs können bis zu 16MB groß sein. Ein Symbol zur Laufzeit zusammenbasteln und darauf zugreifen geht nicht.
Und im Handbetrieb die ganze Anlage zu steuern egal wo man steckt? Macht das Sinn?
 
OP
JanB1

JanB1

Well-known member
Beiträge
376
Punkte Reaktionen
55
Zuviel Werbung?
->Hier kostenlos registrieren

Selbst wenn ich das so umsetzte ist so ein DB viel zu gross für ein anständiges Handling.
Dann wird das ein "Suche die Position in DB".

Gibts denn keine andere Möglichkeit als einen Monster-DB mit >100kB zu erstellen?
 
OP
JanB1

JanB1

Well-known member
Beiträge
376
Punkte Reaktionen
55
Ich kann dir nicht ganz folgen was du mit Index-DB meinst. Was zeigt der Index an? Optimierte DBs können bis zu 16MB groß sein. Ein Symbol zur Laufzeit zusammenbasteln und darauf zugreifen geht nicht.

Im "Index DB" ist jeder Förderbereich, die erste und die letzte Positionsnummer im Bereich sowie die DB-Nummer aufgeführt. Damit lässt sich über indirekte Adressierung anhand der gesuchten Positionsnummer auslesen, in welchem DB die Position zu finden ist.

Und im Handbetrieb die ganze Anlage zu steuern egal wo man steckt? Macht das Sinn?
Natürlich ist es Softwaretechnisch verriegelt, dass eine von dieser Steckstelle nicht einsehbare Position von Hand nicht angesteuert werden kann. Aber grundsätzlich will ich ja 1 MoPa überall auf der Anlage einstecken und in Abhängigkeit der Stecksellen-ID (die ich ja auswerten kann) eine Position bedienen.
 

bcp

Member
Beiträge
7
Punkte Reaktionen
0
Funktioniert es nicht, statt mehrerer DBs mit der gleichen Datenstruktur ein großes Array in einem großen DB anzulegen? Und dieses Array enthält dann den Positions-DB-Inhalt als Struktur/UDT.
Die Variante ist übersichtlich und das würde ich genau so machen.

Selbst wenn ich das so umsetzte ist so ein DB viel zu gross für ein anständiges Handling.
Dann wird das ein "Suche die Position in DB".

Gibts denn keine andere Möglichkeit als einen Monster-DB mit >100kB zu erstellen?
Wenn du unbedingt mehrere DBs haben willst könntest du diese per Peek und Poke absolut per DB-Nummer beschreiben.
Dann bist du aber wieder bei einem alten Programmierstil...
 

escride1

Well-known member
Beiträge
568
Punkte Reaktionen
120
Zuviel Werbung?
->Hier kostenlos registrieren
So spontan würde ich das in dieser Richtung lösen, dann kann der "Master-DB" auch nicht zu groß werden sondern es wird wie bisher auch je Bereich ein DB genutzt werden.

Einen FB/FC erstellen der als IN-Schnittstelle den Positions-DB bekommt. Dieser FB/FC sucht sich in dem DB die Position raus. und gibt die gewünschten Daten raus.
Dann in einem Ablaufbaustein nacheinander diesen FB/FC mit jeweils einem anderen DB aufrufen, also die Förderbereiche.
Das was bisher im Index-DB steht wird dem FB/FC dann eben übergeben und er würde anhand dieser Daten die im Programm angegeben sind wissen ob die Grundinfo in seinem angepinnten DB liegen kann (Vergleich Gesuchteposition >=100 <=150 wenn er 100 bis 150 beinhaltet), diese Infos stehen soweit ich verstanden habe ja im Index-DB der nun als feste Werte an die Schnittstelle kommt.

Dann hat man alles symbolisch, es ist übersichtlich und man kann so viele DBs haben wie man lustig ist und je Förderbereich wird der entsprechende Positions-DB mit diesem FB/FC abgesucht.

Im Prinzip ist also das alles komplett ausprogrammiert und dürfte etwas länger dauern in der Programmierung, dafür aber bleibt alles symbolisch und wird daher diese Vorteile die Siemens nennt (wie kürzere Zykluszeiten) haben können, zumindest vermeintlich.


Okay, das ist nun ein wenig durcheinander, aber ich hoffe der Grundgedanke kommt durch, des Pils auf jeden Fall! 🍻
 

rostiger Nagel

Forums-Knochenbrecher Mod-Trainer
Teammitglied
Beiträge
13.795
Punkte Reaktionen
3.916
Du könntest es vielleicht auch mit Any Zeigern lösen.
Du legst dir ein Array von Any Zeigern an.

Code:
    HeizungUnten    Struct               
    TO    Array[1..8] of DB_ANY        Any Zeiger PID_Compact Heizung 1..8 unten
    TO[1]    DB_ANY                    Any Zeiger PID_Compact Heizung 1 unten
    TO[2]    DB_ANY                    Any Zeiger PID_Compact Heizung 2 unten
    TO[3]    DB_ANY                    Any Zeiger PID_Compact Heizung 3 unten
    TO[4]    DB_ANY                    Any Zeiger PID_Compact Heizung 4 unten
    TO[5]    DB_ANY                    Any Zeiger PID_Compact Heizung 5 unten
    TO[6]    DB_ANY                    Any Zeiger PID_Compact Heizung 6 unten
    TO[7]    DB_ANY                    Any Zeiger PID_Compact Heizung 7 unten
    TO[8]    DB_ANY                    Any Zeiger PID_Compact Heizung 8 unten

Diese musst du einmal Füttern, das kannst du ja im OB100 machen

Code:
//Any Zeiger umladen
//Heizung unten
    "19x-GDB".HeizungUnten."TO"[1] := "191-TDB_71";
    "19x-GDB".HeizungUnten."TO"[2] := "192-TDB_71";
    "19x-GDB".HeizungUnten."TO"[3] := "193-TDB_71";
    "19x-GDB".HeizungUnten."TO"[4] := "194-TDB_71";
    "19x-GDB".HeizungUnten."TO"[5] := "195-TDB_71";
    "19x-GDB".HeizungUnten."TO"[6] := "196-TDB_71";
    "19x-GDB".HeizungUnten."TO"[7] := "197-TDB_71";
    "19x-GDB".HeizungUnten."TO"[8] := "198-TDB_71";

Dann kannst du auf diese per Index zugreifen, im Parameter dataTO des Heizungsbaustein
ist der PID_Compact parametriert

Code:
FOR #tmpZone := 1 TO 8 DO
    //Verwaltung Heizung unten
    #HeizungUnten[#tmpZone](dataLocal  := "19x-GDB".HeizungUnten.Data[#tmpZone],
                            dataGlobal := "005-GDB".Heizung,
                            dataTO     := "19x-GDB".HeizungUnten."TO"[#tmpZone]);
        
    //Verwaltung Heizung oben
    #HeizungOben[#tmpZone](dataLocal  := "19x-GDB".HeizungOben.Data[#tmpZone],
                           dataGlobal := "005-GDB".Heizung,
                           dataTO     := "19x-GDB".HeizungOben."TO"[#tmpZone]);
END_FOR;

Vielleicht hilft dir das ein wenig bei deiner Neustruckturierung
 
OP
JanB1

JanB1

Well-known member
Beiträge
376
Punkte Reaktionen
55
Zuviel Werbung?
->Hier kostenlos registrieren
Okay, das ist nun ein wenig durcheinander, aber ich hoffe der Grundgedanke kommt durch, des Pils auf jeden Fall! 🍻

So was in der Art hatte ich mir auch schon vorgestellt. Das müsste ich dann halt aber für jedes Projekt jeweils wieder anpassen, was ich irgendwie nicht so schön finde. 😬
 

escride1

Well-known member
Beiträge
568
Punkte Reaktionen
120
So was in der Art hatte ich mir auch schon vorgestellt. Das müsste ich dann halt aber für jedes Projekt jeweils wieder anpassen, was ich irgendwie nicht so schön finde. 😬
Die Anpassung hält sich aber in Grenzen. Für neue Projekte müsstest Du nach altem Schema den Index-DB mit mehr Werten füttern und einen DB anlegen.
Hier müsstest Du den DB anlegen und ein Netzwerk erstellen. So viel Unterschied wird da dann nicht mehr sein denke ich, aber für mich sind hier einige Unbekannte die ich natürlich nicht überblicken kann so wie Du :).
 

Schievel

Well-known member
Beiträge
67
Punkte Reaktionen
10
Ich bin mir nicht ganz sicher, was du genau machen willst, aber ich probier es mal.
Wenn ich dich richtig verstehe hast du frueher einen Index-DB gehabt. Da standen frueher die DB-Nummern der DB die Positionen enthalten drin und ein Hinweis darauf welche Positionen in den DBs drin sind. (Nummer der ersten und letzten Position)
Du hast frueher dann im Index DB eine Suche Anhand der gesuchten Postitionsnummer gemacht und die Suche hat dir die DB-Nummer ausgespuckt. Daraus hast du dir dann einen Any-Pointer gebastelt, mit dem auf den jeweiligen Positionen-DB zugegriffen und dort dann die gesuchte Position rausgesucht.
So hab ich das Verstanden.

Das Problem ist jetzt, das du dir in der neuen sauberen TIA-Welt keinen Any-Pointer basteln willst. Das ganze geht jetzt immernoch so, sogar einigermassen sicher, dass man nicht ausversehen im Nirvana landet und auch symbolisch. Man muss sich allerdings ein halbes Bein aussreissen, damit man da hin kommt wo man will.
Also, wenn du dir dieses Anwendungsbeispiel von Siemens anguckst zur Venwendung von DB_ANY machen die da was ganz aehliches, naemlich in einem DB mehrere Referenzen auf Datenbausteine in Form von DB_ANY ablegen und diese dann mit einem zwischengeschalteten Konvertierungsbaustein ihren Funktionsbausteinen von Technologieobjekten uebergeben.
https://cache.industry.siemens.com/...1861/v2/109750880_use_data_type_DB_ANY_de.pdf
Der unterschied ist, dass man DB_ANY wohl einfach als ein Technologyobjekt uebergeben kann, mit Global-DB geht das aber nicht so einfach.

Der IndexDB besteht dazu aus einem Array of Stuct. In einem Arrayelement ist immer ein DB_ANY vorhanden, die untere und obere Positionsnummer und die Funktionsgruppe.
Das Array ist iterable und daher kannst du schonmal bequem mit For-Schleifen suchen. Mit LOWER/UPPER_BOUND sogar ohne projektspezifische Anpassungen.
Initialisiert wird der IndexDB jetzt mit Zeigern auf die PositionsDBs, also ein Netzwerk mit Anweisungen in dem Stil:
"IndexDB".Index[0].DBPointer := "PosiDB1";
Der DBPointer ist vom Typ DB_ANY.
Der Suchbaustein iteriert nun ueber die Arrayeintraege, findet seinen Eintrag und kopiert den DBPointer in einen Ausgang FoundDB vom Typ DB_ANY.
Soweit die einfache Seite, frueher gab es halt DB-Nummern, die man in den IndexDB eingetragen hat, jetzt gibt es direkt Zeiger.

Die Seite mit den PositionsDB ist etwas komplizierter. Zuerst einmal muessen die vom richtigen Typ sein. Ein normaler globaler DB geht nicht, weil dem Compiler zur Uebersetzungszeit nicht bekannt ist, was in diesem steht, wenn ein Baustein nur den DB_ANY auf den Baustein uebergeben bekommt. Ab hier koenntest du halt mit Peek und Poke weitermachen wenn auf den PositionenDB nicht optimiert zugegriffen wird.
Stattdessen legst du einen UDT fuer diesen PositionsDB an, das kann ein Array of Int sein mit den Positionen drin oder irgendwas.
Mit dem geschaffenen UDT legst du jetzt einen DB an, also genauso wie bei einem Global-DB, nur dass du bei dem Erstellen des DB in dem Dropdown die UDT angibst statt "Global-DB".
Das machst du fuer alle PositionsDBs, immer mit dem gleichen UDT.
Der Baustein, der nun in dem PositionsDB suchen soll, bekommt jetzt den FoundDB von vorhin uebergeben, und wandelt diesen in einen Variant um. Das geht nicht mit einem Global-DB, daher der Aufwand mit dem UDT-DB.
#myVariant := DB_ANY_TO_VARIANT(in := #myDB, err => #dump);
Sollte dabei die Anweisung Fehler 8155 zurueckgeben liegt das daran, dass Siemens ein kleines Ei gelegt hat. Einfach so vorgehen wie in der Hilfe von DB_ANY_TO_VARIANT:
DB_ANY_TO_VARIANT: DB_ANY in VARIANT konvertieren (S7-1200, S7-1500)
1) Die Ursache für die Ausgabe des Fehlercodes #8155 liegt darin:
Es wurde ein PLC-Datentyp (UDT1) deklariert und anschließend ein Datenbaustein (DB2) vom Datentyp "UDT1" erstellt. In der Variablentabelle gibt es eine Variable (3) vom Datentyp DB_ANY. In einem Programmbaustein (4) wurde anschließend die Anweisung "DB_ANY_TO_VARIANT" aufgerufen und am Parameter IN mit der Variable (3) versorgt. Beim Ausführen liefert die Anweisung "DB_ANY_TO_VARIANT" den Fehlercode 16#8155.
Zur Auflösung des Fehlercodes gehen Sie folgendermaßen vor:
  1. Legen Sie eine Funktion (FC5) an und deklarieren Sie an der InOut-Schnittstelle eine Variable vom Datentyp VARIANT.
  2. Legen Sie eine weitere Funktion (FC6) an und rufen Sie darin den FC5 auf.
  3. Legen Sie im FC6 in der Temp-Schnittstelle eine Variable (7) vom Datentyp "UDT1" an.
  4. Versorgen Sie die InOut-Schnittstelle des FC5 mit der Variable (7).
  5. Übersetzen und laden Sie die beiden Bausteine (FC5 und FC6) in Ihre CPU. Sie brauchen diese Bausteine (FC5 und FC6) nicht im Anwenderprogramm aufzurufen.

Um jetzt mit dem enthaltenen Daten zu arbeiten, kann man einfach den Variant dereferenzieren:
VariantGet(SRC:=#myVariant,
DST=>#myValues);

So holst du dir die in dem DB gespeicherten Werte und speichest sie in myVariant. Um jetzt in den Positionen einen Eintrag zu suchen und dann an eine NC oder so weiterzugeben, reicht das ja. Um direkt im PositionenDB zu arbeiten, kannst du dir eine Referenz auf den DB holen, in dem Stil:
#myReference ?= #myVariant;
#myReference^.pos2 := 0815;

Der myRefence dann im Temp der Bausteinschnittstelle deklarieren als REF_TO "PosDB"

Ich sehe bei mir jetzt im nachhinein, dass der UDT den ich angelegt habe natuerlich ein bisschen dumm gewaehlt ist, da man nicht ueber ihn iterieren kann. Also lieber ein Array of irgendwas in den UDT klatschen.

Um flexibler zu bleiben koennte man auch den UDT fuer den PositionenDB nur als Array of Byte machen. Dann liest man zuerst in ein Array of Byte aus wie zuvor auch. Danach koennte man aber mit Deserialize dieses Array of Byte einfach auf eine andere Struktur klatschen, aehnlich wie frueher Blockmove. Das vorgehen ist aber aus dem Stoff, aus dem Aufrufe von OB121 gemacht sind, also lieber vorsichtig sein. Muss AFAIK auch mit nichtoptimierten Zugriff gemacht werden, sonst passt ja beim Deserialize nichtsmehr.

Hoffe das ist jetzt das, was du eigentlich haben willst.
 

Anhänge

  • Aufrufe.jpg
    Aufrufe.jpg
    33,1 KB · Aufrufe: 14
  • Daten rein.jpg
    Daten rein.jpg
    44,6 KB · Aufrufe: 14
  • Daten raus.jpg
    Daten raus.jpg
    55,5 KB · Aufrufe: 14
  • PosDB.jpg
    PosDB.jpg
    39,3 KB · Aufrufe: 13
  • UDTfuerPosDB.jpg
    UDTfuerPosDB.jpg
    25,1 KB · Aufrufe: 14
  • REFDBundSucheIn INdex.jpg
    REFDBundSucheIn INdex.jpg
    99,6 KB · Aufrufe: 15
  • INDEXdb.jpg
    INDEXdb.jpg
    41,9 KB · Aufrufe: 16
  • DB_ANY dereferenzieren.jpg
    DB_ANY dereferenzieren.jpg
    84,3 KB · Aufrufe: 13
Zuletzt bearbeitet:
OP
JanB1

JanB1

Well-known member
Beiträge
376
Punkte Reaktionen
55
Zuviel Werbung?
->Hier kostenlos registrieren
Ich bin mir nicht ganz sicher, was du genau machen willst, aber ich probier es mal.
Wenn ich dich richtig verstehe hast du frueher einen Index-DB gehabt. Da standen frueher die DB-Nummern der DB die Positionen enthalten drin und ein Hinweis darauf welche Positionen in den DBs drin sind. (Nummer der ersten und letzten Position)
Du hast frueher dann im Index DB eine Suche Anhand der gesuchten Postitionsnummer gemacht und die Suche hat dir die DB-Nummer ausgespuckt. Daraus hast du dir dann einen Any-Pointer gebastelt, mit dem auf den jeweiligen Positionen-DB zugegriffen und dort dann die gesuchte Position rausgesucht.
So hab ich das Verstanden.

(...)

Hoffe das ist jetzt das, was du eigentlich haben willst.

Ja, das hast du so richtig verstanden. Das sieht dann so aus:
Siemens.Automation.Portal_OM4BZ31i38.png

Besten Dank(!!!) für deine Erläuterungen, ich werde dies mal so prüfen/versuchen sobald ich wieder im Büro bin (aktuell auf Baustelle bei nem anderen Projekt).
 

Schievel

Well-known member
Beiträge
67
Punkte Reaktionen
10
Bitte bitte. War nicht ganz Altruistisch, auch ich habe noch einiges zu lernen ueber die Zeiger in TIA.
Mir mutet es nur so an, als habe sich Siemens da am Anfang gedacht "gibt keine Zeiger mehr, so wie bei Java, basta!" und jetzt bauen sie jedes mal, wenn einer nach einer Funktion schreit die frueher mal ging aber jetzt nichtmehr, irgeindeine neue Funktion mit Zeigern ein.
 
OP
JanB1

JanB1

Well-known member
Beiträge
376
Punkte Reaktionen
55
Ja, das Gefühl bekomme ich langsam auch. Das ist irgendwie nicht ganz zu Ende gedacht. Oder es geht zwar, bedingt aber dass man seine ganze Code-Base über den Haufen schmeisst. Was halt dazu führt, dass nur zögerlich umgestellt wird.

Auch dass sie teils bei neuen Funktionen absichtlich AWL benachteiligen find ich etwas frech. Aber ist wahrscheinlich auch auf Grund der "deprecated" Klassifizierung von IL (AWL) gemäss IEC 61131-3 mit der Revision 3 von 2012.
 

Jinto

Well-known member
Beiträge
49
Punkte Reaktionen
10
Zuviel Werbung?
->Hier kostenlos registrieren
Bitte bitte. War nicht ganz Altruistisch, auch ich habe noch einiges zu lernen ueber die Zeiger in TIA.
Mir mutet es nur so an, als habe sich Siemens da am Anfang gedacht "gibt keine Zeiger mehr, so wie bei Java, basta!" und jetzt bauen sie jedes mal, wenn einer nach einer Funktion schreit die frueher mal ging aber jetzt nichtmehr, irgeindeine neue Funktion mit Zeigern ein.
Moderne Prozessorarchitekturen sind nicht auf direkte Adressierung optimiert. Das war einfach eine technische Notwendigkeit befürchte ich.

Z.b. Booleans sind vom Konzept her 1 bit groß. In einem 64-bit Prozessor kann aber ein einzelnes Bit nicht wirklich adressiert werden, da bräuchte man eine gigantische Anzahl an Adressregistern. Also belegt ein Boolean dort halt nativ 64 bit Speicher, weil das die kleinste adressierbare Einheit im Speicher ist. Kleiner geht es dann nur noch mit komplizierter Adressarithmetik.

Aber diese komplizierte Adressarithmetik ist auch nicht beliebig komplex, wenn sie schnell sein soll. Man würde versuchen, gleiche Datentypen in einen 64-bit Wort zu packen (z.B. 64 Booleans oder 8 Bytes oder 4 Words...).

Wo das hinführt kann man dann bei der Programmierung sehen. Entweder ich mache alles symbolisch, dann stellt der Compiler sicher, dass das Symbol immer an die korrekte Stelle im Speicher zeigt, aber ich weiß als Programmierer nicht welche Stelle (Adresse) das gerade ist. Oder aber man setzt noch einen Emulator oben drauf, der es dem Programmierer erlaubt virtuelle Adressen zu definieren, die das Programm dann aufwändig durch Adress-Mapping bei der Programmausführung auflösen muss.

Dieses emulieren macht direkt-Zugriffe ungeeignet, weil unnötig langsam. Besser man überlässt die Adressierung dem Compiler. Der Compiler neigt aber dazu, bei kleinen Änderungen im Programm, die Speicheradressen gründlich durcheinander zu bringen.

Mal angenommen das Programm nutzt folgende Tags (Symbole):

tag1 %MB0
tag2 %MB1
tag3 %MB2
tag4 %MB3
tag5 %MB4
tag6 %MB5
tag7 %MB6
tag8 %MB7
tag9 %MW8

Dann würde der Compiler das vielleicht so ablegen (Annahme die erste nutzbare Speicheradresse für Daten ist 0x4000.0000.0000.0000):

tag1... tag8 sind vom gleichen Typ und passen hintereinander in das 64-bit-Wort an Adresse 0x4000.0000.0000.0000.
tag9 ist vom gleichen Typ und passt in das 64 bit Wort an Adresse 0x4000.0000.0000.0001.

Wenn ich als Programmierer jetzt direkt addressiert auf tag9 zugreifen möchte, dann muss das gesamte 64 bit Wort an Adresse 0x4000.0000.0000.0001 geladen werden, und dann wird mit Bitmaske 1111.1111.1111.1111...0000 verundet +shift um den Wert für tag9 zu erhalten.

Wenn ich jetzt weitere Symbole einfüge passiert folgendes:

tag1 %MB0
tag2 %MB1
tag3 %MB2
tag4 %MB3
tag5 %MB4
tag6 %MB5
tag7 %MB6
tag8 %MB7
tag9 %MW8
tag10 %M10.0
tag11 %MB11

Der Compiler wird jetzt vermutlich alles etwas anders anordnen:

tag10 ist vom gleichen Typ und passt hintereinander in das 64-bit-Wort an Adresse 0x4000.0000.0000.0000.
tag1... tag8 ist vom gleichen Typ und passt hintereinander in das 64-bit-Wort an Adresse 0x4000.0000.0000.0001.
tag11 ist vom gleichen Typ und passt hintereinander in das 64-bit-Wort an Adresse 0x4000.0000.0000.0002.
tag9 ist vom gleichen Typ und passt hintereinander in das 64-bit-Wort an Adresse 0x4000.0000.0000.0003.

Wenn ich als Programmierer jetzt direkt addressiert auf tag9 zugreifen möchte, dann muss das gesamte 64 bit Wort an Adresse 0x4000.0000.0000.0003 geladen werden, und dann wird mit Bitmaske 1111.1111.1111.1111...0000 verundet + shift um den Wert für tag9 zu erhalten.

Zeiger sind nichts anderes als direkte (oder virtuelle) Speicheradressen. Also gefährlich, weil man nie weiß ob die gerade an die Stelle im Speicher zeigen, die der Programmierer gemeint hat. Außer man gaugelt dem Programmierer einen Zeiger vor, oder macht diesen so Typ/Instanz-Sicher, das garantiert nur das vom Programmierer gewünschte Datum erreicht werden kann. Aber das kostet halt ordentlich Rechenzeit.
 
Zuletzt bearbeitet:

NBerger

Well-known member
Beiträge
616
Punkte Reaktionen
147
Halte ich jetzt mal für mindestens grenzwertig bis falsch.

Beispiel1: Ein Bit in einem DB (optimiert) belegt ein Byte (Laut Hersteller: Siemens).
Beispeil2: Der Speicher wird Zugriffoptimiert verwaltet Bytes zusammen Worte zusammen ... (Laut Hersteller: Siemens).

Da gibt's sogar entsprechende Doku zu.

Die SPS wird etwas anders verwaltet als PC's...
Mit Programm start sind hier die Adressen und Speicherbereiche eindeutig bekannt! Zur Laufzeit kommt es so nicht zuunvorhergesehenen Engpässen.
 

Schievel

Well-known member
Beiträge
67
Punkte Reaktionen
10
ein bit belegt ein Byte und zwei Bit belegen immernoch nur ein Byte.
Es stimmt schon, dass die Frage wie die Daten abgelegt werden bei optimierten Bausteinen dem Compiler überlassen ist und man da schlecht wirkliche Zeiger zulassen kann, wenn man irgendeine Kleinigkeit ändert und der Compiler organisiert den Speicher um.
 
Oben