I'm using MartinL's basic example code from this thread and it works as expected.
I'm toggling pin 13 up and down directly and looking at it on my scope. Since I'm doing this during an interrupt I get slightly less than the theoretical frequency (i.e. 187.394 kHz instead of 187.5 kHz, but that's not the issue.)
When I change both the main and timer clock divisor's to 1 with the PER at 0xFF I get what's expected: 48E6 / (1 * 1 * 256) = 187.5 kHz.
Confusion: With both CC0 and CC1 set to 0 and only toggling during overflows I would expect the frequency to increase as I decrease PER. But in fact any changes I make to PER have no effect on the output frequency. When I set PER To 0xF0 I would expect the output frequency to become 48E6 / (1 * 1 * 240) = 200 kHz, but it doesn't change, code attached.
I've read through the data sheet several times and gone over forum posts but am still confused. Thank you in advance, I'm still relatively new to electronics and these forums are a huge asset.
int testPin = 13;
void setup() {
pinMode(testPin, OUTPUT);
// Set up the generic clock (GCLK4) used to clock timers
REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide the 48MHz clock source by divisor 3: 48MHz/3=16MHz
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 TC4 and TC5
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TC4 and TC5
GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4
GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK4 to TC4 and TC5
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_TC4_COUNT8_CC0 = 0x00; // Set the TC4 CC0 register to some arbitary value 55
while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_TC4_COUNT8_CC1 = 0x00; // Set the TC4 CC1 register to some arbitary value AA
while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_TC4_COUNT8_PER = 0xF0; // ************************************************************* Set the PER (period) register to its maximum value
while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization
//NVIC_DisableIRQ(TC4_IRQn);
//NVIC_ClearPendingIRQ(TC4_IRQn);
NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest)
NVIC_EnableIRQ(TC4_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC)
REG_TC4_INTFLAG |= TC_INTFLAG_MC1 | TC_INTFLAG_MC0 | TC_INTFLAG_OVF; // Clear the interrupt flags
REG_TC4_INTENSET = TC_INTENSET_MC1 | TC_INTENSET_MC0 | TC_INTENSET_OVF; // Enable TC4 interrupts
// REG_TC4_INTENCLR = TC_INTENCLR_MC1 | TC_INTENCLR_MC0 | TC_INTENCLR_OVF; // Disable TC4 interrupts
REG_TC4_CTRLA |= TC_CTRLA_PRESCALER_DIV1 | // Set prescaler to 64, 16MHz/64 = 256kHz
TC_CTRLA_MODE_COUNT8 | // Set the counter to 8-bit mode
TC_CTRLA_ENABLE; // Enable TC4
while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization
}
void loop() {
// put your main code here, to run repeatedly:
}
void TC4_Handler() // Interrupt Service Routine (ISR) for timer TC4
{
// Check for overflow (OVF) interrupt
if (TC4->COUNT8.INTFLAG.bit.OVF && TC4->COUNT8.INTENSET.bit.OVF)
{
// Put your timer overflow (OVF) code here:
REG_PORT_OUT0 |= PORT_PA17; // debug pin 13 HIGH
REG_PORT_OUT0 &= ~PORT_PA17; // debug pin 13 LOW
REG_TC4_INTFLAG = TC_INTFLAG_OVF; // Clear the OVF interrupt flag
}
// Check for match counter 0 (MC0) interrupt
if (TC4->COUNT8.INTFLAG.bit.MC0 && TC4->COUNT8.INTENSET.bit.MC0)
{
// Put your counter compare 0 (CC0) code here:
// ...
REG_TC4_INTFLAG = TC_INTFLAG_MC0; // Clear the MC0 interrupt flag
}
// Check for match counter 1 (MC1) interrupt
if (TC4->COUNT8.INTFLAG.bit.MC1 && TC4->COUNT8.INTENSET.bit.MC1)
{
// Put your counter compare 1 (CC1) code here:
// ...
REG_TC4_INTFLAG = TC_INTFLAG_MC1; // Clear the MC1 interrupt flag
}
}

