TIA Pointer

_Mike_

Level-2
Beiträge
41
Reaktionspunkte
4
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Forum,

meine Hardware: CPU 315-2 PN/DP (6ES7 315-2EH14-0AB0)
meine Software: TIA V14 SP1

Meine Aufgabe, ist es einen Pointer zusammenzustellen. Aber der Pointer soll nicht komplett absolut adressiert sein, sondern der FB (mit dem Pointeraufruf) soll seinen eigene Instanzdatenbausteinnummer selbst auslesen, und den Pointer die DB Nummer mitteilen (als Variable). Wie ich die Instanzdatenenbausteinnummer des FBs auslese habe ich herausgefunden.

Code:
VAR_INPUT 
X :INT; 
END_VAR 
 
VAR_OUTPUT 
DBNR :INT; 
END_VAR 
 
VAR_TEMP 
//--------------------------------------------------- 
// Definition einer Hilfsvariablen und einer eigenen 
// Datentypsicht auf den Datentyp ANY 
//--------------------------------------------------- 
TempPointer              :ANY;              // Hilfsvariable 
AnyPointer AT TempPointer: STRUCT 
                              BYTE0 :BYTE;  // Byte 0 
                              TYP   :BYTE;  // Byte 1        Daten/Parametertyp 
                              ANZ   :WORD;  // Byte 2+3      Länge der Variablen 
                              DBNR  :WORD;  // Byte 4+5      DB-Nummer 
                              BZ    :DWORD; // Byte 6 bis 10 Bereichszeiger 
                           END_STRUCT; 
END_VAR 
 
BEGIN 
 
TempPointer := X;                     // Hilfsvariable mit Zeiger auf 
              // Eingang X laden 
 
DBNR := WORD_TO_INT(AnyPointer.DBNR); // Zugriff auf Byte 4 und 5 
 
END_FUNCTION_BLOCK

Das funktioniert auch alles soweit. Das Programm liest die Datenbausteinnummer des FBs aus.

Mein Frage, wie kann ich die ausgelesene DB Nummer an den Pointer anbinden.

Zum Beispiel
p#Meineausgelesenedbnummer.dbx48.0 byte 48

Folgende Beiträge zu dem Thema habe ich schon gelesen:
https://www.sps-forum.de/faq/12923-zeiger-fuer-datentypen.html
https://www.sps-forum.de/faq/8887-pointer-zeiger-fifo-lifo.html
https://www.sps-forum.de/simatic/47446-db-variabel-beschreiben-und-lesen.html
https://support.industry.siemens.co...inter-zusammengestellt-werden-?dti=0&lc=de-WW
https://support.industry.siemens.co...in-s7-scl-programmiert-werden-?dti=0&lc=de-WW
 
Mein Frage, wie kann ich die ausgelesene DB Nummer an den Pointer anbinden.
Ganz einfach die DB-Nummer in die für die DB-Nummer vorgesehene Speicherstelle in der AnyPointer-Struktur eintragen?

Wo ist denn überhaupt Dein ANY-Pointer?
Kannst Du nicht den Wert Deines Objekts/Variable ganz normal übergeben?

Wozu soll das ganze gut sein? Willst Du andere Bausteine einladen, in den Instanzdaten der Instanzen des FB 'rumzumachen? Ist Dir auch klar, daß bei Adressierung von Instanzdaten von als multiinstanz angelegten FB-Instanzen zu der absoluten Adresse noch der multiinstanz-Offset der jeweiligen Instanz dazukommt? Ist Dir auch klar, daß außer Dir fast niemand die Zugriffe auf solcherart adressierte Variablen in Deinem Programm finden wird, und in einem halben Jahr auch Du selber nichts mehr finden wirst? Viel Spaß bei der zukünftigen Fehlersuche ;)

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich will einen Standard Baustein schreiben der Buswerte ausliest. Dann moechte ich die Buswerte mit der RDREC Funktion auslesen. Um die Buswerte zu speichern brauchen wir den Pointer.
Die Bytegroesse und das Offset wird sich bei dem Pointer nicht Aendern der bleibt gleich. Aber er soll kein feste IDB Nummer geben. Weil der Standard Baustein in jedes beliebiges Projekt verwendet werden soll, ohne das man die IDB Nummer vorgibt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich will einen Standard Baustein schreiben der Buswerte ausliest. Dann moechte ich die Buswerte mit der RDREC Funktion auslesen. Um die Buswerte zu speichern brauchen wir den Pointer.
Um aus Deinem FB den universellen RDREC-Lesebaustein aufzurufen brauchst Du keinen Pointer basteln. Du kannst dem Lesebaustein beim Aufruf direkt symbolisch den eigenen Speicherbereich übergeben (als STRUCT oder UDT oder ARRAY oder ANY), wo RDREC den RECORD hinspeichern soll.

Harald
 
Hab es hinbekommen, ja hab die Variablen als Struct angelegt im Static- Bereich. Und schon konnte ich die Variable am Record anbinden.
 
Jetzt muss ich ein Bytedreher machen. Mit dem Datentyp: INT in SCL. Und ich habe eine 315-2 PN/DP CPU.
ROR funktioniert in INT nicht und SWAP gibt es in der 300er Reihe nicht.
Worauf ich dann gekommen bin:

Code:
 #Cos_Phi_Generator_Word := ROR(IN := #Digureg_Sendedaten.Cos_Phi_Generator, N := 8);
#Cos_Phi_Generator_INT := WORD_TO_INT(#Cos_Phi_Generator_Word);

Mich stört aber an der Lösung das ich in AWL 3 Befehle brauche. Wenn der SCL Code dann Übersetztz wird generiert er viel mehr AWL Zeilen.
Wir wollen aber einen Kompakten Code schreiben, deswegen Zielen wir da ein wenig am Ziel vorbei.
Der Grund das wir in SCL schreiben ist das wir einige Berechnungen und Umwandlungen haben die in SCL deutlich Kompakter gehen.

Gibt es für die 300er CPU eine Kompaktere Lösung?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... das ist ein generelles Problem. Manche Sachen werden in SCL schicker umgesetzt als du es jemals in AWL könntest - manche Sachen nicht.
In deinem Code-Schnipsel wird der Mehr-Code aus meiner Sicht daher rühren, dass du eine Struktur-Variable im ROR hast - damit hat der SCL-Codewandler ein bißchen Probleme.

Gruß
Larry
 
SWAP gibt es in der 300er Reihe nicht.
Du könntest selber eine SWAP-Function in AWL schreiben und in SCL aufrufen:
Code:
FUNCTION "SWAP_I" : INT
TITLE =Bytes in INT tauschen

VAR_INPUT
  IN : INT ;
END_VAR
BEGIN
NETWORK
      L     #IN;
      TAW   ;
      T     #RET_VAL;
END_FUNCTION
Code:
// Aufruf in SCL
Int2 := SWAP_I(IN:=Int1);


ROR funktioniert in INT nicht
Du könntest einfach Typecasts INT_TO_WORD / WORD_TO_INT einsetzen:
Code:
#Cos_Phi_Generator_INT := WORD_TO_INT(ROR(IN := INT_TO_WORD(#Digureg_Sendedaten.Cos_Phi_Generator), N := 8));
Allerdings compiliert der SCL-V5.3-Compiler die ROR-Anweisung äußerst umständlich. :roll: (Ob der TIA-SCL-Compiler das besser macht?? Weiß ich nicht.)
Wenn man den Byte-Swap via SHL und SHR formuliert und dem SCL-Compiler auch noch etwas unter die Arme greift und ihm den Weg via 32-Bit-Operationen zeigt, dann erzeugt er wesentlich kürzeren relativ kompakten AWL-Code :cool:
Code:
(* SCL *)
Int2 := DWORD_TO_INT(SHL(IN:=INT_TO_DWORD(Int1), N:=8) OR SHR(IN:=INT_TO_DWORD(Int1), N:=8));

(* wird von SCL V5.3 compiliert in:
      L     #Int1
      UD    DW#16#FFFF  //überflüssig
      SLD   8
      L     #Int1
      UD    DW#16#FFFF  //überflüssig
      SRD   8
      OD    
      T     #Int2
*)
Warum der SCL-Compiler INTs und WORDs bei INT_TO_DWORD bzw. WORD_TO_DWORD noch unbedingt überflüssigerweise mit 16#FFFF ver-Und-en muß das wissen wohl nur die SCL-Compiler-Programmierer. Ich weiß nicht, wie man dem SCL-Compiler das abgewöhnen kann.

Harald
 
Wir haben das ROR auch schon ohne Struktur Variable getestet. Aber wenn wir dann den Ausgang des ROR mit einer INT Varibale
verschalten, sagt TIA das die Genauigkeit des Codes verloren gehen kann. Und der Classic Codewandler zeigt das als Fehler an.

Mitlerweile sind wir zum Ergebnis gekommen das wir eine Mischung machen zwischen AWL und FUP. Die Berechnungen machen wir in einem externen Baustein in SCL.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Aber wenn wir dann den Ausgang des ROR mit einer INT Varibale
verschalten, sagt TIA das die Genauigkeit des Codes verloren gehen kann.
Also diese neuen TIA-Compiler-Warnungen :roll: - Geht TIA mittlerweile davon aus, daß der typische SCL-Programmierer gar nicht weiß was er tut? Und hat womöglich recht dabei? ;)

Mit welchem Datentyp hast Du da das ROR aufgerufen?

Harald
 
Also diese neuen TIA-Compiler-Warnungen :roll: - Geht TIA mittlerweile davon aus, daß der typische SCL-Programmierer gar nicht weiß was er tut? Und hat womöglich recht dabei? ;)

Die Hoffnung war/ist den "Komfortablen" TIA Editor zu benutzen um einen SCL Baustein für die S7-300/400 zu schreiben.
Wie machen das die PCS-7 Entwickler, wen so ein Classic Compiler nicht weiter entwickelt wird?

Ich könnte noch damit leben wenn das Befehl SWAP nachgerüstet wird, und das der Compiler mehr AWL Code daraus macht.
Dann könnte man wenigstens Kompakt in SCL programmieren.

Bram
 
Wie sehe es mit folgendem Weg aus:
- Wort in Akku (32-Bit) laden
- multiplizieren mit 65537 (alias 10001 hex)
- um 8 Bit nach rechts schieben
- Ergebnis nach Wort transferieren
?
 
Dann verstehe nicht, wieso TIA da so eine unsinnige Warnung wegen angeblich möglichem Genauigkeitsverlust ausgibt.

Nich nur TIA hat die Warnung ausgegeben, Classic hat es als Fehler angezeigt.


Wie sehe es mit folgendem Weg aus:
- Wort in Akku (32-Bit) laden
- multiplizieren mit 65537 (alias 10001 hex)
- um 8 Bit nach rechts schieben
- Ergebnis nach Wort transferieren
?

Haben wir schon getestet, aber wir wollen ganze umwandlen von Datentypen nicht. Und wir brauchen das Ergebnis in INT.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Nich nur TIA hat die Warnung ausgegeben, Classic hat es als Fehler angezeigt.
Classic: Es ist ja auch richtig den falschen Datentyp (INT) als "Fehler" anzumeckern - der Programmierer hat gefälligst eindeutig anzugeben was er will. Für ROR sind BYTE/WORD/DWORD zulässig, und wenn man INT/DINT verwenden will, dann hat man den gewünschten Typecast oder Konvertierung *_TO_* explizit anzugeben.

TIA: Aber das Verhalten von TIA mit der Einstufung als "Warnung" ist unsinnig: einerseits so zu tun als ob es die falsche bzw. ungenaue Angabe des Programmierers automatisch korrigieren könnte, andererseits aber trotzdem warnen - wenn es keine eindeutige Korrekturmöglichkeit gibt, dann soll es die automatische Korrektur besser sein lassen. Ich bin der Meinung, wenn überhaupt dann dürfte TIA implizit nur INT_TO_WORD und DINT_TO_DWORD verwenden - das ist eindeutig und da gehen keine Bits (keine "Genauigkeit" :roll: :ROFLMAO:) verloren.

Code:
myInt2 := ROR(IN := myInt1, N := 8);
[COLOR="#008000"]//Die Zeile wird in SCL Classic richtigerweise als "Fehler" angemeckert.[/COLOR]
[COLOR="#008000"]//TIA übersetzt irgendwie und gibt eine "Warnung", daß dabei "Genauigkeit" verloren gehen könnte.[/COLOR]


[COLOR="#008000"]//so wäre es in SCL Classic und TIA korrekt:[/COLOR]
myInt2 := WORD_TO_INT(ROR(IN := INT_TO_WORD(myInt1), N := 8));

[COLOR="#008000"]//(von der neumodischen Schreibweise von Variablennamen in TIA abgesehen)[/COLOR]

Harald
 
... wir wollen ganze umwandlen von Datentypen nicht. Und wir brauchen das Ergebnis in INT.
You can't have a cake and eat it. Ent oder weder. Die HochsprachenProgrammierer wissen einfach nicht, was Bits und Bytes sind. Damit sie aber dennoch das eine oder andere Stückchen Software zu einem SPS-Programm beisteuern dürfen, muss der Compiler fein aufpassen, dass sie nicht mit Befehlen wie ROR oder SWAP ein totales Chaos in der INT- und DINT-Welt anrichten.
Das waren noch Zeiten, als die SPS-Programmiererei noch nicht durch die HochsprachenProgrammiererei infiziert war und man noch alles durfte! ;o)

Nachschlag zu meinem merkwürdigen Beitrag in #16:
Habe früher gelegentlich die "kleinere Variante" (multiplizieren mit 257 und schieben nach rechts um 4 BitPositionen) benutzt, um die Tetraden (4-Bit-Gruppen) in einem Byte zu tauschen.
Wofür ich das allerdings gebraucht habe, weiss ich nicht mehr ... vermutlich, um die von der HardwareAbteilung festgelegte Belegung von Eingangs- oder AusgangsBits an die Bedürfnisse eines SPS-Programmierers anzupassen.

Gruss, Heinileini
 
Code:
[COLOR="#008000"]//so wäre es in SCL Classic und TIA korrekt:[/COLOR]
myInt2 := WORD_TO_INT(ROR(IN := INT_TO_WORD(myInt1), N := 8));
Genaugenommen dürfte das Ergebnis des ROR gar nicht wieder einer INT-Variable zugewiesen werden (sondern nur einer WORD-Variable), weil der Wert nach dem ROR auf keinen Fall mehr als INT verwendet werden darf (der Wert entspricht nicht mehr dem INT-Format der Plattform). Es hat schon seine Gründe, warum standardmäßig ROR für INT nicht zulässig ist.

Harald
 
Zurück
Oben