Ich bin auf ein Problem gestoßen, bei dem mein Interrupt anscheinend nur einmal ausgelöst wird und sich dann einfach weigert, erneut auf meinem ATMega32U2 zu feuern. Ich habe den folgenden (abgespeckten) Code:
void init(void) {
DDRB = 0xff;
PORTB = 0x00;
TCCR0A = (1 << WGM01);
// 1024 prescaler
TCCR0B = ((1 << CS02) | (1 << CS00));
// Interrupt every 4096 clocks
OCR0A = 3;
// Enable timer compare match interrupt
TIMSK0 != (1 << OCIE0A);
}
ISR(TIMER0_COMPA_vect) {
PORTB++;
}
int main(void) {
init();
sei();
while(1);
return 0;
}
Wenn ich eine LED in jeden Pin von stecke PORTB
, ist der erste Pin hoch, während der Rest niedrig ist. Das Beste, was ich daraus ableiten kann, ist, dass der Interrupt einmal PORTB
inkrementiert und dann in Ruhe gelassen wird, da der Interrupt nie wieder mit dem Vektor ausgelöst wird.0x01
TIMER0_COMPA_vect
Wenn ich jedoch den Vergleichs-Interrupt durch einen Überlauf-Interrupt ( TIMER0_OVF_vect
) ersetze und die Register anders konfiguriere, funktioniert es einwandfrei; PORTB
Zyklen durch 0 - 255 sehr schnell, wie ich es erwarten würde. Dies ist mein Arbeitscode mit der Art von Interrupt, die ich nicht möchte:
// Different timer config
void init(void) {
DDRB = 0xff;
PORTB = 0x00;
TCCR0B |= (1 << CS01);
// Enable timer 0 interrupt
TIMSK0 |= (1 << TOIE0);
}
// This time, it's an OVERFLOW vector, not a compare vector
ISR(TIMER0_OVF_vect) {
PORTB++;
}
int main(void) {
init();
sei();
while(1);
return 0;
}
Ich habe gelesen, was es bei Google zu lesen gibt, aber die einzigen geposteten Korrekturen sind logische Fehler, von denen ich nicht glaube, dass ich sie habe. Ich habe diesen Forumsbeitrag gelesen und mir die Timer-Konfigurationsregister angesehen, und sie sind genau die gleichen wie in meinem ersten Beispiel. Ich habe diese Frage auch gelesen , aber das hat nicht geholfen.
Ich habe das Tutorial auf dieser Seite (PDF) für den LED-Treiberchip TLC5940 verfolgt und bin in Kapitel 4 (Umgestaltung des Codes zur Verwendung von Interrupts). Bitte beachten Sie, dass ich die fertig erstellte Bibliothek nicht verwenden möchte; Ich nutze dies als Lernerfahrung.
Dies kann nur ein Tippfehler in Ihrem Beitrag sein, aber die Zeile, in der Sie den Timer Compare-Interrupt aktivieren, sagt:
TIMSK0 != (1 << OCIE0A);
... wenn es heißen sollte ...
TIMSK0 |= (1 << OCIE0A);
Es ist subtil, aber wenn das Ihr Code tatsächlich war, dann haben Sie TIMSK0 mit einer Konstante verglichen, anstatt ihr zuzuweisen (und daher den Interrupt nie wirklich aktiviert).
In einer Randbemerkung können Sie prägnanter schreiben:
TIMSK0 |= _BV(OCIE0A);
... anstatt ..
TIMSK0 |= (1 << OCIE0A);
in der avr-libc, falls du auf sowas stehst :-).
0xakhil
Markierungen
Shenles
Kevin Vermeer
_BV(3)
verwandelt sich in0b0000 0100
, genauso wie( 1 << 3 )
. Es wird "Unterstrich Bee Vee" ausgesprochen.Bojangles
Vicatcu
Vicatcu