INT spiegeln

Rici

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

kann mir jemand sagen wie ich mit CoDeSys 2.3 in der ST Sprache einen INT spiegeln kann.
Ich bin mit Hochsprache nicht wirklich vertraut.

Das Ergebnis sollte so aussehen bit0-->bit15;bit1-->bit14;bit2-->bit13.....
bit15-->bit0;bit14-->bit1;bit13-->bit2....


Vielen Dank im Voraus!
 
Zum Beispiel so:
Code:
i16_Test02.0 := i16_Test01.15;i16_Test02.1 := i16_Test01.14;
i16_Test02.2 := i16_Test01.13;
usw.
Aber ich bin mir nicht sicher, ob es das ist was Du eigentlich wilst. Sollte es nämlich um die Little Endian/Big Endian Problematik gehen musst Du nämlich nicht die Bits tauschen sondern nur die beiden Bytes.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke,

ich hätte vielleicht etwas mehr schreiben sollen.

Du hast es richtig verstanden, bitweise.
Ich dachte mir da an einen Befehl mit dem ich den ganzen INT drehen kann. Am ende soll es eine Schleife werden.

Im ganzen geht es um ein Kommunikations-Struktur-Aufbau.
Ein ASi Master gibt ein Array [1..125] of INT. Irgendwo drin sind die Slaves. Um nicht mit einer Liste zu arbeiten soll die Struktur so aufgebaut werden dass man am ende so was hat. ASI Kreis 2 [7].1 --> heißt Slave 7 Eingang 1.
Um dies Umzusetzen muss unter andrem der INT gedreht werden.
 
Der "classische" Algorithmus zum Bits spiegeln in einem Byte in C
Code:
n = (n&0xF0)>>4 | (n&0x0F)<<4;
n = (n&0xCC)>>2 | (n&0x33)<<2;
n = (n&0xAA)>>1 | (n&0x55)<<1;

und eine ähnliche OSCAT-Variante REVERSE in ST
Code:
REVERSE := SHL(in,7) OR SHR(in,7) OR (ROR(in,3) AND 2#01000100) OR (ROL(in,3) AND 2#00100010) 
        OR (SHL(in,1) AND 2#00010000) OR (SHR(in,1) AND 2#00001000);

Word oder DWord spiegeln analog dieser Lösung in S7-AWL:
Zunächst die Bit-Reihenfolge in den 4 Teil-Bytes spiegeln und bei Word/Doppelword danach
die in sich gespiegelten Bytes in die gespiegelte Reihenfolge bringen.

Multitasking-sicher: Vorsichtshalber für den Fall, daß das Word nicht als Kopie sondern per Referenz übergeben wird, bei allen Varianten darauf achten, daß zunächst das Eingangsword auf eine lokale Variable umgespeichert wird, dann die Bits der lokalen Kopie spiegeln und erst zum Schluß die lokale Spiegelung auf das Ausgangsword kopieren.

PS:
Für die Ansammlung von Bits ist der Datentyp INT eigentlich falsch und müsste WORD sein.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Lieber Harald,

Danke, das mit dem Datentyp WORD ist ein sehr guter Hinweis gewesen!

Die Lösung in ST sieht auf den ersten blick super aus. Aber ich verstehe überhaupt nicht was es sein soll. :confused:
Muss der Code so 1:1 eingegeben werden? Kann man es auf WORD umbauen?
warum steht dort immer wieder OR? was heißt AND2'0101010101?

Sehe ich es richtig, dass es dafür kein Befehl gibt und man sich die Lösung zurechtbasteln muss?

Ich hoffe es sind nicht zufiele Fragen auf einmal gewesen.

Gruß
Rici
 
Meint Ihr das könnte funktionieren?

FOR M:=0 TO 15 DO
wert:= ROR (wert, 1);
reverse.15:= wert.15;
reverse:=ROL (reverse,1);
m:= m+1;
END_FOR

Habe zurzeit keine Möglichkeit es zu testen.
 
Hallo Oliver,

wie ich am Anfang schrieb mit Hochsprache bin ich nicht vertraut.
Wo ist denn der Fehler bei m:=m+1;
War der Meinung dass m bei jedem Schleifendurchlauf um 1 erhöht wird bis das Ende erreicht ist.
Wenn es nicht so ist muss ich noch ein bisschen lesen.
 
Das ist auch richtig, nur macht das schon die For-Anweisung für Dich. Bei Dir würde m bei jedem Durchlauf durch die For-Anweisung und zusätzlich durch das m:=m+1; um jeweils 1, also in Summe, um 2 erhöht.

Von irgendwas mit Internetzugang gesendet
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Bits im Word spiegeln

Der "classische" Algorithmus zum Bits spiegeln in einem Byte in C
Code:
n = (n&0xF0)>>4 | (n&0x0F)<<4;
n = (n&0xCC)>>2 | (n&0x33)<<2;
n = (n&0xAA)>>1 | (n&0x55)<<1;
Dieser Algorithmus für ein Word in ST:
Code:
FUNCTION REVERSE_W : WORD
VAR_INPUT
  IN : WORD;
END_VAR
VAR
  tmpW : WORD;
END_VAR

// Die Function kehrt die Reihenfolge der Bits in einem Word um.

tmpW := ROL(IN, 8);
tmpW := SHR(tmpW AND 16#F0F0, 4) OR SHL(tmpW AND 16#0F0F, 4);
tmpW := SHR(tmpW AND 16#CCCC, 2) OR SHL(tmpW AND 16#3333, 2);
REVERSE_W := SHR(tmpW AND 16#AAAA, 1) OR SHL(tmpW AND 16#5555, 1);

END_FUNCTION

Harald
 
Der "classische" Algorithmus zum Bits spiegeln in einem Byte in C
Code:
n = (n&0xF0)>>4 | (n&0x0F)<<4;
n = (n&0xCC)>>2 | (n&0x33)<<2;
n = (n&0xAA)>>1 | (n&0x55)<<1;
Ich finde hier wäre eine kurze Erläuterung angebracht, wie und wieso das funktioniert.

Zeile 1:
Code:
a = n&0xF0; b = n&0x0F; // hier wird das Byte in zwei Teile zerlegt: AAAA BBBB
a = a >> 4; b = b << 4; // hier werden die zwei Teile gegeneinander verschoben: BBBB AAAA
n = a | b; // und wieder zusammengesetzt
Zeile 2:
Code:
a = n&0xCC; b = n&0x33; // hier wird das Byte in zwei Teile zerlegt: AA BB AA BB
a = a >> 2; b = b << 2; // hier werden die zwei Teile gegeneinander verschoben: BB AA BB AA
n = a | b; // und wieder zusammengesetzt
Zeile 3:
Code:
a = n&0xAA; b = n&0x55; // hier wird das Byte in zwei Teile zerlegt: A B A B A B A B
a = a >> 1; b = b << 1; // hier werden die zwei Teile gegeneinander verschoben: B A B A B A B A
n = a | b; // und wieder zusammengesetzt

beim Übersetzen nach ST muß man nur noch die Syntax anpassen, also "|" wird zu "OR", "&" zu "AND" und "0xF0" zu "16#F0" (oder "2#11110000") etc.

bei größeren Datentypen (2 byte, 4 byte, etc.) brauchst du entsprechend jeweils eine Zeile mehr, die die entsprechend größeren Blöcke vertauscht
 
Danke Eddi,

ich musste es mir auf dem Zettel aufmalen damit ich es verstehe.

Habe gerade meine Lösung getestet diese funktioniert auch.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Den Algorithmus kann man noch etwas optimieren:
[SUP]1[/SUP]) Die Maskierung in der jeweils 1. Zeile ist eigentlich "Luxus" (= überflüssig).
Da habe ich wohl vor Jahren noch nicht so genau auf mögliche Optimierungen geachtet, als ich den Algorithmus irgendwo gefunden hatte. ;)
Zumindest beim Rechtsschieben wäre es auch noch schöner, zuerst zu schieben und erst danach zu maskieren - dann funktioniert der C-Code auch mit signed Datentypen. Beim Linksschieben ist die Reihenfolge beliebig. (Stichwort: logisch oder arithmetisch verschieben)

Viele Wege führen nach Rom. Man kann die zugrunde liegende Idee/Algorithmus noch etwas besser implementieren.
Anstatt
Code:
n = (n&0xF0)>>4 | (n&0x0F)<<4;
n = (n&0xCC)>>2 | (n&0x33)<<2;
n = (n&0xAA)>>1 | (n&0x55)<<1;
besser für unsigned und signed char (8 Bit Byte):
Code:
n = ((n >> 4) & 0x0F) | ((n << 4) & 0xF0);
n = ((n >> 2) & 0x33) | ((n << 2) & 0xCC);
n = ((n >> 1) & 0x55) | ((n << 1) & 0xAA);

(* oder *)
n = ((n >> 1) & 0x55) | ((n & 0x55) << 1);
n = ((n >> 2) & 0x33) | ((n & 0x33) << 2);
n = ((n >> 4) & 0x0F) | ((n & 0x0F) << 4);

(* oder *)
n = ((n >> 1) & 0x55) | ((n & 0x55) << 1);
n = ((n >> 2) & 0x33) | ((n & 0x33) << 2);
n = ((n >> 4) & 0x0F) | ( n         << 4);

Speziell für unsigned Datentypen kann man abkürzen:
Code:
(* für unsigned char (8 Bit Byte): *)
n = ((n >> 1) & 0x55) | ((n & 0x55) << 1);
n = ((n >> 2) & 0x33) | ((n & 0x33) << 2);
n =  (n >> 4)         | ( n         << 4);

(* für unsigned short (16 Bit Word): *)
n = ((n >> 1) & 0x5555) | ((n & 0x5555) << 1);
n = ((n >> 2) & 0x3333) | ((n & 0x3333) << 2);
n = ((n >> 4) & 0x0F0F) | ((n & 0x0F0F) << 4);
n =  (n >> 8)           | ( n           << 8);

(* für unsigned int (32 Bit DWord): *)
n = ((n >> 1) & 0x55555555) | ((n & 0x55555555) << 1);
n = ((n >> 2) & 0x33333333) | ((n & 0x33333333) << 2);
n = ((n >> 4) & 0x0F0F0F0F) | ((n & 0x0F0F0F0F) << 4);
n = ((n >> 8) & 0x00FF00FF) | ((n & 0x00FF00FF) << 8);
n =  (n >> 16)              | (n << 16);
 
Über den Rest muss man zwar zweimal nachdenken (Auah, hab Logikknoten im Hirn!), sollte aber so passen.
Nein Oliver, zweimal nachdenken reicht bei dieser FOR-Schleife offensichtlich nicht annähernd.
Den Logikknoten im Hirn gibt's gratis (Vorsicht: ansteckend!) beim Versuch, die FOR-Schleife zu verstehen.
Sorry, aber daran scheint rein gar nichts zu passen.
Anzahl SchleifenDurchläufe müsste höchstens 8 sein, da bei jedem Durchlauf 2 (oder mehr!) der 16 Bit getauscht werden sollen. (Tauschen, um dann später wieder zurückzutauschen, wäre vom Aufwand her doppelt gemoppelt und von der Wirkung her total nutzlos!)
Die Anzahl der BitPositionen, um die jeweils geRORt bzw. geROLt wird, müsste von Durchlauf zu Durchlauf ABHÄNGIG VON M variiert werden.
Statt zu rotieren könnte man auch schieben.
Die jeweils relevanten BitPositionen müssten ausmaskiert werden. D.h. man müsste auch noch die Masken mühsam abhängig vom M basteln und das verUNDen nicht vergessen.
Die ZwischenErgebnisse müssten wieder zusammengeODERt werden.
Das ganze wäre mir viel zu aufwändig, um es auch noch in ST zu formulieren.
Warum einfach, wenn's auch kompliziert geht.

Harald hat die Lösung(sAlternativen) und ist gerade voll im Thema, weil dies schon der zweite Thread zu diesem Thema innerhalb weniger Stunden/Tage ist! ;)

Edit & Dementi: Da bin ich ja voll auf die vermeintliche Telepathie hereingefallen! Dies hier ist ja ein RetroThread von 2017!!!
 
Zuletzt bearbeitet:
Zurück
Oben