2 Datenworte mit verschiedenen Bitlängen beschreiben

Dr Mik

Level-2
Beiträge
51
Reaktionspunkte
11
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,
trotz intensiver Suche bin ich bisher auf keine Lösung gestoßen.
Ich möchte bzw. muss mit ST, wie auf dem Bild dargestellt, mein aktuelles Datum und Uhrzeit in 2 Datenworte legen.
Leider schreibt mir die Kommunikation zwischen Galileo und CodeSys V3 zwei Datenworte vor.
Wie kann ich die angegebenen Bits beschreiben ?

Danke,
Markus

Bildquelle: Galileo Anwenderhilfe
 

Anhänge

  • Bild.jpg
    Bild.jpg
    31,3 KB · Aufrufe: 34
Mit SHL die Datumsbestandteile an die richtige Bitposition schieben und mit OR zusammenfügen.
Ungefähr so:
Code:
Word_1 := SHL(Stunden, 11) OR SHL(Minuten, 5) OR (Sekunden/2);
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielen Dank, PN/DP.
Mit SHL hatte ich es bereits in 4 Datenworte gelegt (jeweils 2 Zeitangaben), allerdings habe ich vorher noch mit USINT_TO_BYTE umgewandelt und dachte nun, mit BYTE belege ich auf jeden Fall schon mal 8 Bit, dann würde der Befehl nicht funktionieren, wenn ich 3 Angaben machen muss.
Werde es morgen mal so testen.
Gruß,
Markus
 
allerdings habe ich vorher noch mit USINT_TO_BYTE umgewandelt und dachte nun, mit BYTE belege ich auf jeden Fall schon mal 8 Bit, dann würde der Befehl nicht funktionieren, wenn ich 3 Angaben machen muss.
Dieses Wandeln zu Byte sollte nicht nötig sein. Ein Byte ist eh' nicht sonderlich hilfreich. Der Compiler sollte implizit zu WORD wandeln oder man muss explizit wandeln, dann aber ist WORD sinnvoll, weil am Ende WORD rauskommen soll. (Ich kenne Codesys nicht so genau, ob der Compiler meinen Code von #2 so frisst oder explizite Wandlungen verlangt)
Wie erhältst du denn auf deiner SPS Datum und Uhrzeit? Eine Struktur mit allen Bestandteilen schön einzeln getrennt oder ein spezieller irgendwie gepackter "DATE_AND_TIME"-Datentyp oder die Anzahl Sekunden seit 1970 oder was?
 
Guten Morgen.
Ja, sorry, das hätte ich auch gleich dazuschreiben können. Ich bekomme als Datentyp USINT.
Hier mal mein Code für 4 Datenworte:
Code:
byte_sek := USINT_TO_BYTE (lese_zeit.Second);
byte_min := USINT_TO_BYTE (lese_zeit.Minute);
byte_stunde := USINT_TO_BYTE (lese_Zeit.Hour);
byte_tag := USINT_TO_BYTE (lese_zeit.Day);
byte_monat := USINT_TO_BYTE (lese_zeit.Month);
word_jahr := USINT_TO_WORD (lese_zeit.Year);

gvl.a_date_time[0] := SHL (BYTE_TO_WORD(byte_min),n) OR BYTE_TO_WORD(byte_sek);  //höherwertiges Byte Minuten, dann Sekunden
gvl.a_date_time[1] := SHL (BYTE_TO_WORD(n),n) OR BYTE_TO_WORD(byte_stunde);  //höherwertiges Byte ist leer, dann Minuten
gvl.a_date_time[2] := SHL (BYTE_TO_WORD(byte_monat),n) OR BYTE_TO_WORD(byte_tag); //höherwertiges Byte Monat, dann Tag
gvl.a_date_time[3] := word_jahr;

"n" ist definiert als
Code:
n :BYTE :=8;
und gvl.a_date_time als
Code:
a_date_time : ARRAY[0..3]OF WORD;

Das hätte funktioniert, ich habe dann leider feststellen müssen, das Galileo nur 2 Datenworte verarbeiten kann.
Eventuell brauche ich ja eine andere Datum-Uhrzeit-Ausgangsstruktur ?
Ein USINT belegt doch auf jeden Fall 8 Bit in dem Word oder nicht ?

Markus
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die Wandelei, die du da treibst, macht gar keinen Sinn. Erst wandelst du eine 8Bit-Variable (USInt) in ein Byte und hinterher, fürs Schieben, wieder zurück in ein WORD. Ein USInt ist im Grunde schon ein BYTE.

Edit: ich habe da mal meinen Type-Fehler korrigiert - sorry dafür
 
Zuletzt bearbeitet:
Die Wandelei macht für mich auch keinen Sinn.
USINT = unsigned short Int = 8 Bit entspricht 1 Byte
Wenn du gar nichts explizit wandelst, sollte der ST-Compiler (nach meinen Vorstellungen ;) ) alles implizit über WORD abhandeln.

Hast du denn mal meinen Code von Beitrag #2 ausprobiert? Was sagt der ST-Compiler dazu?
 
Beispiel mit deinen Variablennamen:
Code:
gvl.a_date_time[0] := SHL(lese_Zeit.Hour, 11) OR SHL(lese_zeit.Minute, 5) OR (lese_zeit.Second / 2);  //1. Word mit Stunden Minuten Sekunden

oder falls der ST-Compiler die SHL mit USINT anmeckert, dann so:
Code:
gvl.a_date_time[0] := SHL(USINT_TO_WORD(lese_Zeit.Hour), 11) OR SHL(USINT_TO_WORD(lese_zeit.Minute), 5) OR USINT_TO_WORD(lese_zeit.Second / 2);

Das halbieren der Sekunden kann man alternativ anstatt Division durch 2 lese_zeit.Second / 2 auch mit SHR(lese_zeit.Second, 1) oder SHR(USINT_TO_WORD(lese_zeit.Second), 1) machen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hast du denn mal meinen Code von Beitrag #2 ausprobiert? Was sagt der ST-Compiler dazu?
Es wird kein Fehler ausgegeben, aber unter "Warnung" steht "Verschiebung um 11 überschreitet die Typgröße von USINT".
Galileo auf dem Touchpanel gibt dann den Fehler für das Word raus (type mismatch).
Ich teste jetzt mal Deine anderen Ansätze, danke Dir.
 
also dann so:
Code:
gvl.a_date_time[0] := SHL(USINT_TO_WORD(lese_Zeit.Hour), 11) OR SHL(USINT_TO_WORD(lese_zeit.Minute), 5) OR USINT_TO_WORD(lese_zeit.Second / 2);
So funktioniert es, kein Fehler oder Warnung vom Compiler. Die Meldung von Galileo ist auch weg, allerdings wird die Systemvariable "Date_Time" von Galileo immer noch nicht ausgewertet. Da werde ich mich aber an Eaton wenden.
Vielen Dank PN/DP und Larry.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Es wird kein Fehler ausgegeben, aber unter "Warnung" steht "Verschiebung um 11 überschreitet die Typgröße von USINT".
Wenn zuerst USINT nach WORD oder DWORD kopiert und danach in WORD bzw. DWORD um 11 BitPositionen nach links geschoben wird, sollte das aber nicht zu einer Warnung führen, sondern wunschgemäss ausgeführt werden.
 
Die Warnung wird jeweils für die erste Shift-Operation gezeigt mit Verschiebungen größer 8 Bit. Mit vorheriger Konvertierung lässt sich die Warnung vermeiden. Der Compiler konvertiert aber auch implizit zu Word. Ist also eher eine Frage, ob einen die Warnung stört.

Die Lösungen von oben ergeben das Zielformat aus dem Screenshot. Schau doch mal, ob Du nicht die beiden Worte verdreht hast.
Code:
gvl.aw_date_time[0] := SHL(TO_WORD(lese_Zeit.Hour), 11) OR SHL(lese_zeit.Minute, 5) OR (lese_zeit.Second / 2);
gvl.aw_date_time[1] := SHL(TO_WORD(lese_Zeit.Year), 9) OR SHL(lese_zeit.Month, 5) OR (lese_zeit.Day);
 
... und 32 Bits einzeln kopieren. Wow - so einfach! ;)
gvl.a_date_time[0] := SHL(USINT_TO_WORD(lese_Zeit.Hour), 11) OR SHL(USINT_TO_WORD(lese_zeit.Minute), 5) OR USINT_TO_WORD(lese_zeit.Second / 2);

So einfach wie du hab ich jetzt nicht hinbekommen , übersichtlich und jeder versteht es direkt, Wow.

War nur ein Vorschlag der auf Anhieb ohne Missmatch und Compilerwarnung funktioniert, sry
 
Du kannst auch einfach den Bitzugriff verwenden.

https://de.codesys.com/news-events/...f-einzelne-bits-in-numerischen-variablen.html

Code:
word_1.0 := Seconds.0;
.
.
.
word_1.5 := Minutes.0;
Nabend allerseits,
ja, den Bitzugriff kenne ich, bin allerdings nicht darauf gekommen, dass ich ja auch eine direkte Zuweisung darauf machen könnte, dafür programmiere ich leider viel zu selten. ;)
Ich werde Eure Vorschläge morgen mal testen.
Wie schon gesagt, leider macht meine Visu bzw. Galileo bisher nicht mit und nimmt die Daten aus dem Array nicht für die Datums- Uhrzeitanzeige.
Schönen Abend allen,
Markus
 
Guten Morgen zusammen.
Es läuft jetzt. In Verbindung mit einem Steuerbaustein für Codesys an Galileo, der von Eaton entwickelt bzw. geschrieben wurde, werden nun die Datums- und Uhrzeitdaten aktualisiert. Vielen Dank an alle für die Unterstützung.
Schönen Sonntag,
Markus
 
Zurück
Oben