1 | //
|
2 | // Demo Timer - JannikS
|
3 | // uC = Atmega8515
|
4 | // F_CPU = 8 MHz
|
5 | //
|
6 |
|
7 | #include <avr/io.h>
|
8 | #include <avr/interrupt.h> // Hilfsdefintionen für Interrupts
|
9 |
|
10 | int main(void)
|
11 | {
|
12 | DDRB = 0xff; // Ausgang LED
|
13 |
|
14 | /**
|
15 | Datenblatt: http://www.atmel.com/dyn/resources/prod_documents/doc2512.pdf
|
16 | Ab Seite 80: Timer0
|
17 |
|
18 | Als am einfachsten verstehbarer Modus wird der Normal Mode (Seite 85)
|
19 | von Timer0 gewählt:
|
20 |
|
21 | Ein 8-Bit Register zahlt von einem Anfangswert (Voreinstelltung 0)
|
22 | bis 0xFF hoch. Wenn 0xFF erreicht ist, führt die nächste Erhöhung um
|
23 | Eins zu einem Ergebnis von 0 (neuer Startwert zum Hochzählen) und zu
|
24 | dem gewünschten Overflow-Interrupt
|
25 |
|
26 | Wie das Register TCCR0 (Timer/Counter Control Register) zu setzen ist,
|
27 | um den Normal Mode einzustellen steht in Table 44 bei den Bits WGM01
|
28 | und WGM02
|
29 |
|
30 | Eine weitere Einstellmöglichkeit ist, wie schnell hochgezählt werden
|
31 | soll. Das kann mit der vollen Taktrate F_CPU geschehen oder indem man
|
32 | die Taktrate durch einen Vorteiler (Prescaler) teilt. Die möglichen
|
33 | Prescaler 1, 8, 64, 256, 1024 sind in Table 48 angegeben.
|
34 |
|
35 | Berechnung der Zeit bis zum Overflow bei verschiedenen Prescaler
|
36 | Einstellungen
|
37 |
|
38 | Overflow = 1/F_CPU * 256
|
39 |
|
40 | Prescaler Overflow
|
41 | 1 32 us
|
42 | 8 256 us
|
43 | 64 2048 us
|
44 | 256 8192 us
|
45 | 1024 32768 us = 32,768 ms
|
46 |
|
47 | 1s sind aber 1000 ms bzw. 1000000 us...
|
48 | d.h. man braucht mehrere Overflow Interrupts in denen die nur Anzahl
|
49 | der Interrupts gezählt wird und erst wenn die Anzahl mal die Dauer
|
50 | die gewünschte Sekunde ergibt, wird die LED umgeschaltet.
|
51 |
|
52 | Wieviele Overflows braucht man für eine Sekunde bei verschiedenen
|
53 | Prescaler Werten?
|
54 |
|
55 | Anzahl_Overflows = 1s / Zeit_für_einen_Overflow
|
56 |
|
57 | Prescaler Overflow Anzahl_Overflows
|
58 | 1 32 us 31250
|
59 | 8 256 us 3906,25
|
60 | 64 2048 us 488,28125
|
61 | 256 8192 us 122,0703125
|
62 | 1024 32768 us 30,517578125
|
63 |
|
64 | Bzw. die Gesamtrechnung ist:
|
65 |
|
66 | Anzahl_Overflows = 1 * F_CPU / 256
|
67 |
|
68 | Hier ist der Wert bei Prescaler 1 interessant: Die Anzahl der nötigen
|
69 | ist Overflows ist nämlich eine ganze Zahl und das vereinfacht das
|
70 | Programmieren!
|
71 |
|
72 | Dieser Wert wird im Timer0-Interrupt verwendet.
|
73 | */
|
74 |
|
75 | // 8-Bit TIMER0 Normal Mode, Prescaler 1
|
76 | TCCR0 = (0 << WGM01) | (0 << WGM00)
|
77 | | (0 << CS02) | (0 << CS01) | (1 << CS00) ;
|
78 |
|
79 | // Und den spezellen Timer0 Overflow Interrupt nicht nur konfigurieren,
|
80 | // sondern auch zulassen (enablen) d.h. das Timer/Counter Interrupt Mask
|
81 | // Register setzen (Seite 93)
|
82 |
|
83 | TIMSK = (1 << TOIE0);
|
84 |
|
85 | // Alle zugelassenen Interrupts einschalten
|
86 | sei();
|
87 |
|
88 | // Endlosschleife
|
89 | // 1. main() nie verlassen
|
90 | // 2. wird vom Timer0 Overflow Interrupt unterbrochen
|
91 | while(1)
|
92 | {
|
93 | }
|
94 | }
|
95 |
|
96 | /**
|
97 | Dies ist die Interruptroutine, die aufgerufen wird,
|
98 | wenn der eingestellte Timer einen Überlauf hat.
|
99 |
|
100 | Der Name ist aus Datenblatt und aus avr/iom8515.h
|
101 | ersichtlich. avr/iom8515.h ist die genaue Beschreibung
|
102 | deines µC und wird über avr/io.h eingebunden.
|
103 |
|
104 | Ein möglicher Interruptvektor steht dort im Abschnitt:
|
105 |
|
106 | // Timer/Counter0 Overflow
|
107 | #define TIMER0_OVF_vect _VECTOR(7)
|
108 |
|
109 | Timer0 ist ein 8-Bit-Timer mit Overflow Modus
|
110 | */
|
111 |
|
112 | unsigned int Anzahl_Overflows;
|
113 |
|
114 | ISR(TIMER0_OVF_vect)
|
115 | {
|
116 | Anzahl_Overflows++;
|
117 |
|
118 | // Prüfen ob 1s voll
|
119 | if (Anzahl_Overflows == 1 * F_CPU / 256)
|
120 | {
|
121 | // LOW/HIGH mit Hilfe der XOR Bitmanipulation umschalten
|
122 | // das schaltet die LED(s) AN/AUS
|
123 |
|
124 | // In der Simulation auf die nächste Zeile einen Breakpoint setzen (F9)
|
125 | // und das Programm voll laufen lassen (F5).
|
126 | // Dann mit Hilfe der Stop Watch im I/O View die Zeit bis zum
|
127 | // nächsten Erreichen des Breakpoints messen.
|
128 | // (Nicht ungeduldig werden. Das dauert auf meinem Rechner ca. 65 s)
|
129 | PORTB ^= 0xFF;
|
130 |
|
131 | // Zurücksetzen für nächste 1s Wartezeit
|
132 | Anzahl_Overflows = 0;
|
133 | }
|
134 | }
|