I'm programming a PIC16F877A microcontroller in C, compiling with Microchip XC8 1.44.
I have set up a TMR0 interrupt for every 800 microseconds that scans through a LED matrix, lighting each 8 LED column at a time using the settings as follows:
OPTION_REG = 0x04; // TMR0 prescaler (1:32)
GIE = 1;
TMR0IE = 1;
And this is my 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;
}
}
Basically c
(for 'counter') will hold a number between 0 and 9999, and the 31 column LED matrix displays it using the data in font
to draw the numbers.
Now, this code works just right. But if I move TMR0IF = 0;
to the beginning of the block, something strange happens:
The program seems to become slow, as if the clock dropped by a factor of 100 or more, and the main program loop crashes and because of that I stop receiving the external signals that I use to increment or reset the value of c
, only the ISR remains being called and keep the LED matrix lit, but flickering due to the clock drop.
If I move TMR0IF = 0;
to the end like in the code above though, everything seems to work normally and the world is perfect. But why?
Everywhere I see code reference for Timer 0 interrupt usage people set TMR0IF = 0;
right away, why is it causing all that hassle in my code?
if (TMR0IF) {
(where{
marks the beginning of a block in C syntax). \$\endgroup\$