Go Down

Topic: Arduino Zero TCC Capture (Read 38947 times) previous topic - next topic

trampas

I was not sending the resync command before reading counter.

Now that this fixed I am counting but the direction is always counting positive.

MartinL

#166
Feb 05, 2019, 10:25 am Last Edit: Feb 05, 2019, 10:47 am by MartinL
Hi trampas,

The easiest way to get this working, is to set-up the event channels for asynchronous operation and the interrupt inputs to work on level rather than edge detection. This allows the input signals to pass through the event channels to the TCC2 counter unhindered and for the timer to clock off the event edges instead.

Setting up the event channels for asynchronous operation also means that you don't have clock them with a generic clock.

Here's an example that sets up TCC2 to count input events on D12, with D10 determining timer count direction. The TCC2 counter value is output to the console:

Code: [Select]
// Setup TCC2 to count input events on D12, with D10 determining timer count direction
void setup()
{
  SerialUSB.begin(115200);                   // Send data back on the Zero's native port
  while(!SerialUSB);                         // Wait for the SerialUSB port to be ready
 
  PM->APBCMASK.reg |= PM_APBCMASK_EVSYS;     // Switch on the event system peripheral
 
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Enable the generic clock...
                      GCLK_CLKCTRL_GEN_GCLK0 |     // ....on GCLK0
                      GCLK_CLKCTRL_ID_TCC2_TC3;    // Feed the GCLK0 to TCC2 and TC3
  while (GCLK->STATUS.bit.SYNCBUSY);               // Wait for synchronization

  // Enable the port multiplexer on digital pin D10 count and D12 input
  PORT->Group[g_APinDescription[10].ulPort].PINCFG[g_APinDescription[10].ulPin].reg |= PORT_PINCFG_PULLEN | PORT_PINCFG_PMUXEN;
  PORT->Group[g_APinDescription[12].ulPort].PINCFG[g_APinDescription[12].ulPin].reg |= PORT_PINCFG_PULLEN | PORT_PINCFG_PMUXEN;
 
  // Set-up the pin as an EIC (interrupt) peripheral on D10 and D12
  PORT->Group[g_APinDescription[12].ulPort].PMUX[g_APinDescription[12].ulPin >> 1].reg = PORT_PMUX_PMUXO_A | PORT_PMUX_PMUXE_A ;

  //attachInterrupt(10, NULL, HIGH);                                       // Attach interrupts to digital pin 10 (external interrupt 2)
  EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO2;                                 // Enable event output on external interrupt 2
  EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE2_HIGH;                            // Set event on detecting a HIGH level
 
  //attachInterrupt(12, NULL, HIGH);                                       // Attach interrupts to digital pin 12 (external interrupt 3)
  EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO3;                                 // Enable event output on external interrupt 3
  EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE3_HIGH;                            // Set event on detecting a HIGH level
  EIC->CTRL.reg |= EIC_CTRL_ENABLE;                                        // 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_TCC2_EV_0);              // Set the event user (receiver) as timer TCC2, event 0
 
  EVSYS->USER.reg = EVSYS_USER_CHANNEL(2) |                                // Attach the event user (receiver) to channel 1 (n + 1)
                    EVSYS_USER_USER(EVSYS_ID_USER_TCC2_EV_1);              // Set the event user (receiver) as timer TCC2, event 1

  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
 
  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_2) |    // Set event generator (sender) as external interrupt 2
                       EVSYS_CHANNEL_CHANNEL(1);                           // Attach the generator (sender) to channel 1
 
  TCC2->EVCTRL.reg |= TCC_EVCTRL_TCEI1 |                                   // Enable the TCC event 1 input
                      TCC_EVCTRL_TCEI0 |                                   // Enable the TCC event 0 input
                      //TCC_EVCTRL_TCINV1 |                                  // Invert the event 1 input
                      //TCC_EVCTRL_TCINV0 |                                  // Invert the event 0 input
                      TCC_EVCTRL_EVACT1_DIR |                              // Set event 1 to change the counter direction
                      TCC_EVCTRL_EVACT0_COUNTEV;                           // Set event 0 to count the incoming events

  TCC2->WAVE.reg = TCC_WAVE_WAVEGEN_NFRQ;                                  // Set the TCC2 timer counter to normal frequency mode
  while (TCC2->SYNCBUSY.bit.WAVE);                                         // Wait for synchronization
                                                                                     
  TCC2->CTRLA.bit.ENABLE = 1;                                             // Enable TCC2
  while (TCC2->SYNCBUSY.bit.ENABLE);                                      // Wait for synchronization
}

void loop()
{
  TCC2->CTRLBSET.reg = TCC_CTRLBSET_CMD_READSYNC;                         // Trigger a read synchronization on the COUNT register
  while (TCC2->SYNCBUSY.bit.CTRLB);                                       // Wait for the CTRLB register write synchronization
  while (TCC2->SYNCBUSY.bit.COUNT);                                       // Wait for the COUNT register read sychronization
  SerialUSB.println(TCC2->COUNT.reg);                                     // Output the TCC2 COUNT register
}


aromring

Hello Everyone,
I have implemented some of your code (dutifully acknowledged) in my project:

https://www.instructables.com/id/How-to-Measure-High-Frequency-and-Duty-Cycle-Simul/

Thank you for posting!

Go Up