Liebe Forum Teilnehmer Habe folgendes Problem. Ich möchte eine funktionierende Uhr "Stunden+Minuten" erweitern so dass sie auch Sekunden anzeigt. Den Quellcode habe ich mit meinen bescheidenen Programmierer Kenntnissen erweitert. Leider nur mit mäßigem Erfolg. Die Sekunden werden zwar angezeigt "die laufen nach 59 bis 99 weiter" und die restliche Anzeige ist ein "CHAOS". Im Anhang findet Ihr den Schalt- plan sowie die Quelltexte. Die Erweiterungen sind farblich hinterlegt. Die Anoden der Anzeige habe ich folgender maßen angeschlossen. E=PC5;Z=PC4;H=PC1;T=PC0;ZT=PC2;HT=PC3; Für eine Hilfe wäre ich danbar. Gruß Wilfried
Quelltexte im RTF-Format wird sich hier niemand anschauen. Oder drehst Du sie etwa auch so durch den Compiler?
Wilfried schrieb: > Im Anhang findet Ihr den Schalt- > plan sowie die Quelltexte. Dein Quelltext möchte 6 Stellen, dein Schaltplan hat nur 4 Stellen, das geht logischerweise nicht. Dann flickst du mal die Sekunden rechts und mal links an die Zahl. Die Zahl number wird dadurch grösser als 2359, nämlich 235959, zu viel für ein 'int' der maximal 32767 fasst. Die Hälfte vom Quellcode, auf dem interruptgesteuert die Stellen der Zahl verteilt werden, fehlt. Will man 2 Stellen mehr, muss der natürlich auch geändert werden. Die Ziffern werden bei 6 statt 4 Stellen noch dunkler, schon so laufen sie mit durchschnittlich nur 750uA.
Beitrag #7688482 wurde von einem Moderator gelöscht.
Wilfried schrieb: > Für eine Hilfe wäre ich danbar. Häng einfach direkt die Quellcodedateien an (am besten das Original und deine geänderte Version), und nicht irgend so ein rtf-Zeug. Und gib den Dateien sinnvolle Namen. > E=PC5;Z=PC4;H=PC1;T=PC0;ZT=PC2;HT=PC3 Wie wäre es, wenn du den Stellen ebenfalls sinnvolle Namen gibst, So eine Uhr zählt nicht dezimal, deshalb sind Zehntausender und Hunderttausender sinnlos, kein Mensch sagt: "Es ist Zweihundertzweiunddreißigtausendvierhundertsechsundfünfzig Uhr!". hz,he,mz,me,sz und se wären meine Wahl für die 6 Stellen.
:
Bearbeitet durch Moderator
Es fehlt latuernich noch zwei Transistoren um das Multiplexing von vier auf sechs Stellen zu erweitern. TO: Hast Du einfach ein paar Sieben-Segment-Displays parallel geschaltet? Das geht nicht.
Den Gedankengang möchte ich mal verstehen. Erst verwurstet man alle Variablen zu einer großen Zahl, um sie dann umständlich wieder zu entwursten. Wozu der unnötige Aufwand? Typisch nimmt man gerne für jedes Digit eine Variable, dann braucht man für die Anzeige überhaupt nichts zu rechnen. Und vor allem hat man wenigstens 2 Tasten, um die Uhr zu stellen (Digitauswahl, Weiterzählen). Und zeichne erstmal Deinen Schaltplan auf 6 Digits erweitert. Vorher kann man das ja nicht programmieren.
Peter D. schrieb: > Erst verwurstet man alle > Variablen zu einer großen Zahl, um sie dann umständlich wieder zu > entwursten. Wozu der unnötige Aufwand? Allenfalls BCD könnte sinnvoll sein. Die Multiplex-Ausgabe mit Pufferung wird dann recht einfach.
:
Bearbeitet durch User
Rainer W. schrieb: > Allenfalls BCD könnte sinnvoll sein. Das kriegt man mit Peter D. schrieb: > Typisch nimmt man gerne für jedes Digit eine Variable doch automatisch. Jede der pro-Digit Variablen kann nur einen Wert zwischen 0 und 9 (je nach Stelle auch 6 oder 4 oder 2) enthalten. Die ALU des µC muß dann auch keine BCD-Arithmetik beherrschen. Für eine Uhr braucht es ohnehin nur die INC Operation.
Teo D. schrieb: > So, und nu basteln wir noch ne Weckfunktion dazu... :DDD Ha! Das erinnert mich daran, wie ich mal auf einem Poly-880 [1] eine Uhr mit Weckfunktion programmiert habe. Die hat zur Weckzeit dann die Melodie "Wachet auf, wachet auf, es krähte der Hahn!" gespielt. Das ging sehr komfortabel, denn der Poly-880 hatte einen Fernschreiber(!) Anschluß mit einer Lautsprecherbuchse. Da brauchte man nur eine Box anzustecken. Das Programm paßte natürlich komplett in die 1KB RAM. Und wurde als Maschinencode direkt mit der Hex-Tastatur eingegeben. Die Zeit wurde auf der 8-stelligen LED-Anzeige angezeigt. Damals habe ich sicherlich die BCD-Arithmetik (packed BCD) verwendet, die der Z80 ja beherrschte. [1] https://de.wikipedia.org/wiki/Polycomputer_880
Teo D. schrieb: > So, und nu basteln wir noch ne Weckfunktion dazu... Uhren-Quäl-Code. Wilfried schrieb: > uhrenquelcode
Wilfried schrieb: > Hast du meine Nachricht mit den Dateien bekommen? Nein, da ist nichts gekommen. Aber poste die Dateien doch bitte als Anhang hier im Thread. Dafür ist er da. Dann können dir auch andere zur Seite stehen.
:
Bearbeitet durch Moderator
Hi Um ein Programm so zu erweitern, damit auch eine erweiterte Hardware angesteuert werden kann, solltest du die Programmiersprache verstehen. Wenn ein Programm gut modular aufgebaut ist, dann ist es in der Regel kein Problem. Manchmal ist es aber besser, das Programm neu zu schreiben. Erstens, man lernt die Sprache, zweitens, man versteht das Programm. Dazu einfach mal einen brainstorm was gebraucht wird: Einen Taktgeber 1 Sek. Zwei Speicher jeweils 6 stellig für Zähler und Dekoder. Nun zählst du einfach die Sekunden und überträgst bei 9 nach 0 sowie eins in die Zehner-Stelle. Zehnerstelle von 5 nach 0 und eins in die Minute. 9 nach 0 Minutenzehner +1. Minuten 5 nach 0 + Stunde 1. Nun wird es ein wenig komplizierter, weil ja nach 23 ein neuer Tag mit Stunde 0 beginnt. Ist die Zehnerstunde <2 muss die einer Stunde bis 9 zählen, bevor die Zehnerstunde um eine erhöht wird, Ist die Zehnerstelle der Stunden >1 setzt du beim Übergang von 3 nach 4 alles auf 0. damit wäre dein Zeitzähler fertig. Kommt nun die Anzeige. Die rufst du entweder in jedem Zyklus auf, oder noch besser, alle 10 ms per Interrupt. Anzeige ausschalten, nächste Stelle adressieren Anzeigemuster aus dem Variablenpuffer in den Ausgabeport laden. Nächstes Segment ansteuern und Anzeige einschalten. Jetzt hast du zwei Module, ein Zählermodul mit den Zeitwerten und ein Ausgebemodul mit der Zeitanzeige, die ja ganz anders aufgebaut ist, eben Siebensegment. Nun brauchst du nur noch die Verbindung herstellen, das reicht, wenn du es in den Programmzyklus einbaust. Dazu brauchst du 10 Speicherzellen, die du mit dem Anzeigemuster der Siebensegmentanzeige von 0 - 9 belegst. Nun nimmst du die erste Stelle deines Zeitzählers, lädst den Wert, holst die Anfangsadresse deines Matrixpuffers, addierst den geladenen Wert dazu und holst aus dem Matrixpuffer das Anzeigemuster. Dieses legst du in den Ausgabepuffer. Das machst du mit jeder Stelle. Ich kann dir keinen C-Code liefern, das musst du schon selber machen, aber mit diesem Fahrplan solltest du es schaffen. Gruß oldmax
Martin V. schrieb: > Um ein Programm so zu erweitern, damit auch eine erweiterte Hardware > angesteuert werden kann, solltest du die Programmiersprache verstehen. Ach! Echt jetzt?
Hi oldmax Danke für deine Zeit und ausführliche Beschreibung. Du hast recht ich muss mich noch intensiver mit der Thematik programmieren auseinandersetzen. Habe vor zwei Jahren mit der Programmiersprache C angefangen. Da ich zum alten „Eisen“gehöre ist das lernen nicht mehr so einfach wie früher. Ich dachte jemand schaut sich den original Qeueltext sowie meine Änderungen an korrigiert diese evt.mit Kommentar und lässt sie mir zukommen. Danke nochmals Gruß Wilfried
Wilfried schrieb: > Da ich zum alten „Eisen“gehöre ist das lernen nicht mehr so > einfach wie früher. Ich dachte jemand schaut sich den original Qeueltext > sowie meine Änderungen an korrigiert diese evt.mit Kommentar und lässt > sie mir zukommen. Immer noch aktuell: Beitrag "Re: Hilfe bei Z80 Opcodes" > Und nein, dieses Forum ist zwar hilfreich, aber es ist kein > Cola-Automat, wo man auf den Knopf drückt und schon kommt der Pappbecher > mit dem fertigen Drink heraus. Etwas eigene Arbeit (auch > Einarbeitungsarbeit in den Z80) wäre vonnöten gewesen, schließlich ist > es DEINE Maschine, die jetzt doof herumsteht und nicht mehr benutzbar > ist. Code-Review kann man machen wenn Du die Kosten traegst. Gruesse
Wilfried schrieb: > Ich dachte jemand schaut sich den original Qeueltext > sowie meine Änderungen an korrigiert diese evt.mit Kommentar und lässt > sie mir zukommen. Sobald Du den neuen Schaltplan und den neuen Quelltext vollständig als *.c hier reinstellst, sollte das kein Problem sein. Für den Schaltplan geht auch eine Handzeichnung, muß kein ECAD sein. Es hängt also von Dir ab.
Wilfried schrieb: > Ich dachte jemand schaut sich den original Qeueltext sowie meine > Änderungen an Weil du dich damit offenbar sehr, sehr schwertust, habe ich für dich mal deinen Quellcode wieder in C-Files umgewandelt und hier angehängt. Zum grundlegenden Problem wurde schon etwas gesagt: in einen int16_t passen nur Zahlen von 0 bis 65536. Das kann nicht funktionieren, wenn du damit dann 24 x 3600 = 86400 Sekunden pro Tag darin unterbringen willst. Oder viel schlimmer noch, Zahlen bis zu 235959, weil du das augenscheinlich ja irgendwie mit Divisionen durch Zehnerpotenzen auf die einzelnen Segmente aufteilen willst. > Habe vor zwei Jahren mit der Programmiersprache C angefangen. Sieh dir an, wie groß der Wertebereich der Datentypen uint8_t, uint16_t, int, long usw. ist. Mein Ansatz für eine Uhr wäre etwa so: - in einem Interrupt wird jede Sekunde ein uint8_t Flag_1s gesetzt. - in der Mainloop wird dieses Flag abgefragt und dann entsprechend reagiert - dabei wird jede Stelle (Stunden, Minuten, Sekunden jeweils Zehner und Einer) einzeln für sich behandelt
1 | unit8_t hz,he,mz,me,sz,se; |
2 | |
3 | timerinterrupt() { |
4 | Flag_1s = 1; |
5 | }
|
6 | |
7 | main() { |
8 | for(;;) { // mainloop |
9 | if (Flag_1s) { |
10 | Flag_1s = 0; // Flag zurücksetzen |
11 | if (se < 9) se++; |
12 | else { |
13 | se = 0; |
14 | if (sz < 5) sz++; |
15 | else { |
16 | sz = 0; |
17 | if (me < 9) me++; |
18 | else { |
19 | me = 0; |
20 | if (mz < 5) mz++; |
21 | else { |
22 | mz = 0; |
23 | if (he < 9) { |
24 | he++; |
25 | if (hz==2 && he==4) hz = he = 0; // Tagesüberlauf |
26 | }
|
27 | else { |
28 | he = 0; |
29 | if (hz < 2) hz++; |
30 | }
|
31 | }
|
32 | }
|
33 | }
|
34 | }
|
35 | }
|
36 | }
|
37 | }
|
:
Bearbeitet durch Moderator
So ähnlich gehts auch in ASM. Nur dass unzählige PUSH und POP erscheinen. Erst einmal disassemblieren. Aber da fehlen dann "Labels" und Kommentare. Mach das mal. Aus den Defs des Target die Registerzuordnung wieder in "Klartext" herausklamüsern.(TCRROA ist zum Beispiel R24)
1 | +0000001C: E6A0 LDI R26,0x60 Load immediate |
2 | +0000001D: E0B0 LDI R27,0x00 Load immediate |
3 | +0000001E: 2788 CLR R24 Clear Register |
4 | +0000001F: 938D ST X+,R24 Store indirect and postincrement |
5 | +00000020: 9731 SBIW R30,0x01 Subtract immediate from word |
6 | +00000021: F7E9 BRNE PC-0x02 Branch if not equal |
7 | +00000022: B784 IN R24,0x34 In from I/O location |
8 | +00000023: 2E08 MOV R0,R24 Copy register |
9 | +00000024: 7F87 ANDI R24,0xF7 Logical AND with immediate |
Nur Schnipsel als Beispiel. Wenn man schon ein Hex-File hat, könnte man das so machen. Sowas nennt man dann "Reverse-Engineering". Martin V. schrieb: > Wenn ein Programm gut modular aufgebaut ist, dann ist es in der Regel > kein Problem. Manchmal ist es aber besser, das Programm neu zu > schreiben. Schließe mich der Meinung an. Viel Spaß ciao gustav [Mod: code-Tags hinzugefügt, da sonst auf Mobilgeräten unlesbar]
:
Bearbeitet durch Moderator
Andreas S. schrieb: > Quelltexte im RTF-Format wird sich hier niemand anschauen. Also irgendwas stimmt mit deiner Aussage nicht! Siehe: Michael B. schrieb: > Dein Quelltext möchte 6 Stellen, dein Schaltplan hat nur 4 Stellen, das > geht logischerweise nicht. Lieber Andreas, nehme deinen Namen zum Vorbild: Schweige still !
Karl B. schrieb: > So ähnlich gehts auch in ASM. > Nur dass unzählige PUSH und POP erscheinen. Halb so wild, der Code ist sicher trotzdem schnell genug. Ich habe meinen Code zur Uhr dort mal zum Test laufen lassen: - https://onlinegdb.com/43O72umVg In der Console (siehe Anhang) sieht man dann den tadellosen Ab- und Überlauf an den Minuten-, Stunden- und Tagesübergängen. Und die 6 Stellen der Uhr jetzt auf die Anzeige zu multiplexen, statt auf der Console auszugeben, dürfte kein Problem mehr sein. Jens K. schrieb: > Schweige still ! Hast du auch was zum Thema zu sagen? Natürlich sieht sich bestenfalls der Allergutmütigste so eine rtf-Datei an. Jeder andere denkt sich: "Was für ein unnötiges Gelecke!" BTW: bitte nicht Plenken!
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Karl B. schrieb: >> So ähnlich gehts auch in ASM. >> Nur dass unzählige PUSH und POP erscheinen. > Halb so wild, der Code ist sicher trotzdem schnell genug. Ging doch garnicht um ASM versus C. Wenn ich etwas aus dem Chip auslese, ist es doch bei den Atmels ATMega8 hex. Und ich kenn das dann nur so, dass ich es dann automatisch in ASM "übersetzt" bekomme mit einem Disasemblierprogramm. Nur die Extra-Mühe, die man sich dann damit macht, kann man sich sparen. Gleich neu aufsetzen. Hat Lothar ja gezeigt. Stichwort "Jobregister". ciao gustav
:
Bearbeitet durch User
Karl B. schrieb: > Ging doch garnicht um ASM versus C. > Wenn ich etwas aus dem Chip auslese, ist es doch bei den Atmels ATMega8 > hex. Inkorrekt. Du kriegst ein Abbild des Flashs. Ob binär oder (Intel) HEX ist vollkommen nebensächlich. Und da kann alles mögliche drinstehen. Es kann auch die Telefonnummer der Ex oder ein Rezept für Gulasch sein. Meist ist es aber ein Programm in Maschinencode und die dazugehörigen Daten. Und da das Flash meistens nicht ganz voll ist, kann der Rest leer (Zustand den der Flash nach dem Löschen hat) oder die Überbleibsel eines anderen Programms sein. Die Unterscheidung, was von dem Flash-Inhalt Maschinencode ist und was Daten sind, ist im Allgemeinen nicht trivial. Man kann ausgehend von architekturabhängigen Fixpunkten (z.B. Reset-Vektor, Interrupt-Vektoren) dem Maschinencode folgen. Das nennt man Reverse-Engineering. > Und ich kenn das dann nur so, dass ich es dann automatisch in ASM > "übersetzt" bekomme mit einem Disasemblierprogramm. Es spricht nichts dagegen, den Maschinencode in eine höhere Sprache wie C oder BASIC zu übersetzen. Man kann den Startup-Code meist einem Compiler zuordnen und dann den Maschinencode entsprechend interpretieren. Das gab es früher schon (ich erinnere mich an einen BASIC Decompiler für den C64) aber auch heute noch: z.B. Java (Bytecode) Decompiler. Allerdings ist das viel aufwändiger, als den Maschinencode direkt in Assembler-Mnemonics zu übersetzen. Das geht nämlich 1:1, von Ausnahmen abgesehen. So werden bei AVR bspw. CLR Rx und EOR Rx,Rx zum gleichen Maschinencode übersetzt. Der Disassembler hat dann die Wahl. Dazu gab sogar mal einen Thread: Beitrag "AVR: Werden gleiche Opcodes unterschieden?"
:
Bearbeitet durch User
Wilfried schrieb: > Ich möchte eine funktionierende Uhr "Stunden+Minuten" > erweitern so dass sie auch Sekunden anzeigt. Ich habe das mal mit in deinem Code gändert. Das sieht jetzt gut aus: - https://onlinegdb.com/Pn9fPJmQY Lothar M. schrieb: > Zum grundlegenden Problem wurde schon etwas gesagt: in einen int16_t > passen nur Zahlen von 0 bis 65536. Das kann nicht funktionieren, wenn du > damit dann 24 x 3600 = 86400 Sekunden pro Tag darin unterbringen willst. > Oder viel schlimmer noch, Zahlen bis zu 235959 Der kleinstmögliche Ansatz ist es, wenn nur die Übergabe zum number_output() korrigiert wird. Ich habe aber auch noch die Uhr selber ein wenig geradegezogen und den Sekundenzähler aus dem Timerinterrupt rausgenommen.
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Ich habe aber auch noch die Uhr selber > ein wenig geradegezogen und den Sekundenzähler aus dem Timerinterrupt > rausgenommen. Da hätte man ihm auch das bahnbrechende Konzept der Arrays vermitteln können. Digit_X00000 . . . . naja Und man sollte ein Update nach einer Änderung machen, nicht dauernd. Wird zwar nicht das Weltklima retten, aber trotzdem . . . Und das mit den Klammer und Einrückung über wir auch nochmal . . Und das mit dem Timer und programierbarer Periodendauer . . . und, und, und
:
Bearbeitet durch User
Falk B. schrieb: > Da hätte man ihm auch das bahnbrechende Konzept der Arrays vermitteln > können. Falk, sei dir sicher: mir ist das vollkommen klar, dass da jede Menge Verbesserungspotential ist. > das mit den Klammer und Einrückung über wir auch nochmal . . Obfuscation. > Und man sollte ein Update nach einer Änderung machen, nicht dauernd. Es macht in der Tat kaum einen Unterschied, ob der µC nun mit Vollgas das Angezeigte ständig wiederholt oder ob er mit Vollgas auf die nächste Änderung wartet. > Wird zwar nicht das Weltklima retten, aber trotzdem . . . Wenn ich Strom sparen will, nehme ich aber auch gleich gar keine LEDs zur Anzeige. Das kommt dann aber erst bei > und, und, und
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Obfuscation. Ja, das ist wirklich hässlich. Der Betty-Typ hatte auch so einen Stil.
Beitrag #7694639 wurde vom Autor gelöscht.
Lothar M. schrieb: > Sollte das nicht eher main_fb.c heißen? Keine Ahnung, über den Namen hab ich nicht nachgedacht. Ach so, jetzt verstehe ich, die Initialen.
Hi Danke für die zahlreichen Antworte. Bin bis jetzt nicht dazugekommen mir alles anzuschauen. Werde es zeitnah tun. Im Anhang habe ich die original Dateien sowie die von mir angepassten Dateien angehängt. Gruß Wilfried.
Wastl schrieb: > Noch ein neuer Uhren-Quäl-Code-Thread. Erklärung: jetzt ist der neue Quäl-Thread gelöscht und der Inhalt zum alten hinzugefügt worden.
Wastl schrieb: > zum alten hinzugefügt worden. Ja, der neue Thread war ganz offensichtlich eine Fehlbedienung. Wilfried schrieb: > Angehängte Dateien: > Dokument.txtLETZTERSTAND Eine Datei mit der Endung "*.txtLETZTERSTAND" kann keiner sinnvoll öffnen! Und gleich gar nicht direkt online hier im Forum. Wie ich schonmal gesagt habe: nenne deine C-Dateien einfach *.c wie der ganze Rest der Welt. Und dann siehst du z.B. an LED_clock_III.c und LED_display_no_interrupt.h was die Forensoftware auf magische Weise daraus macht: es gibt Syntaxhighlighting für umme! > LED_display_no_interrupt.h In eine Headerdatei kommt kein C-Code, sondern nur Definitionen und bestenfalls Deklarationen.
:
Bearbeitet durch Moderator
Lothar M. schrieb: > In eine Headerdatei kommt kein C-Code, sondern nur Definitionen und > bestenfalls Deklarationen. Definitionen? Bei Funktionen nur, wenn "inline". (Üblicherweise wird "Definition" für den Code einer Funktion verwendet, und "Deklaration" für deren Prototyp. Ein #define ist keine Definition, sondern ein Macro) Von dem, was da in "LED_display_no_interrupt.h" steht, gehört exakt gar nichts dort rein, denn alles sind Definitionen (d.h. Dinge, die beim Compilieren Code und Linkersymbole erzeugen) und keine Deklarationen (Prototypen bzw. extern-Deklarationen für Variablen & Konstanten).
:
Bearbeitet durch User
Harald K. schrieb: > gehört exakt gar nichts dort rein Ja, der Uhren-Quäl-Code macht seinem Namen alle Ehre. Auch die Be-Namung der Dateien folgt treu diesem Motto.
(Jetzt fehlt eigentlich nur ein zorniges #aufstampf: "Aber es funktioniert doch, kann also gar kein Fehler sein, was die alten Säche da herumgreinen, haben alle keine Ahnung ...")
Wilfried schrieb: > Dokument.txtLETZTERSTAND Sobald Du irgendeine Änderung an der Datei durchführst, ist die im Forum hochgeladene Dateiversion nicht mehr der letzte Stand, sondern völlig veraltet. Derart grottenschlechte Dateinamenkonventionen lassen schon gewaltige Rückschlüsse auf die Sorgfalt bei der Entwicklung zu. So etwas muss ich mir gar nicht erst anschauen.
Andreas S. schrieb: > Derart grottenschlechte Dateinamenkonventionen lassen schon > gewaltige Rückschlüsse .... ... auf die Fähigkeiten und den Gemütszustand des Verfassers zu.
Wilfried schrieb: > Hi Falk > Danke-super! Was willst du uns damit sagen? Funktioniert es wie gewünscht?
Wilfried schrieb: > Ja es funktioniert einwandfrei. Wichtiger noch: hast du verstanden, warum das jetzt funktioniert?
Lothar M. schrieb: > Wichtiger noch: hast du verstanden, warum das jetzt funktioniert? .... Uhren-Quäl-Thread ....
Hi Wastl du wiederholst dich-oder besser du stiehlst mir meine Lebenszeit. Auf diese Kommentare ist niemand gespannt.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.