Hi rsardu,
No, the 32 bit counter will rollover after approx. 4.6 ms. (20*10e6 / 2^32).
If you think about it, 2^32 - 1 = 4,294,967,295. This is the 32-bit timer/counter's maximum value.
It's counting a signal that's producing 20,000,000 pulses a second.
Therefore in one second, the timer/counter has counted to: 20,000,000, in two seconds: 40,000,000 and so on...
...after 214.75 seconds ((2^32 - 1) / 20MHz), the timer/counter has reached a value of 4,294,967,295, it maximum value and overflows.
Here's the code, it generates an 1 second output trigger on D11 (PA16). If you then connect this to the trigger pin input on D10 (PA18), it will trigger a measurement every second. Pin D12 (PA19) meanwhile counts the input pulses from an external source.
// Count the number of pulses on pin D12 (PA19) using 1 second test trigger pulse on D11 (PA16)
// for a trigger input on D10 (PA18)
volatile boolean countRead = false; // Count read flag
volatile uint32_t count; // Variable to hold the TCC0 count value
void setup()
{
SerialUSB.begin(115200); // Initialise the native serial port
while(!SerialUSB); // Wait for the console to open
PM->APBCMASK.reg |= PM_APBCMASK_EVSYS; // Switch on the event system peripheral
////////////////////////////////////////////////////////////////////////////////////////
// Generic Clock Initialisation
////////////////////////////////////////////////////////////////////////////////////////
GCLK->GENDIV.reg = GCLK_GENDIV_DIV(1) | // Select clock divisor to 1
GCLK_GENDIV_ID(4); // Select GLCK4
GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
GCLK_GENCTRL_GENEN | // Enable GCLK
GCLK_GENCTRL_SRC_XOSC32K | // Select GCLK source as external 32.768kHz crystal (XOSC32K)
GCLK_GENCTRL_ID(4); // Select GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable generic clock
GCLK_CLKCTRL_GEN_GCLK0 | // GCLK0 at 48MHz
GCLK_CLKCTRL_ID_TC4_TC5; // As a clock source for TC4 and TC5
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable generic clock
GCLK_CLKCTRL_GEN_GCLK4 | // GCLK4 at 32.768kHz
GCLK_CLKCTRL_ID_TCC2_TC3; // As a clock source for TCC2 and TC3
//////////////////////////////////////////////////////////////////////////////////////////////
// TCC2 Initialisation - reference timer: measures a 1s period
//////////////////////////////////////////////////////////////////////////////////////////////
PORT->Group[PORTA].PINCFG[16].bit.PMUXEN = 1; // Enable the port multiplexer on port pin PA16 (D11)
PORT->Group[PORTA].PMUX[16 >> 1].reg |= PORT_PMUX_PMUXE_E; // Set-up PA16 (D11) as an EIC (interrupt)
TCC2->PER.reg = 32767; // Set the period (PER) register for a PWM period of 1s
while (TCC2->SYNCBUSY.bit.PER); // Wait for synchronization
TCC2->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Set timer to Normal PWM mode (NPWM)
while (TCC2->SYNCBUSY.bit.WAVE); // Wait for synchronization
TCC2->CC[0].reg = 16384; // Set the duty cycle to 50%
while (TCC2->SYNCBUSY.bit.CC0); // Wait for synchronization
TCC2->CTRLA.bit.ENABLE = 1; // Enable TCC2
while (TCC2->SYNCBUSY.bit.ENABLE); // Wait for synchronization
////////////////////////////////////////////////////////////////////////////////////////
// TC4 Initialisation - measurement counter: counts the number incoming of pulses
////////////////////////////////////////////////////////////////////////////////////////
PORT->Group[PORTA].PINCFG[19].bit.PMUXEN = 1; // Enable the port multiplexer on port pin PA19 (D12)
PORT->Group[PORTA].PMUX[19 >> 1].reg |= PORT_PMUX_PMUXO_A; // Set-up PA12 (D12) as an EIC (interrupt)
EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO3; // Enable event output on external interrupt 3
EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE3_HIGH; // Set event detecting a HIGH level
EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT3; // Clear the interrupt flag on channel 3
EIC->CTRL.bit.ENABLE = 1; // Enable EIC peripheral
while (EIC->STATUS.bit.SYNCBUSY); // Wait for synchronization
EVSYS->USER.reg = EVSYS_USER_CHANNEL(1) | // Attach the event user (receiver) to channel 0 (n + 1)
EVSYS_USER_USER(EVSYS_ID_USER_TC4_EVU); // Set the event user (receiver) as timer TC4 event
EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT | // No event edge detection
EVSYS_CHANNEL_PATH_ASYNCHRONOUS | // Set event path as asynchronous
EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_3) | // Set event generator (sender) as external interrupt 3
EVSYS_CHANNEL_CHANNEL(0); // Attach the generator (sender) to channel 0
TC4->COUNT32.EVCTRL.reg = TC_EVCTRL_TCEI | // Enable TC4 event input
TC_EVCTRL_EVACT_COUNT; // Increment the TC4 counter upon receiving an event
TC4->COUNT32.CTRLA.reg = TC_CTRLA_MODE_COUNT32; // Chain TC4 with TC5 to create a 32-bit timer
TC4->COUNT32.CTRLA.bit.ENABLE = 1; // Enable TC4
while (TC4->COUNT32.STATUS.bit.SYNCBUSY); // Wait for synchronization
TC4->COUNT32.READREQ.reg = TC_READREQ_RCONT | // Enable a continuous read request
TC_READREQ_ADDR(0x10); // Offset of the 32-bit COUNT register
attachInterrupt(10, trigger, RISING); // Initialise the trigger pin on D10
}
void loop()
{
while(!countRead); // Block until the trigger() function returns
countRead = false; // Reset the count read flag
SerialUSB.println(count); // Print the result
}
void trigger()
{
count = TC4->COUNT32.COUNT.reg; // Read the COUNT register
countRead = true; // Set the count read flag
}
I tested the D12 (PA19) input with a 21MHz signal from my Arduino Due, here's the results:
1267
21000487
41999707
62998928
83998148
104997368
125996588
146995808
167995028
188994249
209993469
230992688
251991909
If you subtract one result from the next, you can see it measures the 21MHz signal relatively well. Not too bad for a 48MHz microcontroller and better than I expected.