Array an DWORD übergeben (SCL)

MatthiasH24

Level-1
Beiträge
132
Reaktionspunkte
6
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi

habe mal wieder ein Problem mit meinen Arrays :).

Folgendes ich bin grad dabei eine Synoptik für ein Projekt zu programmieren.
der Status zu den jeweiligen Variablen die überprüft werden sollen wird in ein DWORD geschrieben. Und das jeweils als BIT gesehen.

bsp:

Code:
IF Variable THEN
       "P_Systemdaten".Anl_Synoptik.Syn_Status   :=2#0000000000000000000000001000011  ;  
(* Synoptik Status rot = 0, gruen = 1 *)*)
         END_IF;

das funktioniert auch soweit wenn ich nur eine variable überprüfe aber im tatsächlichen Programm kommen mehere If -Abfragen hintereinander. und dann kommt was ja eigentlich klar ist... das dass DWORD immer überschrieben wird... gut eigentlich kein Thema dachte ich ändere ich einfach das DWORD in ein ARRAY of BOOL um. nur das kann ich nicht machen weil sonst mein kollege über einen tag beschäftigt ist die VISU neu einzustellen( ZENON :-( )

Jetzt dachte ich mache ich es so
Code:
IF Variable THEN
        Syn_Status_temp[0]   := TRUE; 
(*"P_Systemdaten".Anl_Synoptik.Syn_Status   :=2#0000000000000000000000001000011  ;   (* Synoptik Status rot = 0, gruen = 1 *)*)
 END_IF;

Nur weiß ich jetzt nicht wie bzw ob es überhaupt geht das Array wieder in das Dword zuschreiben, so dass mein Bitmuster wieder stimmt.

Mein Versuch geht natürlich nicht...

Code:
 FOR i := 0 TO 32 BY 1 DO
     "P_Systemdaten".Anl_Synoptik.Syn_Status := syn_status_temp[i];
     END_FOR;


hat vllt jemand eine Idee?

Grüßle
 
Hallo Matthias,
aus deiner Frage bin ich nicht so recht schlau geworden. 1 Sache habe ich dennoch :

Code:
VAR 
   Test_DWORD : DWORD ;
   Array_DWORD AT Test_DWORD : Array [0..31] of bool ;
 
und im Code dann :
 
Array_DWORD[14] := true ;
 
usw.
In meinem Beispiel wird mittels des Befehls AT eine andere Sicht auf dein DWORD gebildet und nicht etwa eine neue Variable). Wenn du dich hier an die Spielregeln hällst (beide Sichten sollten gleich groß sein), dann kann du so auch einzelne Bits in dem ursprünglichen DWORD verändern.

Gruß
LL
 
Zuviel Werbung?
-> Hier kostenlos registrieren
So also hier mal der prinzippiele Ablauf wie es eigentlich gedacht war.. versuche es so mal zu erklären vllt ist es dann klarer. Was du mir mit deinem code sagen willst versethe ich nocht nicht so ganz. Muss mal in der hilfe nach dem AT befehl schauen

Code:
IF e100.0 THEN
   status :=2#00000000000000000000000000000001 ;
ELSE
   status :=2#00000000000000000000000000000000 ;
 
END_IF;
IF e100.1 THEN
    status :=2#00000000000000000000000000000010;
    ELSE
   status :=2#00000000000000000000000000000000;
END_IF;
IF e100.2 THEN
    status :=2#00000000000000000000000000000100;
    ELSE
   status :=2#00000000000000000000000000000000;
END_IF;
IF e100.3 THEN
    status :=2#00000000000000000000000000001000;
    ELSE
   status :=2#00000000000000000000000000000000;
END_IF;
IF e100.4 THEN
    status :=2#00000000000000000000000000010000;
    ELSE
   status :=2#00000000000000000000000000000000;
END_IF;
IF e100.5 THEN
    status :=2#00000000000000000000000000100000;
    ELSE
   status :=2#00000000000000000000000000000000;
END_IF;

wie man sieht wird ja jedes mal der Status neu überschrieben (logisch aber irgendwie für manche doch nicht)

Mein Problem ist halt das für jede Variable ein Kästchen in der Visu habe das je nachdem dem Wert des BITS die Farbe "rot" oder "grün" annimmt.
und in der ELse schleife will ich es durch ein Array ersetzen das natürlich auch 32 BIT groß ist. und das Array soll dann wieder als DWORD ausgegeben werden und an die VISU zur Anzeige geschickt wird.
 
Larry hat dir ja einen sehr schönen Weg gezeigt, den würde ich empfehlen, gerade in SCL
Eine andere Möglichkeit ist, die Bits zu maskieren.
 
... dann schau dir das mit dem AT-Befehl mal an und test es ggf. mal - ich verspreche dir, dass es dir gefallen wird.

Bezogen auf dein Beispiel könnte das dann so aussehen (keine Gewähr für die korrekte Bit-Position weil nicht getestet) :
Code:
ARRAY_Status[31] := e100.0 ;
ARRAY_Status[30] := e100.1 ;
 
usw.
Wenn du mit Maskieren arbeiten willst, so mußt du vorher ausmaskieren :
Code:
Status := Status and 2#11111111111111111111111111111110 ;
if e100.0 then status := status or 2#00000000000000000000000000000001 ; end_if ;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
nach nochmaligem Ansehen deines Codes noch folgendes :
Code:
VAR 
   dw_Status : DWORD ;
   bool_array_Status AT dw_Status: Array [0..31] of bool ;
   byte_array_Status AT dw_Status: Array [0..3] of byte ;
   word_array_Status AT dw_Status: Array [0..1] of word ;
 
somit geht dann natürlich auch :
 
bool_array_Status [14] := e100.0 ;
 
byte_array_Status [2] := eb101 ;
 
word_array_Status [1] := ew102 ;
 
und zwar sogar gemischt ...

ich würde allerdings bei solchen Sachen eine absolute Adressierung immer hinterfragen ...

Gruß
LL
 
Hi also gleichmal zu absoult adressierung das war nur ein Bsp. in echt sieht es nciht so aus.

habe es mal eingespielt mit der Visu aber geht so leider nicht.

hier Mal der komplette Code:
Variablendeklaration
Code:
VAR_TEMP
Syn_temp : DWORD;
Syn_Status_temp  AT Syn_temp : ARRAY[0..31] OF BOOL;
END_VAR

Vordefintionen:
Code:
"P_Systemdaten".Anl_Synoptik.Syn_Ansicht :=2#00000000000000000000000001111111;(* Synoptik Ansicht der Bits einblenden *)
Damit wird angegeben wieviel Bits für die jeweilige Gruppe es in der Synoptik gibt. hier 7 Stück

Die If Abfragen für die Variablen

Code:
IF "P_I=0+S0-F04:14" THEN 
        Syn_Status_temp[0]   := TRUE;
ELSE
        Syn_Status_temp[0]   := FALSE;
END_IF;
 IF "P_I=00+S00-X31:703" THEN 
        Syn_Status_temp[1]   := TRUE
ELSE
        Syn_Status_temp[1]   := FALSE;
END_IF;
IF "P_I=00+S00-B33.3:4" THEN 
     Syn_Status_temp[2]   := TRUE;
ELSE
     Syn_Status_temp[2]   := FALSE;
END_IF;
IF "P_I=00+S00-0F1:14" THEN
     Syn_Status_temp[3]   := TRUE; 
ELSE
    Syn_Status_temp[3]   := FALSE;
END_IF;
IF "P_I=00+S00-F3:14" THEN
        Syn_Status_temp[4]   := TRUE;
ELSE
        Syn_Status_temp[4]   := FALSE;
END_IF;
IF "P_I=00+S00-F40:14" THEN 
        Syn_Status_temp[5]   := TRUE;
ELSE
        Syn_Status_temp[5]   := FALSE;
END_IF;
IF "P_I=0+S0-0F22:14" THEN
      Syn_Status_temp[6]   := TRUE; 
ELSE
      Syn_Status_temp[6]   := FALSE;
END_IF;

und anschließen nooch die Übergabe in das ursprüngliche DWORD

Code:
"P_Systemdaten".Anl_Synoptik.Syn_Status := Syn_temp;
"P_Systemdaten".Anl_Synoptik.Syn_Uebersicht_Status := "P_Systemdaten".Anl_Synoptik.Syn_Status = "P_Systemdaten".Anl_Synoptik.Syn_Ansicht ;

Die Bits im Array werde auch schön gesetzt, weiß nur nicht ob ich jetzt wegen den Arrays ein Programmierfehler habe oder weil ich was falsch von dir übernommen habe.

Grüßle
 
das ist schon ganz schön ...

ich meinte es aber so :
Code:
Syn_Status_temp[0]   := "P_I=0+S0-F04:14" ;
Syn_Status_temp[1]   := "P_I=00+S00-X31:703"  ;
 
usw.
Das Umkopieren von Syn_Status_temp in Syn_temp kann (muß) entfallen. Du hast durch die AT-Zuweisung sowieso schon die Ganze Zeit in Wirklichkeit in dieses DWORD hinein geschrieben.

AT bedeutet :
Die Variable DWORD (in deinem Fall) wird außerdem noch als ARRAY[0..31] of BOOL betrachtet / verwendet. Es bleibt aber die gleiche Variable ...

Gruß
LL
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... ich habe mich in deinem Code verlesen - du arbeitest ja mit einer temp-Variablen. Somit mußt du natürlich rück-kopieren - außer du machst die AT-Sicht auf die Quell-Variable - das geht auch und erspart das kopieren ...
 
... das mußt du natürlich nicht so machen - es geht auch so wie bei dir.
Mein Beispiel erzeugt nur einen wesentlich geringeren Code und damit verbundene Bearbeitungszeit. Außerdem halte ich ihn für etwas übersichtlicher ;)

Ist im Prinzip wie in AWL. Du kannst es so machen :
Code:
U E100.0
S M10.0
UN E 100.0
R M10.0
oder so :
Code:
U E100.0
= M10.0

Gruß
LL
 
Guten Morgen,

an Larry also dein Tip mit dem AT Befehl funktioniert soweit. nur habe ich jetzt das Problem da wo die lokale Variable übergeben wird es in der Form 16#0000000 gemacht ich bräuchte es aber in der Form 2#00000000000000000000000000000000 also als Bitmuster.

Kennst du einen Befehl in SCL der mir das umwandeln kann!?

Grüßle
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Matthias,
das ist keine Umwandlung sondern eine Darstellung.
2#1111 ist das gleiche wie w#16#F oder 15.
Ich kenne keinen Weg, wie man SCL dazu veranlassen kann, in der Beobachten-Status-Anzeige das Anzeige-Format zu ändern.
WORD's und DWORD's werden hier in hex dargestellt,
INT und DINT in dezimal,
BOOL als true oder false ...

Du müßtest hier also die Variablen-Tabelle für das DWORD im I-DB zu Hilfe nehmen ...

Gruß
LL
 
na wär ja auch zu einfach gewesen wenn es an dem problem liegt :)!

Danke für die Info werde es mir gleich mal im dazugehörigen Db anschauen.
 
So also habe mein problem gefunden wieso es nicht ging. Das mit dem AT befehl von dir larry hat einwandfrei gepasst. Das Problem war nur die "Ablage" im DWORD die Bits waren bei 16#0XX0000 sie müssen aber bei 16#00000XX sein also die letzten 2 stellen belegt. Für die die es interessiert hier die Code zeile in SCL
Code:
 Syn_temp_2 := SHR(IN:=Syn_temp, N:= 24 );

vielen dank für eure Hilfe. Mal schauen ob ich es jetzt ohne Probleme umgebaut bekomme.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ja Also das mit dem Schieben funktioniert leider nur wenn ich nur 1byte an eingängen angeschlossen habe. habe die vermutung das, dass High und Lowbyte getauscht werden müssen.

Weiß jemand wie das in SCl geht?

Genauer ist es im moment so das ich die Bity in der Form:
2#hhhhggggffffeeeeddddccccbbbbaaaa benötige sie aber durch das Programm so abgelegt werden
2#bbbbaaaaddddccccffffeeeehhhhgggg

und so kann ich sie leider nicht verarbeiten weiß aber grad echt nicht wie ich das machen soll
 
Hallo Matthias,
so wie ich das sehe mußt du in den Worten (des DWORD) die Bytes vertauschen. Das kannst du entweder bei der Zuweisung machen oder nachträglich, wenn du die weitere AT-Sicht generierst :
Code:
   word_array_Status AT dw_Status: Array [0..1] of word ;
das könnte dann in der Konsequenz so aussehen :
Code:
 word_array_Status[0] := ROL (IN:= word_array_Status [0] , n:=8) ;
 word_array_Status[1] := ROL (IN:= word_array_Status [1] , n:=8) ;
versuch das mal ...
 
Ok

das klingt nicht unlogisch :). Weiß jetzt nur nicht wie ich es dann mit dem schreiben machen soll. Also wo ich die Variablen einbinde.

im mom ist der Code so: (wie du siehts habe ich dein vorschlag angenommen ohne die If Abfragen)

Code:
FUNCTION FC9 : Void
VAR
    // temporäre Variablen
Syn_temp : DWORD;
Syn_temp_2 :DWORD;
Syn_Status_temp  AT Syn_temp  : ARRAY[0..31] OF BOOL;
syn_Word AT syn_temp_2: ARRAY [0..1] OF WORD;
END_VAR
 
    "P_Systemdaten".Anl_Synoptik.Syn_Aktiv[0] := TRUE;
    "P_Systemdaten".Anl_Synoptik.Syn_Aktiv[1] := TRUE;
    "P_Systemdaten".Anl_Synoptik.Syn_Aktiv[2] := TRUE;
    "P_Systemdaten".Anl_Synoptik.Syn_Aktiv[3] := TRUE;
    "P_Systemdaten".Anl_Synoptik.Syn_Aktiv[4] := TRUE;
    "P_Systemdaten".Anl_Synoptik.Syn_Aktiv[5] := TRUE;
    "P_Systemdaten".Anl_Synoptik.Syn_Aktiv[6] := TRUE;
    "P_Systemdaten".Anl_Synoptik.Syn_Aktiv[8] := TRUE;
(* Initialisierung ----------------------------------------------------- *)
(* Anzeige ------------------------------------------------------------- *)
(* Anpassung durch den Programmersteller *)
"P_Systemdaten".Anl_Synoptik.Syn_Uebersicht_Index :=0;
"P_Systemdaten".Anl_Synoptik.Syn_Uebersicht_Aktiv[0] :=True;
(*Variablenüberprüfung*)
Syn_Status_temp[0]   := "P_I=0+S0-F04:14";
Syn_Status_temp[1]   := "P_I=00+S00-X31:703";
Syn_Status_temp[2]   := "P_I=00+S00-B33.3:4";
Syn_Status_temp[3]   := "P_I=00+S00-0F1:14";
Syn_Status_temp[4]   := "P_I=00+S00-F3:14";
Syn_Status_temp[5]   := "P_I=00+S00-F40:14";
Syn_Status_temp[6]   := "P_I=0+S0-0F22:14";
Syn_Status_temp[8]   := "P_I=00+S00-K15:1";
  
(* Anpassung durch den Programmersteller *)
(* usw *)
(* Anzeige ------------------------------------------------------------- *)
(*Schiebefunktion*)
(*Syn_temp_2 := SHR(IN:=Syn_temp, N:= 20 ); *)
syn_Word[0] := ROL (IN:= syn_word [0] , n:=8) ;
syn_Word[1] := ROL (IN:= syn_word [1] , n:=8) ;
"P_Systemdaten".Anl_Synoptik.Syn_Status := Syn_temp_2;
(* Anzeige Übersichtsseite --------------------------------------------- *)
"P_Systemdaten".Anl_Synoptik.Syn_Uebersicht_Status := "P_Systemdaten".Anl_Synoptik.Syn_Status = "P_Systemdaten".Anl_Synoptik.Syn_Ansicht ; (* Synoptik Uebersicht *)
    
END_FUNCTION
 
Zuletzt bearbeitet:
Zurück
Oben