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
Ich habe mal den Mist mit den 250 Wiederholungen der 4ms rausgenommen. Dasselbe Ergebnis. Die 4ms Schleife wird nicht 250 mal wiederholt.
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
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.
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
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
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.