CoDeSys Zeitsteuerung mittels Taskkonfiguration

Zuviel Werbung?
-> Hier kostenlos registrieren
Oder den BCD-Wert als Text/String ausgeben mit jedes Bit ist ein Zeichen '0' oder '1'?
... oder den BCD-Wert als Text/String ausgeben mit je einem der Zeichen '0' bis '9' für jede Tetrade?
Oder die Variablen z1 .. z4 aus Haralds #34 in je einem DezimalFeld anzeigen ... aber dann würde man sich natürlich fragen, "wozu der ganze Aufwand?", wenn die Visu "intern" die Wandlung in BCD sowieso ausführt und sie dabei keiner Nachhilfe bedarf. Sie kann ja sogar den nächsten Schritt: die Umwandlung in ASCII-Zeichen.
So bekommt man mal eine Vorstellung davon, was in einer Visu oder in einem PG u.a. alles so ablaufen muss, bis die Daten in lesbarer Form anzeigt werden können.
"Wozu soll ich das noch wandeln? Am PG kann ich doch sehen, dass es im Speicher schon so drinsteht." bekam ich mal von einem Kollegen zu hören, der die Ausgabe auf einem Panel programmieren sollte, das schlicht und einfach nur die fix und fertig angelieferten ASCII-Zeichen anzeigen konnte ;)
 
Zuletzt bearbeitet:
Danke euch allen für die große Mühe und Hilfe.

Ihr gebt einem wirklich gute Tipps. Auch so, dass man selbst nochj nachdenken muss. Leider gibt es immer mehr Leute, die einfach nur fertige Lösungen wollen. Und dann wundert sich der Arbeitsmarkt warum solche Leute dann nichts können.

Danke euch allen. Falls noch Fragen sind, quäle ich euch einfach ein bisschen8):-D:-D
 
[myInt muß im Bereich 0..9999 sein!
z1 := myInt / 1000;
z2 := (myInt / 100) MOD 10;
z3 := (myInt / 10) MOD 10;
z4 := myInt MOD 10;
OutBCD := z1 * 4096 + z2 * 256 + z3 * 16 + Z4;/QUOTE]

@PN/DP

Kann mir jemand vielleicht die Rechnung am Ende erklären ? Ich komme nicht so ganz dahinter. Also die Zusammenrechnung der einzelnen Moduloergebnisse.
Warum nehme ich das mal 4096, dann mal 256 usw. Woher kommt diese Herleitung. Den Rest habe ich verstanden. Ich würde mich freuen, wenn mir das jemand zum Verständnis kurz erläutern könnte.
 
Falscher Ansatz.
Jede DezimalStelle isolieren (Division und Mod) mit 10er Potenzen und mit entsprechender 16er Potenz multiplizieren (mal 16^3 entspricht nach links schieben um 12 Positionen; mal 16^2 entspricht nach links schieben um 8 Positionen; mal 16^1 entspricht nach links schieben um 4 Positionen). ZwischenErgebnisse zusammenODERn.
Sorry, ausführliche Antwort kann ich im Moment nicht so schnell geben. In FUP dauert's noch viel länger ...

Da war schon jemand so freundlich :)
 
Hallo alle,

leider verstehe immer noch eine Sache nicht ganz. Und zwar das Shifting mit der 16^3 und 16^2.

Ich habe eine vierstellige positive Dezimalzahl 1234. Diese ergibt 8-4-2-1-BCD codiert eine 16 Bit Binärzahl. Klar pro Dezimalzahl gibt es eine Tetrade.
Soweit so gut.

Also selektiere ich jede einzelne Dezimalzahl mithilfe der MUL,DIV,ADD und MOD Operatoren. Soweit auch klar.

Ich verstehe aber den letzten Schritt nicht. Warum schiebe ich nun die Zahl 1 um 16^3 nach links? Eine Umwandlung ins Hexadezimalystem erfolgt doch durch Division der Dezimalzahl durch 16. Also kann es das schon mal nicht sein.

Meine Überlegung ist nun, dass es an dem 16Bit Datentyp liegt. 16^0 ist die erste Tetrade, 16^1 die zweite, 16^2 die dritte und 16^3 die vierte. Da die 1 binär ja 0001 lautet, muss diese Zahl um 12 Stellen nach links verschoben werden, sodass sie in der vierten Tetrade ist. Das wäredann die 1000von den 1234. Die vierte Tetrade ist ja 16^3. Aber warum multipliziere ich das jetzt?
Und wie wäre es , wenn ich dann eine Zahl hätte, die BCD-codiert ein DWORD ergeben würde. Also 32 BIT. das wären ja dann 8 Tetraden. Hätte ich dann das BIT um 32^7 verschieben müssen??? Sorry für all die Frgen, aber mir ist es wirklich wichtig, dass ich es auch verstehe.
 
Ihr gebt einem wirklich gute Tipps. Auch so, dass man selbst noch nachdenken muss.
Hier kommt von Tausenden denkbaren Lösungswegen einer zum Nachdenken:
Code:
iTmp1 := Eingabe;
IF iTMP1 >= 0 AND iTmp1 <=9999 THEN

    wErg  := 0;

    iTmp2 := iTmp1 / 10 ** 3;
    wErg  := wErg OR SHL(IN:= INT_TO_WORD(iTmp2); N:= 4 * 3);  // links schieben um 12 BitPos entsprechend * 16^3 also * 4096
//  wErg  := SHL(IN:= wErg; N:= 4) OR INT_TO_WORD(iTmp2);  // alternativ zur vorausgehenden Zeile
    iTmp1 := iTmp1 - iTmp2 * 10 ** 3;  // "Ersatz" für iTmp1 MOD 10^3
    
    iTmp2 := iTmp1 / 10 ** 2;
    wErg  := wErg OR SHL(IN:= INT_TO_WORD(iTmp2); N:= 4 * 2);  // links schieben um  8 BitPos entsprechend * 16^2 also * 256
//  wErg  := SHL(IN:= wErg; N:= 4) OR INT_TO_WORD(iTmp2);  // alternativ zur vorausgehenden Zeile 
    iTmp1 := iTmp1 - iTmp2 * 10 ** 2;  // "Ersatz" für iTmp1 MOD 10^2
    
    iTmp2 := iTmp1 / 10 ** 1;
    wErg  := wErg OR SHL(IN:= INT_TO_WORD(iTmp2); N:= 4 * 1);  // links schieben um  4 BitPos entsprechend * 16^1 also * 16
//  wErg  := SHL(IN:= wErg; N:= 4) OR INT_TO_WORD(iTmp2);  // alternativ zur vorausgehenden Zeile 
    iTmp1 := iTmp1 - iTmp2 * 10 ** 1;  // "Ersatz" für iTmp1 MOD 10^1
    
    iTmp2 := iTmp1 / 10 ** 0;
    wErg  := wErg OR SHL(IN:= INT_TO_WORD(iTmp2); N:= 4 * 0);  // links schieben um  0 BitPos entsprechend * 16^0 also * 1           
//  wErg  := SHL(IN:= wErg; N:= 4) OR INT_TO_WORD(iTmp2);  // alternativ zur vorausgehenden Zeile 
    iTmp1 := iTmp1 - iTmp2 * 10 ** 0;  // "Ersatz" für iTmp1 MOD 10^0
    
ELSE

    wErg  := 16#FFFF // Fehler

END_IF;
Sieht furchtbar unelegant und aufwändig aus. Lässt ein wenig die Systematik durchblicken, legt die Realisierung in einer FOR-Schleife nahe (FOR idx := 3 TO 0 BY -1 DO) und kommt ohne den MOD-Operator aus.
Zu Deiner Frage nach der letzten Anweisung in Haralds Vorschlag: hier wird's scheibchenweise (à la Salami) gemacht, jedoch mit LinksSchieben und Odern statt Multiplizieren und Addieren.

PS:
Hast Du schon darüber nachgedacht, warum Dein Ansatz mit WahrheitsTabelle nicht so recht zum Ziel führt?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Warum schiebe ich nun die Zahl 1 um 16^3 nach links?
Weil die Zahl 1 als BCD die Stellen/Positions-Wertigkeit 16^3 hat.

Aber warum multipliziere ich das jetzt?
Weil viele Wege nach Rom führen ;) und weil "a * 16 + b * 256" verständlicher und einfacher/schneller getippt ist als "SHL(a, 4) + SHL(b, 8 )" (und Compilerfreundlich alle Operanden in der Formel vom Datentyp INT sind)

In FUP sind beide Wege gleich aufwendig einzugeben:
Code:
    +-----+              +-----+
    | MUL |              | SHL |
 a--|     |---   =    a--|     |---
    |     |              |     |
16--|     |           4--|     |
    +-----+              +-----+
Bei BCD sind immer 4 Bits (eine Tetrade) eine Ziffer - wie bei Hexadezimalzahlen, mit dem Unterschied daß nur die Ziffern 0 bis 9 zulässig sind. Wegen der 4 Bits ist die Positions-Wertigkeit einer Ziffer eine 16-er Potenz, entsprechend der Position wo die Ziffer steht.

Eine Dezimalzahl (Basis 10) der Form abcd hat den Wert: a * 10^3 + b * 10^2 + c * 10^1 + d * 10^0
Eine BCD-Zahl (Basis 16) der Form BCD#abcd = 16#abcd hat den Wert: a * 16^3 + b * 16^2 + c * 16^1 + d * 16^0

Bei allen Zahlenformaten/Zahlensystemen entspricht die Verschiebung um eine Ziffernstelle nach Links einer Multiplikation mit der Basis des Zahlensystems. Eine Verschiebung um eine Ziffernstelle nach Rechts entspricht einer Division mit der Basis des Zahlensystems.

Bei Binärzahlen entspricht die Verschiebung um 1 Stelle (1 Bit) nach Links der Multiplikation mit 2 (dez), um 2 Stellen nach Links der Multiplikation mit 4 (dez) ... um 4 Stellen nach Links der Multiplikation mit 16 (dez) usw.

Bei BCD- und Hexadezimalzahlen entspricht die Verschiebung um 1 Ziffernstelle (1 Tetrade) nach Links einer Multiplikation mit 16 = 16^1, um 2 Ziffernstellen nach Links einer Multiplikation mit 16 * 16 = 16^2 = 256, um 3 Ziffernstellen nach Links einer Multiplikation mit 16 * 16 * 16 = 16^3 = 4096 usw.

Eine Umwandlung einer Dezimalzahl in eine BCD-Zahl ist nicht nur eine Änderung der Ansicht des Wertes in einem anderen Zahlensystem (wie z.B. 1234 = 16#04D2) sondern die Dezimalziffern werden in jeweils 4 Bits untergebracht/neu gruppiert, wodurch sich 1234 ---> BCD#1234 = 16#1234 (= 4660 dezimal) ergibt.


Und wie wäre es , wenn ich dann eine Zahl hätte, die BCD-codiert ein DWORD ergeben würde. Also 32 BIT. das wären ja dann 8 Tetraden. Hätte ich dann das BIT um 32^7 verschieben müssen???
Wenn Du eine Dezimalzahl der Form 12345678 hast, dann mußt Du die 1 mit 16^7 multiplizieren oder um 7 * 4 = 28 Bit nach Links schieben.
12345678 ---> BCD#12345678 = 16#12345678:
1 * 16^7 + 2 * 16^6 + 3 * 16^5 + 4 * 16^4 + 5 * 16^3 + 6 * 16^2 + 7 * 16^1 + 8 * 16^0

Harald
 
Zurück
Oben