1

I am using an Arduino Mega 2560.

I have a code in a c file, that looks like this:

 #include <avr/io.h> /* for DDRB, PORTB, etc. */
#include <util/delay.h> /* for _delay_ms () */
#include <arduino.h>
int main(void){
 DDRB |= ((1 << DDB7)); // Define pin 13 as output
 noInterrupts();
//set timer1 interrupt at 1Hz
 TCCR1A = 0;// set entire TCCR1A register to 0
 TCCR1B = 0;// same for TCCR1B
 TCNT1 = 0;//initialize counter value to 0
 // set compare match register for 1hz increments
 OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
 // turn on CTC mode
 TCCR1B |= (1 << WGM12);
 // Set CS12 and CS10 bits for 1024 prescaler
 TCCR1B |= (1 << CS12) | (1 << CS10); 
 // enable timer compare interrupt
 TIMSK1 |= (1 << OCIE1A);
 interrupts();
 while(1){
 asm("nop");
 }
return 0;
}
 ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine
{
 PORTB ^= ((1 << PB7)); // toggle LED pin
 PINB |= _BV(7);
 PINB = PINB | _BV(7);
}

Which is called from an ino file, like this:

 extern "C"
 {
 void foo ();
 }
void setup ()
 { 
 foo ();
 } // end of setup
void loop ()
 {
 } // end of loop

However, if I set up another timer interrupt (ex Timer Interrupt 0 or 2, the blink will stop happening, for some reason...

For example:

//set timer0 interrupt at 2kHz
 TCCR0A = 0;// set entire TCCR2A register to 0
 TCCR0B = 0;// same for TCCR2B
 TCNT0 = 0;//initialize counter value to 0
 // set compare match register for 2khz increments
 OCR0A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256)
 // turn on CTC mode
 TCCR0A |= (1 << WGM01);
 // Set CS01 and CS00 bits for 64 prescaler
 TCCR0B |= (1 << CS01) | (1 << CS00); 
 // enable timer compare interrupt
 TIMSK0 |= (1 << OCIE0A);

Now, the strangest part happens that if all the three (or just the same two) timer interrupts are set, and with everything defined in the INO file, it works fine...

//this code will enable all three arduino timer interrupts.
//timer0 will interrupt at 2kHz
//timer1 will interrupt at 1Hz
//timer2 will interrupt at 8kHz
//storage variables
boolean toggle0 = 0;
boolean toggle1 = 0;
boolean toggle2 = 0;
void setup(){
 //set pins as outputs
 pinMode(8, OUTPUT);
 pinMode(9, OUTPUT);
 pinMode(13, OUTPUT);
cli();//stop interrupts
//set timer0 interrupt at 2kHz
 TCCR0A = 0;// set entire TCCR2A register to 0
 TCCR0B = 0;// same for TCCR2B
 TCNT0 = 0;//initialize counter value to 0
 // set compare match register for 2khz increments
 OCR0A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256)
 // turn on CTC mode
 TCCR0A |= (1 << WGM01);
 // Set CS01 and CS00 bits for 64 prescaler
 TCCR0B |= (1 << CS01) | (1 << CS00); 
 // enable timer compare interrupt
 TIMSK0 |= (1 << OCIE0A);
//set timer1 interrupt at 1Hz
 TCCR1A = 0;// set entire TCCR1A register to 0
 TCCR1B = 0;// same for TCCR1B
 TCNT1 = 0;//initialize counter value to 0
 // set compare match register for 1hz increments
 OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
 // turn on CTC mode
 TCCR1B |= (1 << WGM12);
 // Set CS12 and CS10 bits for 1024 prescaler
 TCCR1B |= (1 << CS12) | (1 << CS10); 
 // enable timer compare interrupt
 TIMSK1 |= (1 << OCIE1A);
//set timer2 interrupt at 8kHz
 TCCR2A = 0;// set entire TCCR2A register to 0
 TCCR2B = 0;// same for TCCR2B
 TCNT2 = 0;//initialize counter value to 0
 // set compare match register for 8khz increments
 OCR2A = 249;// = (16*10^6) / (8000*8) - 1 (must be <256)
 // turn on CTC mode
 TCCR2A |= (1 << WGM21);
 // Set CS21 bit for 8 prescaler
 TCCR2B |= (1 << CS21); 
 // enable timer compare interrupt
 TIMSK2 |= (1 << OCIE2A);
sei();//allow interrupts
}//end setup
ISR(TIMER0_COMPA_vect){//timer0 interrupt 2kHz toggles pin 8
//generates pulse wave of frequency 2kHz/2 = 1kHz (takes two cycles for full wave- toggle high then toggle low)
 if (toggle0){
 digitalWrite(8,HIGH);
 toggle0 = 0;
 }
 else{
 digitalWrite(8,LOW);
 toggle0 = 1;
 }
}
ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
//generates pulse wave of frequency 1Hz/2 = 0.5kHz (takes two cycles for full wave- toggle high then toggle low)
 if (toggle1){
 digitalWrite(13,HIGH);
 toggle1 = 0;
 }
 else{
 digitalWrite(13,LOW);
 toggle1 = 1;
 }
}
ISR(TIMER2_COMPA_vect){//timer1 interrupt 8kHz toggles pin 9
//generates pulse wave of frequency 8kHz/2 = 4kHz (takes two cycles for full wave- toggle high then toggle low)
 if (toggle2){
 digitalWrite(9,HIGH);
 toggle2 = 0;
 }
 else{
 digitalWrite(9,LOW);
 toggle2 = 1;
 }
}
void loop(){
 //do other things here
}

Is anybody able to explain why it works in the first case, doesn't work in the second, and in the third, it works as well?

asked Nov 3, 2015 at 22:46

1 Answer 1

1

I found out that it's not enough to just define the interrupts, there must also be an ISR method with the compare vector...

 ISR(TIMER0_COMPA_vect) // timer compare interrupt service routine
{
 PORTB ^= ((1 << PB6)); // toggle LED pin
 PINB |= _BV(6);
 PINB = PINB | _BV(6);
}

There was no error at compile, though.

answered Nov 3, 2015 at 22:56
1
  • there must also be an ISR method with the compare vector - that's correct - you have told the processor to jump to an ISR vector, and the default vector jumps to the start of your program. There was no error at compile, though. - you have not made any syntactical errors. Commented Nov 4, 2015 at 1:53

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.