# DWORD zu BOOL Array konvertieren in CODESYS ST



## vo13 (21 November 2015)

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....


----------



## PN/DP (21 November 2015)

vo13 schrieb:


> 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:

```
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_


----------



## MasterOhh (21 November 2015)

```
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.


----------



## PN/DP (21 November 2015)

MasterOhh schrieb:


> 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:

```
xArray[i] := DWORD_TO_BOOL(dwWert AND dwMaske);
```



MasterOhh schrieb:


> 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


----------



## MasterOhh (21 November 2015)

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;


----------



## PN/DP (21 November 2015)

MasterOhh schrieb:


> 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:

```
boolArray[0] := dw.0;

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

Harald


----------



## vo13 (23 November 2015)

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 doboolArray_ := 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...._


----------



## hucki (23 November 2015)

vo13 schrieb:


> 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:
	
	



```
[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]
```


----------



## PN/DP (23 November 2015)

vo13 schrieb:


> 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:

```
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" )

Harald


----------



## vo13 (23 November 2015)

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).


----------



## PN/DP (25 September 2020)

Weil ich gerade über dieses ältere Thema gestolpert bin:
Anstatt der DWORD_TO_BOOL-Konvertierung würde ich heute besser diese "logischere" Variante verwenden:

```
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


----------



## ms4wago (12 Dezember 2022)

Hallo, funktioniert das bei einem 16bit WORD auch? Sieht das dann so aus?
`boolArray[i] := (w AND SHL(WORD#1,i)) <> 0;`


----------



## Oberchefe (12 Dezember 2022)

sofern die Schleife dann nur von 0 bis 15 geht...


----------

