I am trying to set a timer trigger an interrupt 8k times a second on the AVR128DB48. The initialization code I am using to initialize the clock is below.
//clock init
//24Mhz/64 = 375k
//(1/375k)*top=(1/8000)
//top = 46
TCA0.SINGLE.PER = 46;
//enables overflow interrupt
TCA0.SINGLE.INTCTRL |= 0x1;
//sets clock divider to 64 enables clock
TCA0.SINGLE.CTRLA |= TCA_SINGLE_RUNSTDBY_bm | TCA_SINGLE_ENABLE_bm | (5<<1);
This is almost exactly what the documentation says the initialization code should be. In order to test the interrupt I am using this function as the interrupt handler
ISR(TCA0_OVF_vect)
{
outputval = !outputval;
if (outputval){
PORTC.OUT |= 2;
}
else{
PORTC.OUTCLR |= 2;
}
return;
}
When I hook up this pin to my oscilloscope and measure the frequency it reads output frequency of 35k. If I change the per value to anything it also always reads 35k. I tested with values like 100 and 200 all the same results. I also change the clock divider and I still get the same result of 35k. If I don't set the enable bit I don't get any output. Is there something I missing? Does the interrupt OVF not do what I think it does? I have gone through the documentation several times and I believe I am doing everything correct.
As pointed out by kkrambo the issue was that with the AVR128DB48, this interrupt flag is not cleared automatically by the interrupt controller so you need to clear the flag at the end of the interrupt handler before you return. If you don't it will continuously try to service the interrupt over and over again. This is done by writing 1 to the interrupt flag which for the this peripheral and for this interrupt (OVF) done by the following code below:
TCA0.SINGLE.INTFLAGS |= 0x1;
So for the revised code for the whole interrupt would be:
ISR(TCA0_OVF_vect)
{
outputval = !outputval;
if (outputval){
PORTC.OUT |= 2;
}
else{
PORTC.OUTCLR |= 2;
}
TCA0.SINGLE.INTFLAGS |= 0x1;
return;
}