Ich bin gerade etwas verwirrt. Ich habe einen ATMEGA328P mit einem
20-MHz-Quarz und möchte etwas trickreich eine gewisse Anzahl von
Mikrosekunden abwarten. Um den Programmablauf nicht zu unterbrechen,
soll das per Timer-Interrupt passieren. Aus verschiedenen Gründen steht
mir nur noch Timer2 zur Verfügung.
Das Ganze dient dazu, einen Servo anzusteuern.
Beim Programmstart initialisiere ich meinen Timer mit:
1 | TCCR2A = 0;
|
2 | TCCR2B = _BV(CS21) | _BV(CS20); // Prescaler 1/32
|
Für einen Impuls resette ich TCNT2, setze meinen Ausgang auf High und
aktiviere den Interrupt.
Im Interrupthandler wird die Zahl der Überlaufe gezählt und bei
Erreichen der gewünschten Zahl wird der Ausgang wieder auf Low gesetzt
und der Interrupt deaktiviert.
1 | static volatile uint8_t Overflows;
|
2 |
|
3 | ISR(TIMER2_OVF_vect) {
|
4 | if (--Overflows > 0) return;
|
5 |
|
6 | LO(PIN_SERVO); // Ist ein Makro
|
7 | TIMSK2 = 0;
|
8 | }
|
Ich habe (durch Ausprobieren) herausgefunden, dass mein Servo bei 40000
CPU-Takten in Mittelstellung (genau zwischen den Endanschlägen) geht:
1 | Overflows = 5;
|
2 | TCNT2 = 30;
|
3 | HI(PIN_SERVO); // Ist ein Makro
|
4 | TIMSK2 = _BV(TOIE2);
|
Der Timer zählt also insgesamt 5*256-30 = 1250 Mal, also 40000 Takte
(Prescaler 1/32). 40000 Takte sind bei 20 MHz aber 2000 µs und nicht
1500 µs (was laut Datenblatt die Mittelstellung sein soll). Es stimmt
aber definitiv, denn bei der halben Zeit (1000 µs) versucht das Servo
schon über den Endanschlag zu fahren und rattert und knackt
besorgniserregend.
Wo habe ich falsch gerechnet?