A few tips for those in the same situation I was in earlier today:
- don't use routines that require interrupts (such as delay()) in your interrupt handlers.
- keep your interrupt handler as quick as possible
- check the datasheet, setting some registers (ASSR) can corrupt others, so order is important.
- the largest prescalar is 1024x, so the longest delay between interrupts is 8 seconds. You need a counter if you want increase this (as in the example).
Code: Select all
int led = 13; // led pin
int led_state = 0; // initial led state
int toggle_led = 0; // flag to indicate led needs to be toggled
int flash_led = 0; // flag to indicate led needs to be flashed
int count_int = 0; // count
void setup() {
// disable interrupts
noInterrupts();
// set out LED to output and set its initial state
pinMode(led, OUTPUT);
digitalWrite(led, led_state);
// enable crystal clock source
ASSR = (1 << AS2);
// use CTC mode
TCCR2A = (1 << WGM21);
// set prescalar to 1024x, each count is 0.03125 seconds.
TCCR2B = ( (1<<CS22) | (1<<CS21) | (1<<CS20) );
// set OCR2A to 32 (1 second)
OCR2A = 32;
// enable timer compare interrupt
TIMSK2 = (1 << OCIE2A);
// enable interrupts
interrupts();
}
void loop() {
// If the toggle_led flag is set, toggle the led
if (toggle_led == 1) {
toggle_led = 0; // clear the flag
led_state = ~led_state;
digitalWrite(led, led_state);
}
// if the flash_led is set, flash the led a few times
if (flash_led == 1) {
flash_led = 0; // clear the flag
for (int i = 0; i<4; i++) {
digitalWrite(led, HIGH);
delay(80);
digitalWrite(led, LOW);
delay(80);
}
// set the led back to what it was
digitalWrite(led, led_state);
}
}
ISR(TIMER2_COMPA_vect){
// increment our interrupt counter
count_int++;
// set the toggle_led flag to true
toggle_led = 1;
// set the flash_led count to true every 10th interrupt
if ((count_int % 10) == 0) {
flash_led = 1;
}
// reset the interrupt counter to zero after 60 interrupts
if (count_int > 59) {
count_int = 0;
}
}