Estoy programando un microcontrolador PIC16F877A en C, compilando con Microchip XC8 1.44.
He configurado una interrupción TMR0 por cada 800 microsegundos que escanea a través de una matriz de LED, iluminando cada columna de 8 LED a la vez usando la configuración de la siguiente manera:
OPTION_REG = 0x04; // TMR0 prescaler (1:32)
GIE = 1;
TMR0IE = 1;
Y este es mi ISR:
void interrupt isr()
{
static const uint16_t divs[4] = { 1000, 100, 10, 1 };
if (TMR0IF)
{
PORTB = 0x00; // PORTB is the 8 LED column
if (i)
{
PORTAbits.RA0 = 1; // pin that clocks CD4017 for next column
__nop(); // give a brief delay just for good measure
PORTAbits.RA0 = 0;
}
else
{
PORTAbits.RA1 = 1; // pin that resets CD4017 to first column
__nop();
PORTAbits.RA1 = 0;
}
// pattern to be displayed
PORTB = font[i % 8U + 8U * ((c / divs[i / 8U]) % 10U)];
i = (i + 1U) % 31U; // increment i for next iteration
TMR0 = TMR0_OFFSET; // 240 for 4MHz crystal for 800us delay according to my calculations (I am bad at calculations)
TMR0IF = 0;
}
}
Básicamente, c
(para 'contador') mantendrá un número entre 0 y 9999, y la matriz de 31 columnas LED lo muestra utilizando los datos en font
para dibujar los números.
Ahora, este código funciona correctamente. Pero si muevo TMR0IF = 0;
al principio del bloque, sucede algo extraño:
El programa parece ser lento, como si el reloj se retrasara por un factor de 100 o más, y el bucle del programa principal falla y, por eso, dejo de recibir las señales externas que utilizo para aumentar o restablecer el valor de c
, solo permanece el ISR y mantiene la matriz de LED encendida, pero parpadea debido a la caída del reloj.
Si muevo TMR0IF = 0;
al final como en el código anterior, todo parece funcionar normalmente y el mundo es perfecto. Pero ¿por qué?
En todas partes veo la referencia del código para el uso de interrupciones del Temporizador 0, la gente establece TMR0IF = 0;
de inmediato, ¿por qué está causando todos los problemas en mi código?