I'm trying to use CTC mode on Arduino 1 but I have the following problem. I need to generate an interrupt on threshold B and A and I have set the prescaler to 1 since I want to generate interrupt A at 15999 (correspond to 1ms) and interupt B at 15( ie a number small enough from the start of counting). I'have write a println function in ISR(A and B) to proof the calling of the latter but the program does not print all the characters in the println function and furthermore the counter does not reset at treshold A but stop his work. How I can resolve the problem?
Here is the program I wrote:
void setup() {
TCCR1A = 0x00; // No outputs on compare math, no PWM mode
TCCR1B = 1 | (1 << WGM12); // Enable CTC mode up to OCR1A and prescaler /1 -> Start
//TCCR1B = 0b00001001;
TCCR1C = 0x00; // Nothing to set into C register
OCR1A = 15999; // Set Threshold A
OCR1B = 15; // Set Threshold B
TCNT1 = 0; // Clear Counter
TIFR1 = (1 << OCIE1A) | (1 << OCIE1B); // Clear Interrupt flag Match A and B
TIMSK1 = (1 << OCIE1A) | (1 << OCIE1B); // Enable Interrapt flag Match A and B
analogRead(A0); // Dummy Read to make Arduino setting the AD
ADCSRA |= (1 << ADIE); // Enable AD Interrupt on conversion completed
ADCSRB = 5; // Select Timer 1 Match B as trigger
ADCSRA |= 1 << ADATE; // Enable Auto trigger
Serial.begin(115200); // Initialize the USART
Serial.println("Start"); // Write the welcome message
}
void loop() {
// Nothing to do
}
ISR(ADC_vect)
{
Serial.print(TCNT1);
Serial.print(" - ADC Conversion Completed (");
Serial.print(ADC);
Serial.println(")");
}
ISR(TIMER1_COMPA_vect)
{
TCNT1=0;
Serial.print(TCNT1);
Serial.println(" - Interrupt A");
}
ISR(TIMER1_COMPB_vect)
{
Serial.print(TCNT1);
Serial.println(" - Interrupt B");
}
-
In CTC mode TCNT1 is automatically set back to 0 when it reaches OCR1A. So there is no need to do that inside the ISR. In fact TCNT1 might have already increase in value by the time the ISR is called, so the interval would be slightly more that the 1ms you want.Gerben– Gerben2014年10月24日 18:11:30 +00:00Commented Oct 24, 2014 at 18:11
1 Answer 1
I don't know about configuring the timers on an AVR off hand, but one thing I will point out:
- Never ever use Serial in an ISR.
Serial is interrupt driven - when there are characters in the outgoing serial buffer an interrupt routine sends them out through the serial port. That can't happen when you're in an interrupt routine yourself, so when the buffer fills up the next Serial.write() (print, etc) blocks until there is room in the buffer for the next character. As the ISR can't run, that space never appears, so the print(), write(), etc never finish and the program locks up.
Instead you should store any incoming values in your ISRs into volatile variables, and set flags to indicate to your main program what has happened in the ISR - then your main loop() reads (and resets) those flags and prints out the statuses you want.
-
Ok thanks, but why if I increment prescaler setting and threshold the program works?lui14– lui142014年10月24日 10:44:13 +00:00Commented Oct 24, 2014 at 10:44
-
If you're running the timer slower you're giving it more time between ISR calls to empty out the serial buffer.Majenko– Majenko2014年10月24日 11:31:18 +00:00Commented Oct 24, 2014 at 11:31
-
1serial in an ISR is still bad practice; However, the arduino Serial library detects if interrupts are disabled and will manually run the serial interrupt handlers when necessary so lock up never happens. printing will take a (relatively) long and inconsistent amount of time though.BrettFolkins– BrettFolkins2014年10月24日 16:44:17 +00:00Commented Oct 24, 2014 at 16:44
-
@BrettAM: Interesting, thanks for the note. This seems to be the case since release 1.5.6 BETA. Interestingly, it appears that, although this behaviour was implemented in April 2013, almost a month before the 1.0.5 release, it didn't make it to 1.0.5, ant not even to 1.0.6, which came eight months after 1.5.6 BETA.Edgar Bonet– Edgar Bonet2016年02月10日 13:53:32 +00:00Commented Feb 10, 2016 at 13:53
Explore related questions
See similar questions with these tags.