DWORD zu BOOL Array konvertieren in CODESYS ST

vo13

Level-1
Beiträge
31
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
ich habe ein 32 Bit DWORD und möchte das umwandeln in ein BOOL Array[32].
D.h. BOOL Array[0]= Bit 0 von Word, BOOL Array[1]= Bit 1 von Word usw.
Das Ganze dann in einer Schleife ablaufen lassen.

Wie kann die Konvertierung am schnellsten durchgeführt werden?
Mit IF Abfragen dauert das wohl etwas lange.

Vielen Dank für eure Antworten und Lösungen....
 
Wie kann die Konvertierung am schnellsten durchgeführt werden?
Mit IF Abfragen dauert das wohl etwas lange.
IF-Abfragen benötigt man für diese Aufgabe tatsächlich überhaupt nicht.
Was meinst Du mit "am schnellsten"?

Folgendes ist mit am wenigsten nachdenken am schnellsten getippt und der Code wird auch am schnellsten ausgeführt:
Code:
xArray[0] := dwWert AND 16#00000001;
xArray[1] := dwWert AND 16#00000002;
xArray[2] := dwWert AND 16#00000004;
xArray[3] := dwWert AND 16#00000008;
xArray[4] := dwWert AND 16#00000010;
...
...
xArray[31]:= dwWert AND 16#80000000;

Wenn man das in eine Schleife packen will, so ist gut zu sehen, daß man dafür lediglich den Array-Index durch die Schleifenvariable ersetzen muß und die Maske für das AND in jedem Schleifendurchlauf jeweils um 1 Bit nach links shiften muß.

Die Variante mit der Schleife erzeugt kürzeren Programmcode, braucht aber mindestens dreimal so lange für die Ausführung.

dwMaske := 1;
FOR i:=0 TO 31 DO
xArray := dwWert AND dwMaske;
dwMaske := SHL(dwMaske, 1);
END_FOR;

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
dw :dword;
boolArray :array[0..31] of bool;
i:int;

for i := 0 to 31 do[INDENT]boolArray[i] := DWORD_TO_BOOL(dw AND REAL_TO_DWORD(EXPT(2,i)));
[/INDENT]
end_for

EXPT(2,i) gibt dir die Bitmaske für jedes der 32 Bits im DWORD.
Durch die Verundung der Maske mit dem DWORD bekommst du für jedes Bit als Ergebnis entweder eine 0 wenn das Bit 0 ist oder den Wert 2^i wenn das Bit 1 ist.
Mit DWORD_TO_BOOL machst du daraus das FALSE oder TRUE für dein Array.

EDIT:
Kurzer 3-Zeiler aber Verglichen mit PN/DPs Lösung ein Ressourcenschwein (REAL-Operationen in EXPT).
Auf einer halbwegs modernen Steuerung geht das im Grundrauschen der Prozessorauslastung unter, sollte aber der Vollständigkeit halber erwähnt werden.

Wenn dir die "CPU schonende" Version zuviel Code ist. Mach ne Funktion draus.

Ach ja, in PN/DPs Lösung muss auch noch der DWORD_TO_BOOL Cast rein. Ein DWORD mit einem DWORD verundet ergibt wieder ein DWORD und kein BOOL.
 
Zuletzt bearbeitet:
in PN/DPs Lösung muss auch noch der DWORD_TO_BOOL Cast rein.
Ich habe kein Codesys, doch laut Codesys-Hilfe sollte der explizite Cast DWORD_TO_BOOL nicht nötig sein. (siehe mal hier #3 und #5)
Mit explizitem DWORD_TO_BOOL wird es aber besser lesbar/verstehbar und sähe dann so aus:
Code:
  xArray[i] := DWORD_TO_BOOL(dwWert AND dwMaske);
EXPT(2,i) gibt dir die Bitmaske für jedes der 32 Bits im DWORD.
Wenn man die Maske aus der Schleifenvariable berechnen muß, dann würde ich SHL(1,i) anstatt EXPT(2,i) benutzen.

Harald
 
Ok, wenn Codesys implizit casten kann, muss man das nicht mehr explizit machen. TwinCAT möchte halt gern nochmal gesagt bekommen, das das DWORD jetzt ein Bool ist ;)

Ansonsten bleibt noch der Klassiker, der sicherlich auch in Codesys funktioniert:

boolArray[0] := dw.0;
boolArray[1] := dw.1;
boolArray[2] := dw.2;
...
boolArray[31] := dw.31;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
boolArray[0] := dw.0;
boolArray[1] := dw.1;
Diese Variante geht allerdings nicht in einer Schleife.

btw: Ich vermute, die Bitadressierung ".<n>" ist nur ein Compiler-Makro für eine AND-Maskierung und der Codesys-Compiler liefert bei beiden Varianten den gleichen Ausgangscode:
Code:
boolArray[0] := dw.0;

boolArray[0] := dw AND 16#00000001;

Harald
 
Hallo,
erstmal danke für Eure Antworten.
Habe das nun so gemacht:
dw :dword;
boolArray :array[0..31] of bool;
i:int;

for i := 0 to 31 do
boolArray := DWORD_TO_BOOL(dw AND SHL(1,i));

end_for

Funktioniert so.
Bekomme jedoch eine Warnung 1511: Der Typ der zu schiebenden Größe ist nicht festgelegt! Bitte benutzen Sie eine getypte Konstante (etwas DWORD#1)

Wie bekomme ich die Warnung weg?

Danke für eure Antworten....
 
Bekomme jedoch eine Warnung 1511: Der Typ der zu schiebenden Größe ist nicht festgelegt! Bitte benutzen Sie eine getypte Konstante (etwas DWORD#1)

Wie bekomme ich die Warnung weg?
Z.B. so wie's da steht:

Eine Konstante vom Typ DWORD mit dem Wert 1 definieren und dann statt der 1 direkt halt diese Konstante schieben:
Code:
[COLOR=#333333]for i := 0 to 31 do
[/COLOR][COLOR=#333333]   boolArray[i] := DWORD_TO_BOOL(dw AND SHL([/COLOR][COLOR=#ff8c00][B]#dwordConst[/B][/COLOR][COLOR=#333333],i));[/COLOR]
[COLOR=#333333]end_for[/COLOR]
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Bekomme jedoch eine Warnung 1511: Der Typ der zu schiebenden Größe ist nicht festgelegt! Bitte benutzen Sie eine getypte Konstante (etwas DWORD#1)
Das meint folgendes:
Code:
for i := 0 to 31 do
  boolArray[i] := DWORD_TO_BOOL(dw AND SHL([COLOR="#0000FF"]DWORD#1[/COLOR],i));
end_for;

Oder benutze eine DWORD-Variable wie in meinem Programmbeispiel für die Schleife in Beitrag #2 (markiere mal den Text von "Die Variante mit der Schleife" bis "Harald" :cool:)

Harald
 
Danke an alle, klappt nun wie gewünscht!
Bin noch nicht so tief in CODESYS ST drin --> learning by doing!

... bis zum nächsten Mal (nächste Frage wird sicherlich bald kommen).
 
Weil ich gerade über dieses ältere Thema gestolpert bin:
Anstatt der DWORD_TO_BOOL-Konvertierung würde ich heute besser diese "logischere" Variante verwenden:
Code:
for i := 0 to 31 do
  boolArray[i] := (dw AND SHL(DWORD#1,i)) <> 0;
end_for;

(Vermutlich macht "DWORD_TO_BOOL(x)" auch nichts anderes als den Vergleich "x <> 0", man sieht es aber nicht so deutlich.)

Harald
 
Zurück
Oben