Der 8-Bit Timer/Counter Drucken E-Mail

 

Bisher wurden Zeitverzögerungen über Zeitschleifen erzeugt. Viele Anwendungen erfordern aber exakte Zeitverzögerungen bzw. Zeitspannen.
Mit Zeitschleifen ist es praktisch unmöglich exakte Zeitverzögerungen zu programmieren. Außerdem kann der Mikrocontroller bei der Abarbeitung einer Schleife keine anderen Aufgaben erfüllen.

Zur Entlastung des Mikrocontrollers und zur Erfüllung exakter Zeitbedingungen werden Timer verwendet.

Timeranwendungen:

  • Zählen von externen Impulsen
  • Erzeugen exakter Zeiten (Zeitsteuerungen, Rechteckimpulse etc.)
  • Erzeugen von Pulsweitensignalen (PWM) für die Ansteuerung von Gleichstrommotoren, LED-Dimmung usw.

Ein Timer zählt Taktimpulse des internen oder externen Oszillators und löst bei einem Überlauf einen Interrupt oder ein Flag aus.
Die interne Taktfrequenz kann mit einem Prescaler noch weiter heruntergetaktet werden.

Der Timer kann sowohl als Zeitgeber (Timer) wie auch als Ereigniszähler für externe Impulse (Counter) eingesetzt werden.

Beispiel: Der 8-Bit Timer/Counter des ATtiny 2313

 

ATtiny2313 Timer

Das Timer/Counter-Register TCNT bildet den zentralen Teil der Baugruppe.
Der ATtiny2313 verfügt über ein 8-TCNT-Register (TCNT0) welches die Taktimpulse zählt (bei 8-Bit max. von 0 bis 255 oder 0x00 bis 0xFF).
Mit jedem Takt wird der Zählerstand im Register um 1 erhöht. Ist das Register mit allen Bits gesetzt, also 1111 1111, so ist der maximale Zählwert von 255 erreicht.
Der Timer erreicht jetzt seinen Überlauf (Overflow) und setzt das Timer-Overflow-Flag (im Timer/Counter-Interrupt-Flag-Register TIFR) auf 1.

Das Flag kann abgefragt oder zum Auslösen eines Interrupts verwendet werden.
Das Timer/Counter-Register beginnt nach dem Überlauf wieder bei 0000 0000 und zählt die Takte wieder bis 255 usw.

TIMER/COUNTER-REGISTER 0 TCNT0

Timer/Counter-Register TCNT

 

Das gesetzte Flag kann gelöscht werden, indem das Bit 1 (TOV0 für Timer 0) bzw. das Bit 7 (TOV1 für Timer 1) im Timer/Counter-Interrupt-Flag-Register TIFR auf 0 setzt.

Löschen des TOV0 im Timer/Counter-Interrupt-Flag-Register TIFR in C:

TIFR |=(0<<TOV0);

 

TIMER/COUNTER-INTERRUPT-FLAG-REGISTER TIFR

Timer TIFR

 

Um einen Timer betreiben zu können, muss dieser zuvor eingestellt werden. Diese Einstellungen werden in verschiedenen Timer-Registern vorgenommen.

  1. Aktivierung der Interrupts
  2. Interrupt für Timer-Overflow aktivieren
  3. Einstellen der Zählfrequenz
  4. Einstellen des Timer-Startwertes

Beispiel:

Hier ein kleines C-Programm, welches mit einem Timer einen 1-Sekundentakt erzeugt. Mit diesem Sekundentakt sollen alle LEDs am PORTB blinken.

Die interne Taktfrequenz wurde über die Fuse-Bits mit 4MHz eingestellt. Dies ist die Basisfrequenz für den Taktgeber.
Unter Verwendung des 8-Bit-Timers soll nun 1 mal pro Sekunde ein Timerinterrupt ausgelöst werden, welcher dann das PORTB invertiert und damit die Blinksequenz erzeugt.

Da ein 8-Bit-Timer aber maximal von 0 bis 255 zählt, ergeben sich bei einer Taktfrequenz von 4MHz (4000000 / 256 =15625 Timerüberläufe pro Sekunde).
Diese Timerüberläufe könnte man einerseits mittels Zählschleife zählen und damit nach 15625 Timerüberläufen das PORTB invertieren oder man teilt den Oszillatortakt mit dem Prescaler vorerst etwas herunter.

In diesem Beispiel wird dieTaktfrequenz mit dem Prescaler vorgeteilt.

Timer

 

Hier der Code Schritt für Schritt:

#include <avr/interrupt.h>
Die Headerdatei wird benötigt, da ein Interrupt verwendet wird.

TIMSK = (1<<TOIE0);
Im Timer-Interrupt-Maskenregister TIMSK wird das 1. Bit TOIE0 (Timer0-Overflow-Interrupt-Enable) auf High gesetzt.
Damit teilen wir dem Programm mit, dass bei einem Timerüberlauf der Timer0-Overflow-Interrupt ausgelöst werden soll.

Timer TIMSK

 

TCCR0B =(1<<CS02);
Im Timer/Counter-Control-Register 0B stellen wir den Wert (Teiler) des Vorteilers (Prescaler) ein.
Hier wird das 2. Bit gesetzt und bewirkt eine Frequenzteilung von 256.


Timer TCCR0B

 

Hier eine Übersicht der Einstellungen des Prescalers. Um z.B. eine Vorteilung von 64 einzustellen, muss das 0. und das 1. Bit gesetzt werden.
CS00 und CS01 = 1            TCCR0B =(1<<CS00) && (1<<CS01);

Prescaler

In unserem Beispiel wurde der Teiler 256 gewählt und bewirkt eine Timerfrequenz von:

4000000 / 256 = Taktfrequenz von 15625 Hz.

Für den 8-Bit-Timer erhalten wir also 15625 / 256 = 61,0352 Überläufe pro Sekunde.
(Möchte man eine ganz exakte Zeitbasis haben, wird der Timer entsprechend vorgeladen. Dazu aber später.)

TCNT0 = 0x00;
Hier wird das Timer/Counter-Register auf den Anfangszustand 0000 0000 gesetzt.
Würde man hier z.B. den Timer mit dem Wert 131 (0b1000 0011 bzw. 0x83) vorladen, dann läuft der Timer nach genau 125 Taktzyklen über.
Und 125 Taktzyklen entsprechen einer Frequenz von 15625 / 125 = 125 Überläufe pro Sekunde.

while (1)
{
asm ("nop");
}

Die While-Schleife bildet eine Endlosschleife. Der Assemblerbefehl nop (No Operation) bewirkt - keine Operation - also nichts.

Passiert einer Timerüberlauf, wird der Timerinterrupt mit ISR (Timer0_OVF_vect) aufgerufen.
Die if-Abfrage zählt die Timerüberläufe und bei Überschreitung von 61 Überläufen wird in der else-Anweisung das PORTB invertiert.

Die Auflistung der Interrupt-Vektoren finden Sie im jeweiligen Datenblatt.

Vektoren

 

 

Samstag, 25. Oktober 2014


Warning: Creating default object from empty value in /home/.sites/492/site105/web/modules/mod_stats/helper.php on line 106
Seitenaufrufe : 1976586