Aus RN-Wissen.de
Wechseln zu: Navigation, Suche
Balkonkraftwerk Speicher und Wechselrichter Tests und Tutorials

(Siehe auch)
K (Timer im 1 Sekunden Takt)
 
(19 dazwischenliegende Versionen von 8 Benutzern werden nicht angezeigt)
Zeile 3: Zeile 3:
  
 
=== Zweck ===
 
=== Zweck ===
Timer sind selbständige Zähler im Prozessor. Man braucht sie dort, wo zeitkritische und genaue Aufgaben gefordert sind.
+
[[Timer]] sind selbständige Zähler im Prozessor. Sie werden dort gebraucht, wo zeitkritische und genaue Aufgaben gefordert sind.
  
 
=== Struktur: ===
 
=== Struktur: ===
Zeile 9: Zeile 9:
 
<pre>
 
<pre>
 
  Config TimerXXX = Timer, Prescale= XX    ‘Konfiguriere TimerXXX
 
  Config TimerXXX = Timer, Prescale= XX    ‘Konfiguriere TimerXXX
  Enable TimerXXX           ‘schalte den TimerXXX ein
+
  Enable TimerXXX           ‘schalte den Overflow-Interrupt zu TimerXXX ein
 
  On  TimerXXX  SprungXXX           ‘verzweige bei TimerXXX überlauf zu SprungXXX
 
  On  TimerXXX  SprungXXX           ‘verzweige bei TimerXXX überlauf zu SprungXXX
 
  Enable Interrupts           ‘generell Interrupts zulassen
 
  Enable Interrupts           ‘generell Interrupts zulassen
Zeile 20: Zeile 20:
 
  SprungXXX: ‘Unterprogramm von TimerXXX
 
  SprungXXX: ‘Unterprogramm von TimerXXX
 
  ....Ausführung ‘arbeitet hier etwas ab und springt mit Return  
 
  ....Ausführung ‘arbeitet hier etwas ab und springt mit Return  
  Return ‚ wieder zurück, zum Hauptprogramm
+
  Return ‘wieder zurück zum Hauptprogramm
 
</pre>
 
</pre>
  
  
 
Zuerst muss man den zu verwendeten Timer mit „Config“, konfigurieren.  
 
Zuerst muss man den zu verwendeten Timer mit „Config“, konfigurieren.  
Dazu definiert man ihn als Timer (mann könnte auch einen Counter daraus machen).
+
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 Quarzfequenz für den Timer reduziert .
+
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.)
+
(Sonst würde der Timer immer mit der vollen Frequenz vom Quarz zählen und das wäre meistens zu schnell.)
 
   
 
   
Dann mit „Enable“ den bestimmten Timer einschalten.  
+
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,   
 
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.
 
wenn dieser überläuft(ISR= Interrupt Service Routine). Dann das generelle Einschalten von Interrupts.
Zeile 35: Zeile 35:
 
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).
 
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).
 
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 bis 256, 16-Bit Timer bis 65536.
+
8-Bit Timer zählen von 0 bis 255, 16-Bit Timer von 0 bis 65535.
  
Bei einem Überlauf, unterbricht der Timer das Hauptprogramm und springt in die ISR. Die ISR wird abgearbeitet und mit Return wird wieder an  
+
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.  
 
die Stelle zurückgesprungen, wo vorher das Hauptprogramm unterbrochen wurde.  
  
Man soll darauf achten, dass in der ISR immer nur kurze Anweisungen abgearbeitet  
+
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.  
 
werden und der Hauptteil dann im Hauptprogramm bearbeitet wird.  
 
Sonst kann es sein, dass man den Prozessor damit blockiert.
 
Sonst kann es sein, dass man den Prozessor damit blockiert.
Zeile 47: Zeile 49:
 
<pre>
 
<pre>
 
  Config Timer0 = Timer, Prescale= 8    ‘Konfiguriere Timer0
 
  Config Timer0 = Timer, Prescale= 8    ‘Konfiguriere Timer0
  Enable Timer0                    ‘schalte den Timer0 ein
+
  Enable Timer0                    ‘schalte den Timer0 Overflow-interrupt ein
 
  On  Timer0  Isr_von_Timer0         ‘verzweige bei Timer0 überlauf zu Isr_von_Timer0
 
  On  Timer0  Isr_von_Timer0         ‘verzweige bei Timer0 überlauf zu Isr_von_Timer0
 
  Enable Interrupts    
 
  Enable Interrupts    
Zeile 62: Zeile 64:
  
 
Timer0 ist nun so eingestellt, dass die Frequenz vom Quarz, durch den Prescaler,  durch 8 geteilt wird.<br>
 
Timer0 ist nun so eingestellt, dass die Frequenz vom Quarz, durch den Prescaler,  durch 8 geteilt wird.<br>
(Beim Prescaler kann man Teilungen von 1 , 8 , 64, 256, oder 1024 einstellen).<br> Diese Frequenz kommt nun zum Timer0 und der zählt nun mit dieser Frequenz bis 256.
+
(Beim Prescaler kann man Teilungen von 1 , 8 , 64, 256, oder 1024 einstellen).<br> Diese Frequenz kommt nun zum Timer0 und der zählt nun mit dieser Frequenz bis 255.
Ab 256 läuft der Timer über, fängt wieder bei Null an zu zählen, und verzweigt dabei in die ISR.
+
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.
 
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)
 
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 ===
 
=== 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.
 
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 insovern 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)
+
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-256) und wir mit einem grossen Prescaler auch nicht auf 1 Sekunde kommen, nehmen wir dazu den Timer1.
+
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-65536 zählen.
+
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 heist, 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.
+
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 er nur beim Überlaufen in die ISR springt und meine Variable somit um 1 hochzählt), 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 = 65536) von meiner gewünschten Zählweite, abziehen. Also 65536-31250 = 34286 .Der Timer muss also schon bei 34286 zu zählen anfangen und macht dann nach 1 Sekunde einen Überlauf. 34286+31250= 65536 = Überlauf
+
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.
 +
<pre>
 +
$regfile = "m8def.dat"                    'für Mega8
 +
$crystal = 8000000                        'für 8MHz Quarz
 +
 +
Config Portd = Output                    'definiert Portd als Output
  
Das obige Beispiel wird nur um die Vorgabe für den Timer ergänzt.
+
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
  
<pre>
+
Do
  Config Timer0 = Timer, Prescale= 256  ‘Konfiguriere Timer0
+
  '....Hauptprogramm
Enable Timer0                    ‘schalte den Timer0 ein
+
Loop
On  Timer0  Isr_von_Timer0         ‘verzweige bei Timer0 überlauf zu Isr_von_Timer0
+
End
Enable Interrupts
+
 
Timer1 = 34286                        'Timer1 soll schon von 34286 wegzählen
+
Isr_von_timer1:                           'ISR von Timer1
+
Timer1 = 34285                            'Timer1 soll wieder von 34285 wegzählen
Do
+
Toggle Portd.0                            'schaltet Portd.0 im Sekundentakt
....Hauptprogramm
+
                                          'EIN und AUS
Loop
+
'....oder z.B. incr Variable  
End
+
 
+
Return
Isr_von_Timer0: ‘ISR von Timer0
+
Timer1 = 34286                        'Timer1 soll wieder von 34286 wegzählen
+
.....Programm-Code                    'z.B. erhöhe Variable um 1
+
Return
+
 
</pre>
 
</pre>
  
Die Vorgabe (Timer1=34286) soll man vor dem Hauptprogramm reinsetzen und bei der ISR.
+
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 34286 anfangen zu zählen.
+
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.  
 
Um sich das Rechnen zu ersparen könnte man statt der Anweisung: Timer1 = 34286 , auch den Befehl "Load" verwenden.  
Zeile 114: Zeile 122:
 
Damit hat man nun einen Timer der alle Sekunden eine Variable hochzählt.
 
Damit hat man nun einen Timer der alle Sekunden eine Variable hochzählt.
  
Um das Zählen der Sekunden noch genauer zu machen, müsste man 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 !  :-)
+
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.
  
 
==Autor==
 
==Autor==
Zeile 121: Zeile 130:
 
==Siehe auch==
 
==Siehe auch==
 
* [[Avr]]
 
* [[Avr]]
 +
* [[Timer]]
 
* [[Bascom]]
 
* [[Bascom]]
 
* [[Interrupt]]
 
* [[Interrupt]]
 +
 +
==Weblinks==
 +
* [http://www.roboternetz.de/phpBB2/dload.php?action=file&file_id=169 AvrTimer Windows Berechnungstool / Bascom Codegenerator]
  
 
[[Kategorie:Robotikeinstieg]]
 
[[Kategorie:Robotikeinstieg]]
 
[[Kategorie:Microcontroller]]
 
[[Kategorie:Microcontroller]]
 
[[Kategorie:Software]]
 
[[Kategorie:Software]]
 +
[[Kategorie:Praxis]]
 
[[Kategorie:Quellcode Bascom]]
 
[[Kategorie:Quellcode Bascom]]

Aktuelle Version vom 23. Dezember 2013, 15:30 Uhr

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äre meistens zu schnell.)

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 er nur beim Überlaufen in die ISR springt und meine Variable somit um 1 hochzählt), 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.

Autor

Siehe auch

Weblinks


LiFePO4 Speicher Test