Schaltung
Das Display ist mit 7 Leitungen am Port
B angeschlossen.
Ein Schalter ist zwischen RB1 und Masse angeschlossen. Die Schaltung entspricht der LCD-Tastatur-Platine , verbunden mit der 16F84-Testplatine oder der 16F84-Miniplatine . |
Besonderheiten
Dieses Lernbeispiel entstand eigentlich als Kalibrierhilfe für
den 50-MHz-Frequenzzähler.
Es
eignet sich aber auch als Lernbeispiel. Ich bin aber einige
Kompromisse
eingegangen:
Das große Problem
Um mit einem 16F84 aus dem PIC-Takt einen langsamen Uhrentakt zu
erzeugen
steht nur der Timer0 zur Verfügung. Dieser arbeitet dabei als
256:1-Frequenzteiler.
Ein kleineres Teilerverhältnis ist nicht möglich, da
dafür
nach jedem Überlaufen des Timers0 das Register TRM0 mit einem
Voreinstellwert
beschrieben werden müsste. Dabei wird aber automatisch der
Vorteiler
auf 0 zurückgesetzt, und dem Timer0 für 2 Takte das
Zählen
verboten. Als Folge gängen einige Takte beim Zählen verloren.
Das ist für eine präzise Uhr unzulässig.
Lösung Nr. 1
Der PIC-Takt beträgt 10 MHz. der Zyklustakt
beträgt folglich 2,5 MHz.
Wenn der Timer0 ohne Vorteiler arbeitet, liefert er 9765,625 Interrupts
pro Sekunde. Der Ausgangstakt des Timer0 ist also KEIN Vielfaches von 1
Hz. Folglich lässt sich eine 1-Hz-Takt daraus nicht durch
einfaches
Teilen erzeugen.
Die einzige Lösung besteht darin, dass man immer abwechselnd 7
Sekunden der Länge 9766 Interrupts und 1 Sekunde der Länge
9763
Interrupts abzählt. Die 8 Sekunden sind dann zusammen genau
78125 Interrupts lang, und das entspricht dem richtigen Wert (8 x
9765,625
= 78125 = (7 x 9766) + 9763 ).
In einer solchen Uhr sind zwar alle Sekunden zu lang (1,0000384
s)
oder zu kurz (0,99973 s), der Gangfehler ist aber nie größer
als 0,3 ms. Das merkt keiner.
Lösung Nr.2
Wenn man den Timer0 ohne Vorteiler benutzt, dann kann man TMR0
beschreiben,
ohne das man sich um einen zurückgesetzten
Vorteiler Gedanken
machen
muss. Der einzige Mess(Zähl-)fehler besteht dann
darin,
dass nach dem Beschreiben von TMR0 der Timer0 zwei Zyklen lang nicht
zählt.
Das kann man aber schon dadurch kompensieren, dass man in TMR0 einen
Wert
einschreibt, der um 2 größer ist, als nötig.
Nun lässt sich der Timer0 also z.B. als 250:1-Teiler
benutzen.
Es kommen aber weitere Probleme hinzu. Wenn man den Timer0 ohne
Vorteiler
betreibt, schafft man es nicht, den TMR0 mit einem neuen Wert zu
beschreiben,
während der noch nach dem Überlauf auf 0 steht. Man muss
also die Zahl, die man in den TMR0 hineinschreibt, auch noch um die
Zahl
der Zyklen verringern, die vom Timer0-Überlauf bis zum Beschreiben
des TMR0 vergehen. Das ist ziemlich heikel.
Programmablauf
Programmlisting