Hinweis: Nutzen Sie bei der Programmierung nach Möglichkeit bereits vorhandene Funktionen und Funktionsblöcke wie z.B. die INT_TO_BCD Funktion.
INT_TO_BCD ist also nicht zwingend vorgeschrieben.
Die Aufgabe wird in
Codesys 2.3.9. visualisiert und simuliert
Visualisiert mit einer grafischen Visu? Dann brauchst Du die 28 Segmente gar nicht als 28 einzelne Bit-Ausgänge. Sondern 4 (notfalls nur 1) Variablen für die Visu, also 1 Variable je Ziffer.
( Für die Visualierung könnte man die 7-Segment-Dekodierung weglassen bzw. direkt in der Visu machen, indem jede Ziffer aus einer Liste/Array von 10 vorgefertigten Bildern angezeigt wird. )
Oder für jede Ziffer ein Byte vorsehen, wo jedes Segment einem Bit zugeordnet ist, und die Visu animiert 28 Segmente durch Abfrage des zugehörigen Bits:
Einer_Segment_a: Byte_E Bit0
Einer_Segment_b: Byte_E Bit1
...
Einer_Segment_g: Byte_E Bit6
Zehner_Segment_a: Byte_Z Bit0
...
Tausender_Segment_g: Byte_T Bit6
Insgesamt werden 4 * 7 = 28 Segmente benötigt.
Nun kann man simpel aber aufwändig für jedes Segment eine Verknüpfung der 16 BCD-Bits programmieren entsprechend der
Wahrheitstabelle für 7-Segmentdekoder = 28 Verknüpfungen (so wird ein 7-Segment-Decoder in Elektronik realisiert)
Code:
Einer_Segment_a := E1 OR (E2 AND E0) OR E3 OR (NOT(E2) AND NOT(E0));
oder
Einer_Segment_a := NOT( NOT(E3) AND NOT(E2) AND NOT(E1) AND E0) OR (NOT(E3) AND E2 AND NOT(E1) AND NOT(E0) );
...
Tausender_Segment_g := ...
Man kann auch aufwändig für jedes Segment eine Verknüpfung von Vergleichen (=, <>, >=, <=, ...) progammieren = 28 Verknüpfungen
Code:
Einer_Segment_a := NOT (E = 1 OR E = 4); //oder: E <> 1 AND E <> 4
...
Tausender_Segment_g := NOT(T = 0 OR T = 1 OR T = 7); //oder: T <> 0 AND T <> 1 AND T <> 7
Oder mit der CASE-Anweisung direkt das 7-Segment-Bitmuster an das Visu-Byte zuweisen je nach Wert der Ziffer = 4 CASE-Konstrukte je 10 Fälle.
Oder die 7-Segment-Bitmuster vorberechnet in einer Tabelle (ARRAY OF BYTE) hinterlegen und 4 mal mit dem Wert der Ziffer als Index das zugehörige Bitmuster aus der Tabelle lesen. (siehe Beispielcode unten)
Wie aber erwähnt, könnte ich nach diesem Verfahren nur eine Anzeige ansteuern und nicht mehrere. Ich müsste also mein Vorgehen grundsätzlich
überdenken.
Damit sich großer Code-Aufwand für 4 Ziffern nicht vervierfacht gegenüber der Lösung für eine Ziffer, kann man eine Function für eine Ziffer schreiben und viermal aufrufen, oder mit Stellen-Arrays und Programmschleife arbeiten. Besser: eine Lösung verwenden, wo der Code für eine Ziffer so kurz ist, daß eine Vervierfachung immer noch kürzer als Schleifen ist, ein umschreiben zu Schleife also nicht lohnt.
Für alle Lösungen gemeinsam braucht man die Isolierung/Zerlegung der Eingangszahl in einzelne Dezimalziffern.
Hierfür kann man nun INT_TO_BCD verwenden (ist aber in Codesys relativ umständlich, siehe Beitrag #2). Besser finde ich die Ziffernzerlegung mit MOD (ebenfalls siehe Beitrag #2).
Codebeispiel mit vorberechneter 7-Segment-Bitmuster-Tabelle (ungetestet)
Code:
VAR_INPUT
v : INT; //Eingangswert, davon werden die niederwertigsten 4 Ziffern decodiert
END_VAR
VAR_OUTPUT
Ziffer_E : BYTE ; //7-Segment-Bitmuster Einer-Stelle: a=Bit0 .. g=Bit6
Ziffer_Z : BYTE ; //7-Segment-Bitmuster Zehner-Stelle
Ziffer_H : BYTE ; //7-Segment-Bitmuster Hunderter-Stelle
Ziffer_T : BYTE ; //7-Segment-Bitmuster Tausender-Stelle
END_VAR
VAR
Bitmuster : ARRAY[0..9] OF BYTE := ( 16#3F, 16#06, 16#5B, 16#4F, 16#66,
16#6D, 16#7D, 16#07, 16#7F, 16#6F );
END_VAR
Ziffer_E := Bitmuster[v MOD 10];
Ziffer_Z := Bitmuster[(v / 10) MOD 10];
Ziffer_H := Bitmuster[(v / 100) MOD 10];
Ziffer_T := Bitmuster[(v / 1000) MOD 10];
Ausgangssetig sollen direkt die einzelnen Segmente a bis g angesprochen werden.
Wenn Du 28 BOOL-Variablen brauchst, dann kannst Du die Bytes noch aufdröseln:
Code:
E_Segment_a := Ziffer_E.0;
...
E_Segment_g := Ziffer_E.6;
Z_Segment_a := Ziffer_Z.0;
...
T_Segment_g := Ziffer_T.6;
Harald