Trying to get started with timer interrupts

Hi all,

I'm just getting started using Arduino. After getting my first blinking LED using the timer utils, I tried to start using timer interrupts. The project I'm aiming this at will eventually use an external interrupt triggered by the 50Hz mains frequency, but since I don't have the signal source yet, I'm trying to use the internal timer interrupt.

Anyway, my code is below. All it does is turn on the LED and keep it on which shows that main() does get executed. When I move the bit "PORTB |= LED_PIN;" (and nothing else) into the ISR the LED never turns on which shows that the ISR simply never gets executed.

(Note that I'm not using setup() or anything other Arduino-specific convenience functions, nor the IDE. The .hex is built with avr-gcc and flashed using avrdude because eventually this is going to end up on a non-Arduino AVR).

The code is based on this tutorial: https://engineerexperiences.com/arduino-uno-timer-and-interrupts.html

The datasheet says "The corresponding Interrupt Vector (see
“Interrupts” on page 66) is executed when the OCF1A Flag, located in TIFR1, is set." so I added the line "TIFR1 |= (1 << OCF1A);" (not in the tutorial), but it doesn't make a difference.

#include <avr/io.h>
#include <avr/interrupt.h>

#define LED_PIN (1 << 5) // Port B Bit 5 = I/O 13 on Ard. UNO

int main(void) {
    /* set up 50 Hz timer:
     * Clock 16MHz
     * Prescaler = 256
     * Count limit = 16000000 / (256 * 50) - 1 = 1249
     * We need timer 1 b/c timer 0 and 2 only can count up to 255 */
    cli();                              // disable interrupts

    TCCR1A = 0;                         // Set up timer control registers
    TCCR1B = (1 << WGM12)               // CTC mode
           | (1 << CS12);               // Prescaler bit for 256
    TCNT1 = 0;                          // start at 0
    OCR1A = 1249;                       // Count to this number
    TIFR1 |= (1 << OCF1A);              // found this in the datasheet
    TIMSK1 |= (1 << OCIE1A);            // set interrupt mask


    sei();                              // enable interrupts

    DDRB = LED_PIN;                     // Port B Bit 5 = I/O 13
    PORTB |= LED_PIN;                   // Turn LED on (confirm we have the
                                        // right pin)
}

#define MAX_TICKS 50
uint8_t ticks = MAX_TICKS;

ISR(TIMER1_COMPA_vect) {
    --ticks;
    if (ticks == 0) {
        ticks = MAX_TICKS;
        if (PORTB & LED_PIN) {          // if LED is on, turn it off
            PORTB &= ~LED_PIN;
        } else {                        // if LED is off, turn it on
            PORTB |= LED_PIN;
        }
    }
}

Found it! I forgot to add a while(!) {} loop in main() to keep the program running. That said, even if main() falls right through, shouldn't the interrupt just keep running, considering that the AVR has no operating system that could reclaim the resources?

Are you trying to understand the working mechanism of INT0-interrupt by applying 50 Hz signal at DPin-2? But, you have no external source of the 50 Hz signal. If you wish, you can create this 50 Hz signal using TC1 of the MCU at DPin-9 and feed it into DPin-2 to interrupt the MCU.

No. I just wanted to figure out how to use interrupts, and a timer interrupt seems to be the simplest option for that.

For example: Fig-1 shows that there are 5 possible interrupt sources for TC1. Which interrupt do you want to use and for what purpose?


Figure=1:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.