Implizite und explizite Konvertierungen bei SCL

Earny

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

hätte mal eine Frage zur impliziten (KLasse A) bzw. expliziten Konvertierung (Klasse B) bei SCL. Mir ist nicht klar, was der eigentliche Unterschied ist. Ich dachte bisher, implizite Konvertierungen können entfallen, weil der Kompiler sie implizit ausführt.

Beispiel 1: Folgende Anweisungen rechnen richtig. Das habe ich in PLCSim getestet:
Code:
FUNCTION FC1: VOID
//MW_16 wurde als INT deklariert
//MW_18 wurde als INT deklariert
//MD_20 wurde als DINT deklariert
MD_20:=INT_TO_DINT(MW_16) + INT_TO_DINT(MW_18);
END_FUNCTION

Beispiel 2: Folgende Anweisungen rechnen z.B. bei negativen Zahlen falsch:
Code:
FUNCTION FC1: VOID
//MW_16 wurde als INT deklariert
//MW_18 wurde als INT deklariert
//MD_20 wurde als DINT deklariert
MD_20:=MW_16 + MW_18;
END_FUNCTION


Ich dachte, die Typ A-Konvertierungen können entfallen. "INT_TO_DINT" gehört zu den Klasse A Konvertierungen.
Irgendwas habe ich da wohl nicht verstanden.

Was heißt dann also Klasse A bzw. Klasse B?


Gruß
Earny
 
Da hast du recht, ich seh das Problem auch nicht wirklich, nur mal eine Vermutung:

Versuch das ganze mal mit Temp-Variablen zu machen, dann gehts vielleicht.
Ich könnte mir vorstellen, dass der ein Problem mit den Merkerworten hat, weil das für ihn keine richtigen INT sind, sie werden nur als INT interpretiert. Darum verhaspelt er sich vielleicht mit dem Vorzeichen, welches das höchstwertige Bit in deinem Merkerwort ist...

Für mich ist das ein Compilerfehler... ??!!??
 
Also auf dem ersten Blick scheint der SCL-Editor deine Deklarationen aus der Symboltabelle zu ignorieren. Er addiert Word und speichert das mit Hilfe von Akku1 in ein Dword. Dann ist natürlich das Bit für negative Werte an der Stelle 15, im Dword muss es aber an Stelle 31 sein. Ohne Umwandlung (AWL: ITD, SCL INT_TO_DINT) wird das nichts. Anders ist es, wenn Du Variablen direkt im Editor deklarierst, dann kann der Übersetzer das berücksichtigen.
 
MW_16 (MW16) und MW_18 (MW18) wurden in der Symbole jeweils mit INT deklariert. Es müssen deshalb zwei Variablen mit dem Datentyp INT sein.
Ich habe die Version V5.3 + SP5 + HF1.

Gruß
Earny
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Dann jetzt mal mit Temp-Variablen:

das nachfolgende Programm rechnet stes richtig:

Code:
FUNCTION FC2: VOID
VAR_TEMP
    Temp1:INT;
    Temp2:INT;
END_VAR
Temp1:=MW_16;
Temp2:=MW_18;
MD_20:=INT_TO_DINT(Temp1) + INT_TO_DINT(Temp2);
END_FUNCTION

Lasse ich INT_TO_DINT weg, rechnet es meistens falsch.
Ich steuere wieder in PLCSim Werte ins MW16 und MW18. Beide Speicher stehen auf INT!


Gruß
Earny
 
Habe noch herausgefunden, dass die beiden folgenden Varianten richtig rechnen:

FUNCTION FC1: VOID
//MW_16 wurde als INT deklariert
//MW_18 wurde als INT deklariert
//MD_20 wurde als DINT deklariert
MD_20:=INT_TO_DINT(MW_16) + MW_18;
END_FUNCTION

FUNCTION FC1: VOID
//MW_16 wurde als INT deklariert
//MW_18 wurde als INT deklariert
//MD_20 wurde als DINT deklariert
MD_20:=MW_16 + INT_TO_DINT(MW_18);
END_FUNCTION

Möglicherweise sind nur automatische Konvertierungen rechts vom Gleichheitszeichen gemeint?

Gruß
Earny
 
Du musst deinem Ergebnis das richtige Format zumindest einmal gönnen.
Ob es der erste oder der zweite Term ist völlig egal.
Wenn du nur 16 Bit rechnest, wie soll dann dein Ergebnis das Vorzeichen bekommen.
Auch rechnen deine beiden letzten Versionen falsch, wenn du die 32767 in einem Term überschreitest.
Aber das ist ja verständlich.
Zumindest habe ich das noch so am Rande in Erinnerung. :confused:

bike
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ja, ist dann wohl so. Deshalb arbeiten meine beiden Varianten von 21:31 Uhr beide richtig.
Das mit -32768 bis +32767 bei 16 Bit-Ganzzahlen war mir klar.

Gruß
Earny
 
Beispiel 2: Folgende Anweisungen rechnen z.B. bei negativen Zahlen falsch:
Code:
FUNCTION FC1: VOID
//MW_16 wurde als INT deklariert
//MW_18 wurde als INT deklariert
//MD_20 wurde als DINT deklariert
MD_20:=MW_16 + MW_18;
END_FUNCTION

Zeig doch mal den generierten AWL Code von der Funktion.

Eigentlich kann da nur etwas schiefgehen wenn der Übersetzer als Operation in AWL ein +D ohne voriges ITD anstelle eines +I generiert.

Bei mir ist der erzeugte AWL Code so wie man es erwarten würde:
Addition von zwei INT -> keine Konvertierung
Zuweisung des Ergebnisses auf ein DINT -> Vorherige implizite Konvertierung (ITD in AWL)

Und ich habe die gleiche SCL Version.
 
Bei mir ist der erzeugte AWL Code so wie man es erwarten würde:
Addition von zwei INT -> keine Konvertierung
Zuweisung des Ergebnisses auf ein DINT -> Vorherige implizite Konvertierung (ITD in AWL)

Hallo,
dann ist das doch auch schon die Erklärung.
Wenn in jedem der beiden MW als Betrag -20000 (oder auch +20000) drin stände dann wäre ohne eine vorherige Umwandlung des Ausgangsbetrages in DINT eine sinnvolle Addition gar nicht möglich weil ein INT weder einen Betrag < -32768 noch einen Betrag > +32767 darstellen kann sondern dann den weniger sinnvollen Rest darstellen würde (bei z.B. -40000 wäre das dann +7232).

Es macht eigentlich meisst Sinn, erst in das Zielformat zu konvertieren und dann zu rechnen. Zumindestens dann, wenn das Zielformat mehr darstellen kann als das Ausgangsformat (wie z.B. bei DINT und INT).

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Thomas,

der zugehörige AWL-Code für MD20 := MW16 + MW18 ist (von ein paar AWL-Specials abgesehen):
Code:
      SET   
      SAVE  
      =     L      0.1
      L     MW    16
      L     MW    18
      +I    
      SPO   I007
      SPA   I008
I007: CLR   
      =     L      0.1
I008: ITD   
      T     MD    20
      CLR   
      U     L      0.1
      SAVE  
      BE

Das ist nur eine Integer-Addition. Das geht gelegentlich schief.




Der zugehörige AWL-Code für MD20 := INT_TO_DINT(MW16) + MW18 ist:
Code:
      SET   
      SAVE  
      =     L      0.1
      L     MW    16
      ITD   
      SAVE  
      L     MW    18
      ITD   
      +D    
      SPO   I007
      SPA   I008
I007: CLR   
      =     L      0.1
I008: T     MD    20
      CLR   
      U     L      0.1
      SAVE  
      BE

Das ist jetzt eine Double-Integer-Addition. Die liefert immer das richtige Ergebnis.


Gruß
Earny
 
Zurück
Oben