AVR Embedded Tutorial - Timer, Counter/de
│ Deutsch (de) │ English (en) │
Timer / Counter
Titel
Hier geht es nicht darum, alle Register zu verstehen. Dies sollte nur ein praktisches Beispiel sein, wie man es in FPC/Lazarus umsetzt.
Genauere Details gibt es hier:
Beispiel, LEDs über Timer steuern
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 PD0 etwas schneller blinken.
Beispiel Code
program Project1;
Timer 0 Interrupt
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;
Timer 1 Interrupt
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;
Timer initialisieren
begin
// -- Interrupt unterbinden.
asm cli end;
// -- PD0 und PD1 auf Ausgabe stellen.
DDRD := %00000011;
// -- 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 shr 1; // 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 shl 1 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 := 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
Autor: Mathias