AVR Embedded Tutorial - Timer, Counter/de
Timer / Counter
Titel
Dieses Beispiel zeigt, wie man die beiden Timer eines ATtiny2313 verwenden kann.
Jeder Timer steuert eine LED an, welche an Bit 0 und 1 des PortD sind. Dabei sollte die LED an Pin0 etwas schneller blinken.
Hier geht es nicht darum, alle Register zu verstehen. Dies sollte nur ein praktisches Beispiel sein, wie man es in FPC umsetzt.
Genauere Details gibt es hier: https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR
Beispiel-Code
program Project1;
procedure Timer0_Interrupt; public Name 'TIMER0_COMPA_ISR'; interrupt;
const
t = 10; // LED sollte nur bei jedem 10. Durchlauf umschalten.
z: integer = 0; // Zähler für Leerdurchläufe.
begin
TCNT0 := 128; // Speed halbieren 0 = langsam (default)
Inc(z);
if (z = t) then begin
PORTD := PORTD or (1 shl 0); // LED Pin0 ein
end;
if (z = t shl 1) then begin
PORTD := PORTD and not (1 shl 0); // LED Pin0 aus
z := 0;
end;
end;
procedure Timer1_Interrupt; public Name 'TIMER1_COMPA_ISR'; interrupt;
const
t = 500; // LED sollte nur bei jedem 500. Durchlauf umschalten.
z: integer = 0; // Zähler für Leerdurchläufe.
begin
Inc(z);
if (z = t) then begin
PORTD := PORTD or (1 shl 1); // LED Pin1 ein
end;
if (z = t shl 1) then begin
PORTD := PORTD and not (1 shl 1); // LED Pin1 aus
z := 0;
end;
end;
begin
// -- Interupt unterbinden.
asm cli end;
// -- Bit 0 und 1 von PORTD auf Ausgabe stellen.
DDRD := %00000001;
// -- Timer0 initialisieren.
TCCR0A := 0;
TCCR0B := %101; // CPU-Takt / 1024
TIMSK := TIMSK or (1 shl OCIE0A); // Timer0 soll Interrupt auslösen.
// -- Timer1 initialisieren.
TCCR1A := 1; // CTC-Modus
TCCR1B := %010; // CPU-Takt / 8
TIMSK := TIMSK or (1 shl OCIE1A); // Timer1 soll Interrupt auslösen.
// -- Interrupt aktivieren.
asm sei end;
// -- Hauptschleife
repeat
// Mache Irgendwas.
until 1 = 2;
end.
Timer extern getaktet
Einen Timer kann man auch extern getaktet werden. Folgendes Beispiel demonstriert dies mit einem Atmega328. Zum extern takten gibt es folgende Pins am AVR:
- T0 taktet Timer 0
- T1 taktet Timer 1
Der Timer 2 kann nicht extern getaktet werden.
Beispiel einer Uhr
Für eine exakte Uhr ist ein Quarz/Oszilator mit 4.194304MHz geeignet. Dieser lässt sich gut in einer 2er Potenz teilen, so das man auf einen Sekunden-Takt kommt. Hier wird der Timer 0 extern getaktet, dazu muss man den Oszilator an T0 (PD4) anschliessen.
Timer Interrupt
Jeder 16384 Aufruf des Interupts ist eine Sekunde.
procedure Timer0_Interrupt; public Name 'TIMER0_OVF_ISR'; interrupt;
const
cl = 16384 div 2; // 4194304 / 256 / 2;
zaehler: UInt16 = 0; // Zählt bis cl erreicht ist.
begin
Inc(zaehler);
// Nach einer halben Sekunde LED ausschalten.
if zaehler = cl then begin
PORTB := PORTB and not (1 shl 5);
end;
// Sekunde ist erreicht.
if zaehler >= cl * 2 then begin
PORTB := PORTB or (1 shl 5);
zaehler := 0; // Zähler zurücksetzen.
end;
end;
Timer inizialisieren
Der springende Punkt ist der Wert bei TCCR0B, dieser sagt, das der Timer extern getaktet wird.
begin
DDRB := DDRB or (1 shl 5); // Pin PD5 auf Ausgabe
TCCR0A := %00; // Normaler Timer
TCCR0B := %111; // Clock / Externer Pin TO, steigende Flanke.
TIMSK0 := (1 shl TOIE0); // Timer 0 Interrupt aktivieren.
asm sei end; // Interrupts einschalten.
repeat
// Hier kann die Zeit auf ein Display ausgegeben werden.
until 1 = 2;
end.
Stolperfalle
Die Namen der Proceduren können abweichen, ein Beispiel:
// ATtiny2313
procedure Timer0_Interrupt; public Name 'TIMER0_COMPA_ISR'; interrupt;
// ATtiny44
procedure Timer0_Interrupt; public Name 'TIM0_COMPA_ISR'; interrupt;
Siehe auch
- Übersichtseite AVR Embedded Tutorial/de