I am trying to get an interrupt working using TC3. The below code works fine, except for the fact that it appears to run at only .5MHz instead of the intended 48MHz. CC[0] is set to 4166. My oscilloscope, connected to PA15, shows a period of 8300ms, so that works about to be half a megahertz.
Looking at the code, I am pretty sure no prescaling is being done and that the clock should run at 48MHz, but I guess I must be missing something.
The CC0 register acts as the TOP value of your timer cycle.
However, in match frequency mode you also have to take into account that the fact the output pin is toggled, this effectively further divides your output frequency by 2.
At what frequency were you intending to trigger the TC interrupt?
Thanks for your response and for pointing me in the right direction.
I am trying to get it to trigger the interrupt at 48MHz (/4166, so about 11.5K times per second). I will study the data sheet some more tonight and see if I can figure it out.
// Set timer TC3 to call the TC3_Handler every 86.8us
void setup() {
// Set up the generic clock (GCLK4) used to clock timers
REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide the 48MHz clock source by divisor 1: 48MHz/1=48MHz
GCLK_GENDIV_ID(4); // Select Generic Clock (GCLK) 4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
GCLK_GENCTRL_GENEN | // Enable GCLK4
GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source
GCLK_GENCTRL_ID(4); // Select GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
// Feed GCLK4 to TCC2 and TC3
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TCC2 and TC3
GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4
GCLK_CLKCTRL_ID_TCC2_TC3; // Feed the GCLK4 to TCC2 and TC3
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
// Enable output to test, should be a frequency of 5760Hz
// Enable the port multiplexer for the digital pin D10
PORT->Group[g_APinDescription[10].ulPort].PINCFG[g_APinDescription[10].ulPin].bit.PMUXEN = 1;
// Connect the TC3 timer to the port output D10 - port pins are paired odd PMUXO and even PMUXE
// In this case peripheral E specifies the TC3/WO[0] timer output
PORT->Group[g_APinDescription[10].ulPort].PMUX[g_APinDescription[10].ulPin >> 1].reg = /*PORT_PMUX_PMUXO_E |*/ PORT_PMUX_PMUXE_E;
REG_TC3_COUNT16_CC0 = 4166; // Set the TC3 CC0 register as the TOP value in match frequency mode
while (TC3->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization
NVIC_SetPriority(TC3_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC3 to 0 (highest)
NVIC_EnableIRQ(TC3_IRQn); // Connect TC3 to Nested Vector Interrupt Controller (NVIC)
REG_TC3_INTFLAG |= TC_INTFLAG_OVF; // Clear the interrupt flags
REG_TC3_INTENSET = TC_INTENSET_OVF; // Enable TC3 interrupts
// REG_TC3_INTENCLR = TC_INTENCLR_OVF; // Disable TC3 interrupts
REG_TC3_CTRLA |= TC_CTRLA_PRESCALER_DIV1 | // Set prescaler to 1, 48MHz/1 = 48MHz
TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC3 into match frequency (MFRQ) mode
TC_CTRLA_ENABLE; // Enable TC3
while (TC3->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization
}
void loop() {}
void TC3_Handler() // Interrupt Service Routine (ISR) for timer TC3
{
// Check for overflow (OVF) interrupt
if (TC3->COUNT16.INTFLAG.bit.OVF && TC3->COUNT16.INTENSET.bit.OVF)
{
// Put your timer overflow (OVF) code here:
// ...
REG_TC3_INTFLAG = TC_INTFLAG_OVF; // Clear the OVF interrupt flag
}
}