Step 7 INT in HEX umwandeln und anschließend vertauschen

PuiPui

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

ich habe folgendes Problem:

Wie kann ich im SCL folgendes erreichen:
1. Die Zahl 20203 (dezimal) soll in HEX umgewandelt werden (Lösung: 20203_dez == 4EEB)
2. Dieser hexadezimale Wert muss nun in ein DWORD geschrieben werden, wobei allerdings das 1. und 2. Byte vertauscht werden müssen. (Lösung soll sein: EB 4E 00 00)
Das 3. und 4. Byte werden vermutlich ebenfalls getauscht. Da der dezimale Wert der Zahl im obigen Beispiel allerdings zu klein ist, ist das 3. und 4. Byte jeweils gleich 0.

Anschließend werden die Daten dann in einen DB geschrieben, was aber für mein Problem zunächst unwichtig ist:Unbenannt.JPG
Byte1 == EB
Byte2 == 4E
Byte3 == 00
Byte4 == 00

Wie kann ich das im SCL auf verständliche Art realisieren?


Vielen Dank im Voraus!
 
Och nö, nicht schon wieder die Hex Geschichte (Ich spüre ein leichtes Zucken im Auge und eine aufkommende Aggression). :sm14:
Also nochmals, Hex ist keine Zahl sondern wie Dezimal und Oktal eine Darstellungsart für Zahlen. Deswegen kann, bzw. muss man eine Zahl in Dezimalschreibweise nicht umwandeln, sondern die Zahl wird einfach anders dargestellt. Dein Vorhaben die Bytes wordweise zu tauschen erscheint mir allerdings seltsam, denn das würde ein Mixed Endian ergeben und ich denke mal Du möchtest von Little Endian nach Big Endian oder umgekehrt wandeln und dafür muss die Position aller Bytes einmal gespiegelt (Byte 1 wird Byte 4, Byte 2 wird Byte 3, usw.) werden. Um das zu tun speicherst Du die Zahl (In welcher Anzeigenform Du sie auch immer eingegeben hast ist egal) in ein DWORD und tauscht dann die Bytes mit dem Befehl SWAP (in TIA, Classic weiß ich leider nicht).
 
Zuletzt bearbeitet:

Ist ja gut, tut mir leid, wenn ich nicht den richtigen Fachbegriff verwendet habe, ich nenne es trotzdem weiterhin umwandeln.

Ich benötige die Hilfe für das gaaanz normale Step 7, nicht TIA.


Nochmal zum Problem:
20203 (dez.) == 4E EB (hex.) == 00 00 4E EB (DWord)

Jetzt müssen die Sachen nach von rechts nach links vertauscht werden, so dass herauskommt:
EB 4E 00 00 (DWord)


Mein ursprüngliches Problem hat sich damit verändert, Entschuldigung
 
Die Sicht AT kann in TIA auch direkt auf In- und Outputs erstellt werden.
Das erspart Zwischenschritte zum Umspeichern auf/von temporären Variablen:

Anhang anzeigen 38149




Allerdings erledigt dies das von oliver.tonn angesprochene SWAP ganz ohne ATs und damit auch in optimierten FCs:
Code:
#nOut := SWAP_DWORD(INT_TO_DWORD(#nIn));

Anhang anzeigen 38152

Stimmt.. SWAP geht auch. Aber die AT-Sicht geht auch in optimierten Bausteinen man muß nur die Variable auf Remanent im IDB setzen, dann kann ich AT auch im optimierten Baustein machen. Und mit AT geht es halt auch in Classic. Der Code müsste der gleiche sein nur die deklaration ist anders.
 
Aber die AT-Sicht geht auch in optimierten Bausteinen man muß nur die Variable auf Remanent im IDB setzen, dann kann ich AT auch im optimierten Baustein machen.
Ist allerdings etwas schwierig, in einem optimierten FC die Remanenz auf "Im IDB setzen" zu stellen, wenn es gar keinen IDB gibt.
;)
 
Mit nur einem ROL bekommt man die Vertauschung 00 00 4E EB --> EB 4E 00 00 nicht hin.

@PuiPui
Hast Du mal das SWAP ausprobiert? Die umständliche Variante mit dem AT würde ich nur im Notfall machen, falls die CPU das SWAP nicht kennt.
Was hast Du überhaupt für eine CPU?

Harald
 
Danke für eure Inspirationen. Ich habe es jetzt folgendermaßen gelöst:

FUNCTION IntelMoto : VOID
// Konvertiere einen Doppelintegerwert in eine hexadezimal Zahl und vertausche anschließend die Reihenfolge von rechts nach links
//
// Beispiel: InBy3 InBy2 InBy1 InBy0
// L#20234 (DINT) == 00 00 4F 0A (Intelformat, DWORD)
//
// OutBy3 OutBy2 OutBy1 OutBy0
// == 0A 4F 00 00 (Motorolaformat, DWORD)

VAR_INPUT
InVal : DINT;
InBy AT InVal : ARRAY[0..3] OF BYTE;
END_VAR

VAR_OUTPUT
OutBy0 : BYTE;
OutBy1 : BYTE;
OutBy2 : BYTE;
OutBy3 : BYTE;
END_VAR


//Vertauschen: Von Intel- ins Motorola-Format
OutBy0 := InBy[3];
OutBy1 := InBy[2];
OutBy2 := InBy[1];
OutBy3 := InBy[0];
END_FUNCTION


Leider gibt es keine "simple" Funkition für so etwas in SCL.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin,

hat sich Deine Aufgabenstellung nochmal geändert? Du hast nirgends geschrieben, daß Du einen DINT in 4 BYTE zerlegen willst. Deine bisherigen Aufgabenstellungen waren, von einem DINT die Bytes zu tauschen und in ein DWORD zu schreiben.
2. Dieser hexadezimale Wert muss nun in ein DWORD geschrieben werden, wobei allerdings das 1. und 2. Byte vertauscht werden müssen. (Lösung soll sein: EB 4E 00 00)
Das 3. und 4. Byte werden vermutlich ebenfalls getauscht.
Nochmal zum Problem:
20203 (dez.) == 4E EB (hex.) == 00 00 4E EB (DWord)

Jetzt müssen die Sachen nach von rechts nach links vertauscht werden, so dass herauskommt:
EB 4E 00 00 (DWord)


Mein ursprüngliches Problem hat sich damit verändert, Entschuldigung
FUNCTION IntelMoto : VOID
[...]
VAR_INPUT
InVal : DINT;
InBy AT InVal : ARRAY[0..3] OF BYTE;
END_VAR
[...]
OutBy0 := InBy[3];
OutBy1 := InBy[2];
OutBy2 := InBy[1];
OutBy3 := InBy[0];
END_FUNCTION

Leider gibt es keine "simple" Funkition für so etwas in SCL.
Für das Zerlegen eines DWORD (und jedes beliebigen 32-Bit-Datentyps) in 4 Byte in SCL ist tatsächlich das AT der einfachste Weg. Eventuell noch gewünschte Byte-Vertauschungen kann man sehr einfach beim Bausteinaufruf mit der Beschaltung an den 4 Byte-Ausgängen vornehmen. Das Zerlegen in 4 Byte ist wohl an sich schon so simpel, daß es weder in classic-SCL noch in OSCAT eine eigene Funktion dafür gibt. Falls AT nicht möglich ist kann man die Aufgabe auch ohne AT z.B. mit shiften lösen.

Dein Programm mit dem AT auf einen VAR_INPUT-DINT und dann viermal lesen ist allerdings keine gute Lösung, weil nicht multi-Tasking-sicher. Der Eingangs-DINT muß zuerst auf eine TEMP-Variable umkopiert werden und die kann dann in aller Ruhe zerlegt werden, ohne daß es einen Einfluß hat, wenn sich der Wert der am INPUT angeschalteten Variable während der FC-Ausführung ändert.


Für die zweite Formulierung Deiner Aufgabe mit dem Tauschen der 4 BYTE in einem DWORD gibt es von OSCAT die fertige Funktion SWAP_BYTE2, deren ST-Quelltext man sehr einfach für Step7-"classic"-SCL anpassen kann (oder fertig als SCL-Quelltext bei OSCAT downloaden kann).
GitHub / oscat / SWAP_BYTE2.EXP schrieb:
Code:
Swap_Byte2 := (ROR(in,8) AND 16#FF00FF00) OR (ROL(in,8) AND 16#00FF00FF);

Harald
 
Hallo PuiPui,
Ist ja gut, tut mir leid, wenn ich nicht den richtigen Fachbegriff verwendet habe, ich nenne es trotzdem weiterhin umwandeln.
Ich benötige die Hilfe für das gaaanz normale Step 7, nicht TIA.

Nochmal zum Problem:
20203 (dez.) == 4E EB (hex.) == 00 00 4E EB (DWord)

Jetzt müssen die Sachen nach von rechts nach links vertauscht werden, so dass herauskommt:
EB 4E 00 00 (DWord)

Mein ursprüngliches Problem hat sich damit verändert, Entschuldigung
bitte entschuldige, ich wollte Dir nicht auf den Schlips treten. Natürlich kann nicht jeder sofort alles wissen. Allerdings gab es hier im Forum in letzter Zeit häufig Fragen in denen auch die Hexadezimaldarstellung vorkam wo von völlig falschen Vorstellungen ausgegangen wurde, die sich bei den Betreffenden trotz entsprechender Er-/Aufklärung hartnäckig hielten und auch nur sehr schwer ausräumen ließen.
Ich bitte darum auch um Verständnis, wenn ich mich wiederum aufgrund Deiner Antwort ein wenig auf den Schlips getreten fühle. Ich hatte Dir schon erklärt, dass es keine Wandlung gibt und trotzdem schreibst Du in Deinem Post wieder davon. Den Schritt 20203(dez.)==4E EB (hex.) gibt es nicht. Wenn ein Typ in einen anderen umgewandelt wird gibt es Änderungen im Speicher der SPS, entweder ändert sich der Inhalt oder der Speicherbedarf oder beides. Wenn ein Int in Dezimal dargestellt 255 enthält sieht das Bitmuster bei Little Endian so aus: 0000 0000 1111 1111
Wandelt man dies jetzt in ein DInt um sieht das im Speicher so aus: 0000 0000 0000 0000 0000 0000 1111 1111
Bei Dezimaler Darstellung wird der obige Int-Wert als 255 angezeigt und im Speicher steht 0000 0000 1111 1111
Bei Hexadezimaler Darstellung wird 00 FF angezeigt, aber im Speicher steht immer noch 0000 0000 1111 1111
Es wird also nichts gewandelt, sondern lediglich anders dargestellt und deshalb gibt es den Schritt auch nicht. Auch in Deiner Lösung von Post #11 konvertierst Du einen DInt-Wert nicht in eine Hexadezimale Zahl, sondern Du stellst die Daten einmal als DInt zur Verfügung und parallel als Array of Byte, was aber, wie Harald schon festgestellt hat, nicht notwendig ist. Haralds Tipp dürfte die einfachste Lösung unter Step 7 Classic darstellen.
 
Zuletzt bearbeitet:
Zurück
Oben