Forum: Mikrocontroller und Digitale Elektronik TMR0 LCD UHR


von HDW (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

Ich möchte ein 1 Hz Signal mit einem PIC 16f84A erzeugen.
Das Register "sec" soll dann nach jeder Sekunde um eins erhöht werden.
Die Register werden dann nach ASCII umgerechnet und auf ein LCD 
übertragen.

Zeitbasis ist ein 4 Mhz Schwinger. Vorteiler ist auf 32 eingestellt. 
Nach 125 Überläufen des TMR0 sind 4ms vorbei. Die ganze Prozedur wird 
250 durchlaufen, dann ist eine Sekunde vorbei. Das Register "sec" wird 
dann um eins erhöht. Danach werden die Register "std", "min" und "sec" 
am LCD ausgeben.

Das ist ja alles schön und gut, aber das Register "sec" wird zu schnell 
erhöht.
Wenn ich den Vorteiler von 32 auf 256 erhöhe, flackert zwar die Anzeige 
im LCD (wg. schnellerem Ablauf), aber das Register "sec" wird genauso 
schnell wie vorher erhöht.

Der Vorteiler hat wohl irgedenwie keinen Einfluss auf das Incrementieren 
von "sec".

Quellcode ist im Anhang.


mfg   Wolfram Hildebrandt

von HDW (Gast)


Lesenswert?

Ich habe mal den Mist mit den 250 Wiederholungen der 4ms rausgenommen. 
Dasselbe Ergebnis.
Die 4ms Schleife wird nicht 250 mal wiederholt.

von Steffen (Gast)


Lesenswert?

Der Vorteiler hat schon einen Einfluss. Ich hab mal kurz über dein 
Programm geschaut. Müsste nicht nach dem decfsz loop4ms ein Sprung nach 
oben rein?

  decfsz  loop4ms

; hier fehlt der Sprung nach oben oder

  goto  Uhrschleife

  call  increase
  call  OUT
  goto  Uhrschleife

Ohne diesen wird jedesmal, wenn TMR0=0 increase ausgeführt ausser, wenn 
loop4ms=0.

Das mit der Zeitbasis wird so auch nicht 100%-ig funktionieren, da der 
Überlauf des Timers ja irgendwo in der Schleife passiert. Wenn Du den 
Timerinterupt verwendest passt das allerdings auch nicht, da der 
Einsprung in die Interuptroutine 1 oder 2 Zyklen dauern kann je nachdem 
was für ein Befehl gerade ausgeführt wird.
Aber zum Lernen ist das trotzdem ein schönes Beispiel.

MfG
Steffen

von HDW (Gast)


Lesenswert?

Ja.
Die Ungenauigkeit ist mir schon beim schreiben des Quellcodes 
aufgefallen. Mit dem Interupt muss ich ja auch dauernd das Interupt-Bit 
über pollen abfragen.

Der Fehler lag durchaus in dem vergessenen Sprung.

Jetzt habe ich dummerweise das Display am Blinken im 1 Hz Takt, weil ich 
die Register erst nach dem Increase an das LCD ausgebe.

von Steffen (Gast)


Lesenswert?

Das mit dem Interupt geht auch ohne Polling. INTCON=10100000b und dann 
die ISR ab Adresse 0x04. Dort muss dann INTCON,T0IF zurückgesetzt 
werden. Nur wie gesagt dauert der Einsprung je nachdem was gerade für 
ein Befehl ausgeführt wird unterschiedlich lange.

Am besten lässt sich eine genaue Zeibasis mit dem CCP-Modul aufbauen, 
was der 16F84 ja aber leider nicht hat.

Die einzigste Variante, die mir jetzt in den Sinn kommt ist die 
Anzeigeroutine und dir Incrementierung der Zeit so zu optimieren, dass 
egal was passiert immer die gleiche Anzahl an Takten benötigt wird. Also 
so umschreiben, dass wenn die Minuten und Stunden erhöht werden müssen 
die Routine genauso lange dauert wie wenn nicht. Beim LCD am besten 
nicht das Bussy-Flag abfragen sondern einfach die Maximalzeit abwarten.

Das ganze dann in eine MainLoop und danach eine Zeitverzögerung, so dass 
genau 1s rauskommt. Da ist die StopWatch von MPLAB sehr hilfreich. Durch 
ein paar NOPs mehr oder weniger kann man dann auch leicht die Uhr genau 
auf den verwendeten Resonator bzw. Quarz abstimmen.

Das Blinken fällt weg, wenn Du nicht das Display löschst sondern nur den 
Cursor auf Adresse 00 setzt bevor Du die Daten ausgibst.

MfG
Steffen

von Peter D. (peda)


Lesenswert?

Würde mich jetzt aber echt wundern, wenn das beim PIC ohne CCP-Modul 
nicht geht.

Beim 8051 oder AVR laufen die Timer jedenfalls weiter, auch nachdem das 
Interruptbit gesetzt wurde.

D.h. es spielt absolut keine Rolle wann genau der Interrupt behandelt 
wird. Man muß nur den Timer auslesen, dazu den entsprechenden 
Verkürzungswert addieren und wieder zurück schreiben.

Man braucht auch nicht unbedingt eine glatte Quarzfrequenz, jede 
beliebige Frequenz ist geeignet um eine hochgenaue Uhr zu realisieren.

Ich hab das hier mal am Beispiel des 8051 ausführlich  beschrieben:

http://www.specs.de/users/danni/appl/soft/clock/index.htm


Peter

von Steffen (Gast)


Lesenswert?

Nö, das klappt beim PIC nicht, da der Prescaler bei jedem 
Schreibzugriff, also auch bei einer Addition zurückgesetzt wird, was 
beim 8051 nicht der Fall ist. Ohne CCP geht das beim PIC nur durch 
Programmoptimierung, so dass ich immer genau eine Schleifenzeit von 1s 
habe. Ich wüsste jedenfalls keine elleganntere Möglichkeit, lasse mich 
aber gern eines besseren belehren.

MfG
Steffen

von Steffen (Gast)


Lesenswert?

Habe gerade mal ein Beispiel für einen Kurzzeittimer in die Codesammlung 
gesetzt.

@HDW
Das ist vom Prinzip ähnlich wie das was Du gerade programmierst.

Dort wollte ich eigentlich auch TMR0 verwenden, damit der Code auch auf 
anderen Controllern ohne CCP läuft. Aber es geht einfach nicht, da die 
Ungenauigkeiten zu groß werden.

MfG
Steffen

von HDW (Gast)


Lesenswert?

Hallo

Das Blinken habe ich dem PIC gestern schon ausgetrieben.
Dass das auch mit dem Setzten auf Home-Position im LCD geht, wusste ich 
noch nicht.

Der File aus der Codesammlung hat mir durchaus noch bei einem weiteren 
Problem geholfen.
Die Uhr und eine zugehörige Test-Weckfunktion habe ich gerade 
fertiggestellt.

Wenn ich mir mal überlege, dass ich noch vor ein paar Monaten einen 
Wecker mit drei Weckzeiten und allem Drum und Dran allein aus 
CMOS-Bausteinen gebaut habe, ist mir die Methode mit dem PIC dann doch 
sehr viel angenehmer.
Zudem sind mir die Entwicklungskosten von ca. 400EUR für den Wecker doch 
sehr auf den Magen geschlagen.

Aber die Zeiten von CMOS-Bausteinen sind durch die Mikrocontroller schon 
eh gezählt.

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
Noch kein Account? Hier anmelden.