Difference between revisions of "AVR Embedded Tutorial - Timer, Counter/de"
m (Fixed template loop; modded categories to German; added language category) |
|||
(9 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
− | {{ | + | {{LanguageBar}} |
+ | |||
=Timer / Counter= | =Timer / Counter= | ||
==Titel== | ==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: | ||
+ | |||
+ | * https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR | ||
+ | |||
+ | ==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=== | |
− | |||
<syntaxhighlight lang="pascal"> | <syntaxhighlight lang="pascal"> | ||
program Project1; | program Project1; | ||
+ | </syntaxhighlight> | ||
− | + | ====Timer 0 Interrupt==== | |
+ | |||
+ | <syntaxhighlight lang="pascal"> | ||
+ | procedure Timer0_Interrupt; public Name 'TIMER0_COMPA_ISR'; interrupt; | ||
const | const | ||
t = 10; // LED sollte nur bei jedem 10. Durchlauf umschalten. | t = 10; // LED sollte nur bei jedem 10. Durchlauf umschalten. | ||
Line 30: | Line 40: | ||
end; | end; | ||
end; | end; | ||
+ | </syntaxhighlight> | ||
− | + | ====Timer 1 Interrupt==== | |
+ | |||
+ | <syntaxhighlight lang="pascal"> | ||
+ | procedure Timer1_Interrupt; public Name 'TIMER1_COMPA_ISR'; interrupt; | ||
const | const | ||
t = 500; // LED sollte nur bei jedem 500. Durchlauf umschalten. | t = 500; // LED sollte nur bei jedem 500. Durchlauf umschalten. | ||
Line 46: | Line 60: | ||
end; | end; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ====Timer initialisieren==== | ||
+ | <syntaxhighlight lang="pascal"> | ||
begin | begin | ||
− | // -- | + | // -- Interrupt unterbinden. |
asm cli end; | asm cli end; | ||
− | // -- | + | // -- PD0 und PD1 auf Ausgabe stellen. |
− | DDRD := % | + | DDRD := %00000011; |
// -- Timer0 initialisieren. | // -- Timer0 initialisieren. | ||
Line 70: | Line 88: | ||
repeat | repeat | ||
// Mache Irgendwas. | // Mache Irgendwas. | ||
+ | until 1 = 2; | ||
+ | end. | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==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. | ||
+ | |||
+ | <syntaxhighlight lang="pascal"> | ||
+ | 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; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ====Timer inizialisieren==== | ||
+ | |||
+ | Der springende Punkt ist der Wert bei '''TCCR0B''', dieser sagt, das der Timer extern getaktet wird. | ||
+ | |||
+ | <syntaxhighlight lang="pascal"> | ||
+ | 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; | until 1 = 2; | ||
end. | end. | ||
Line 75: | Line 154: | ||
==Stolperfalle== | ==Stolperfalle== | ||
+ | |||
Die Namen der Proceduren können abweichen, ein Beispiel: | Die Namen der Proceduren können abweichen, ein Beispiel: | ||
+ | |||
<syntaxhighlight lang="pascal"> | <syntaxhighlight lang="pascal"> | ||
// ATtiny2313 | // ATtiny2313 | ||
Line 83: | Line 164: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | = Siehe auch = | |
− | * Übersichtseite [[AVR Embedded Tutorial/de]] | + | |
+ | * Übersichtseite [[AVR Embedded Tutorial/de|AVR Embedded Tutorial]] | ||
+ | |||
+ | Autor: [[User:Mathias|Mathias]] | ||
− | [[Category: | + | [[Category:AVR/de]] |
− | [[Category: | + | [[Category:Arduino/de]] |
− | [[Category: | + | [[Category:Embedded/de]] |
+ | [[Category:Tutorials/de]] | ||
+ | {{AutoCategory}} |
Latest revision as of 01:35, 24 January 2020
│ 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