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