La interrupción por desbordamiento se dispara solo una vez

5

Me he topado con un problema donde, al parecer, mi interrupción solo se dispara una vez, luego simplemente se niega a disparar nuevamente en mi ATMega32U2. Tengo el siguiente código (simplificado):

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;
}

Cuando conecto un LED en cada pin de PORTB , el primer pin es alto, mientras que el resto es bajo. Lo máximo que puedo deducir de esto es que PORTB se incrementa a 0x01 con la activación de la interrupción una vez, y luego se deja solo ya que la interrupción nunca se dispara nuevamente usando el vector TIMER0_COMPA_vect .

Sin embargo , si sustituyo la interrupción de comparación por una interrupción por desbordamiento ( TIMER0_OVF_vect ) y configuro los registros de manera diferente, funciona bien; PORTB pasa de 0 a 255 muy rápidamente, como es de esperar. Este es mi código de trabajo con el tipo de interrupción que no quiero:

// 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;
}

He leído lo que hay que leer en Google, sin embargo, las únicas correcciones publicadas son errores lógicos que creo que no tengo. He leído esta publicación del foro y eché un vistazo al temporizador los registros de configuración, y son exactamente los mismos que en mi primer ejemplo. También he leído esta pregunta , pero eso no ayudó.

He estado siguiendo el tutorial en esta página (PDF) para el LED TLC5940 chip del controlador y estoy en el Capítulo 4 (código de refactorización para utilizar interrupciones). Tenga en cuenta que no quiero usar la biblioteca ya construida; Estoy usando esto como una experiencia de aprendizaje.

    
pregunta Bojangles

1 respuesta

6

Esto puede ser simplemente un error tipográfico en su publicación, pero la línea donde habilita la interrupción de la Comparación del Temporizador dice:

TIMSK0 != (1 << OCIE0A);

... cuando debería decir ...

TIMSK0 |= (1 << OCIE0A);

Es sutil, pero si eso es lo que realmente era su código, entonces estaba comparando TIMSK0 con una constante en lugar de asignarle (y por lo tanto, nunca habilitó la interrupción).

En una nota al margen, puedes escribir más concisamente:

TIMSK0 |= _BV(OCIE0A);

... en lugar de ...

TIMSK0 |= (1 << OCIE0A);

en avr-libc, si te gusta ese tipo de cosas :-).

    
respondido por el vicatcu

Lea otras preguntas en las etiquetas