Bascom und Timer
aus RN-Wissen, der freien Wissensdatenbank
Inhaltsverzeichnis |
Bascom Timer (Mega8 und andere)
Zweck
Timer sind selbstÀndige ZÀhler im Prozessor. Sie werden dort gebraucht, wo zeitkritische und genaue Aufgaben gefordert sind.
Struktur:
Config TimerXXX = Timer, Prescale= XX âKonfiguriere TimerXXX Enable TimerXXX âschalte den Overflow-Interrupt zu TimerXXX ein On TimerXXX SprungXXX âverzweige bei TimerXXX ĂŒberlauf zu SprungXXX Enable Interrupts âgenerell Interrupts zulassen Do ....Hauptprogramm âHauptprogramm Loop End SprungXXX: âUnterprogramm von TimerXXX ....AusfĂŒhrung âarbeitet hier etwas ab und springt mit Return Return âwieder zurĂŒck zum Hauptprogramm
Zuerst muss man den zu verwendeten Timer mit âConfigâ, konfigurieren.
Dazu definiert man ihn als Timer (man könnte auch einen Counter daraus machen).
Dazu muss man noch den Prescaler definieren. Der Prescaler ist der Teiler, der die Quarzfrequenz fĂŒr den Timer reduziert .
(Sonst wĂŒrde der Timer immer mit der vollen Frequenz vom Quarz zĂ€hlen und das wĂŒrde meistens zu schnell sein.)
Dann mit âEnableâ den gewĂŒnschten Interrupt des Timers einschalten. Der Timer selbst lĂ€uft auch schon so, mit dem definieren des Taktes. Mit âOnâ das Unterprogramm (ISR) definieren, an die der Timer springen soll, wenn dieser ĂŒberlĂ€uft(ISR= Interrupt Service Routine). Dann das generelle Einschalten von Interrupts.
Jeder ZĂ€hler hat eine bestimmte, maximale ZĂ€hlweite. ZĂ€hlt er ĂŒber diese, fĂ€ngt er wieder bei Null an zu zĂ€hlen (Ăberlauf). Wie weit ein ZĂ€hler zĂ€hlen kann, ergibt sich aus seiner Struktur. Es gibt da 8-Bit Timer (Timer0 und Timer2, beim Mega8)und 16-Bit Timer (Timer1 beim Mega8). 8-Bit Timer zĂ€hlen von 0 bis 255, 16-Bit Timer von 0 bis 65535.
Bei vielen Timern ist es möglich einzustellen bis zu welchen Wert der Timer zĂ€hlt. Mit âCONFIG .... COMPARE A = CLEARâ im Vergleichsregister A die Grenze eingestellt werden.
Bei einem Interrupt (z.B. Ăberlauf), unterbricht der Timer das Hauptprogramm und springt in die ISR. Die ISR wird abgearbeitet und mit Return wird wieder an die Stelle zurĂŒckgesprungen, wo vorher das Hauptprogramm unterbrochen wurde.
Man soll darauf achten, dass in der ISR immer nur kurze Anweisungen (d.h. insbesondere kein WAIT oder PRINT) abgearbeitet werden und der Hauptteil dann im Hauptprogramm bearbeitet wird. Sonst kann es sein, dass man den Prozessor damit blockiert.
Timer Beispiel:
Config Timer0 = Timer, Prescale= 8 âKonfiguriere Timer0 Enable Timer0 âschalte den Timer0 Overflow-interrupt ein On Timer0 Isr_von_Timer0 âverzweige bei Timer0 ĂŒberlauf zu Isr_von_Timer0 Enable Interrupts Do ....Hauptprogramm Loop End Isr_von_Timer0: âISR von Timer0 .....Programm-Code Return
Timer0 ist nun so eingestellt, dass die Frequenz vom Quarz, durch den Prescaler, durch 8 geteilt wird.
(Beim Prescaler kann man Teilungen von 1 , 8 , 64, 256, oder 1024 einstellen).
Diese Frequenz kommt nun zum Timer0 und der zÀhlt nun mit dieser Frequenz bis 255.
Ab 255 lĂ€uft der Timer ĂŒber, fĂ€ngt wieder bei Null an zu zĂ€hlen, und verzweigt dabei in die ISR.
Mit Return springt die ISR dann wieder zum Hauptprogramm zurĂŒck.
In der ISR könnte man z.B. eine Variable hochzĂ€hlen. Diese wĂŒrde dann bei einem 8Mhz Quarz, ca. 3906mal in der Sekunde um 1 hochgezĂ€hlt. ( (8000000Hz/8) /256=3906.26Hz)
Timer im 1 Sekunden Takt
Wenn man jetzt z.B. will, dass eine Variable nur alle Sekunden um 1 hochgezĂ€hlt wird, muss man den Prescaler anpassen und auch noch die ZĂ€hlweite vom Timer anpassen. Die ZĂ€hlweite vom Timer kann man nur insofern verĂ€ndern, dass man ihn nicht von Null weg zĂ€hlen lĂ€sst, sondern von einem höheren Wert.(der Ăberlauf ist immer der maximale Wert vom Timer)
Da der Timer0 aber mit 8-Bit jetzt zu kurz zÀhlt (0-255) und wir mit einem grossen Prescaler auch nicht auf 1 Sekunde kommen, nehmen wir dazu den Timer1.
Der Timer1 ist ein 16-Bit Timer und kann von 0-65535 zÀhlen.
Wenn ich jetzt einen Prescaler von 256 verwende, bekomme ich bei einem 8Mhz Quarz, eine Taktrate von 31250Hz. Das heiĂt, dass der ZĂ€hler in einer Sekunde von 0 bis 31250 zĂ€hlt. Wenn ich jetzt will, dass der Timer nach 31250 ZĂ€hlungen ĂŒberlĂ€uft (weil nur beim Ăberlaufen springt er in die ISR und zĂ€hlt somit meine Variable um 1 hoch), darf ich den Timer nicht von Null wegzĂ€hlen lassen sondern von einem höheren Wert.
Dazu muss ich die maximale mögliche ZĂ€hlweite (16-Bit = 65535) von meiner gewĂŒnschten ZĂ€hlweite, abziehen. Also 65535-31250 = 34285 .Der Timer muss also schon bei 34285 zu zĂ€hlen anfangen und macht dann nach 1 Sekunde einen Ăberlauf. 34285+31250= 65535 = Ăberlauf
Hier ein Beispiel mit dem Timer 1. Zur Kontrolle wird eine Led im Sekundentakt aus und ein geschalten. Man kann in der ISR auch eine Variable hochzÀhlen lassen.
$regfile = "m8def.dat" 'fĂŒr Mega8
$crystal = 8000000 'fĂŒr 8MHz Quarz
Config Portd = Output 'definiert Portd als Output
Config Timer1 = Timer , Prescale = 256 'Konfiguriere Timer1
Enable Timer1 'schalte den Timer1 ein
On Timer1 Isr_von_timer1 'verzweige bei Timer1 ĂŒberlauf zu Isr_von_Timer1
Enable Interrupts
Timer1 = 34285 'Timer1 soll schon von 34285 wegzÀhlen
Do
'....Hauptprogramm
Loop
End
Isr_von_timer1: 'ISR von Timer1
Timer1 = 34285 'Timer1 soll wieder von 34285 wegzÀhlen
Toggle Portd.0 'schaltet Portd.0 im Sekundentakt
'EIN und AUS
'....oder z.B. incr Variable
Return
Die Vorgabe (Timer1=34285) soll man vor dem Hauptprogramm reinsetzen und bei der ISR. Wenn man die Vorgabe nicht bei der ISR reinsetzen wĂŒrde (ISR = Ăberlauf), wĂŒrde er ja wieder bei 0 statt bei 34285 anfangen zu zĂ€hlen.
Um sich das Rechnen zu ersparen könnte man statt der Anweisung: Timer1 = 34286 , auch den Befehl "Load" verwenden.
Man gibt dann ein: Load Timer1 , 31250
Mit Load rechnet sich der Compiler selber die Werte aus ( 65536-31250 ).Man gibt einfach nach dem Komma, die beabsichtigte ZĂ€hlweite ein.
Damit hat man nun einen Timer der alle Sekunden eine Variable hochzÀhlt.
Das nachladen des Startwertes gibt nur bei einem groĂen Prescaler (64 oder gröĂer), und wenn keine anderen Interrupts aktiv sind genaue Zeitwerte. Beim Prescaler 64 mĂŒsste man eventuell noch die Zeiten fĂŒr Sprung in die ISR u.s.w. mit einberechen. Aber fĂŒr die meisten Anwendungen reicht diese Genauigkeit vollkommen aus ! :-) Besser macht man das ohnehin mit einem Vergleichsregister in Hardware.

