1
  • I need to count the number of pulses in a moving window (e.g. last 60 seconds) using as less CPU time as possible.
  • The first step is to use TCC to capture pulse period.
  • The pulses arrive randomly at PB02 and the average frequency is about 20-100 counts per minute.

Attempt

According to datasheet TCC has Period and Pulse-Width (PPW) Capture Action

External pulse(PB02)-->EIC-->Event channel-->Event user(TC)

volatile uint32_t T;
volatile uint32_t count;
void setup() {
  Serial.begin(9600);
  while (!Serial);
  Serial.println("init");
  md_setup();
  // put your setup code here, to run once:

}

void loop() { Serial.println(T); Serial.println(count);
}

void md_setup() { //PM REG_PM_APBCMASK |= PM_APBCMASK_EVSYS; REG_PM_APBCMASK |= PM_APBCMASK_TCC0; Serial.println("PM done");

//GLCK REG_GCLK_GENDIV = GCLK_GENDIV_DIV(8) | GCLK_GENDIV_ID(5); while (GCLK->STATUS.bit.SYNCBUSY); REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW GCLK_GENCTRL_GENEN | // Enable GCLK 5 GCLK_GENCTRL_SRC_OSCULP32K | // Set the clock source to 32K GCLK_GENCTRL_ID(5); // Set clock source on GCLK 5 while (GCLK->STATUS.bit.SYNCBUSY); REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK5 | GCLK_CLKCTRL_ID_TCC0_TCC1; while (GCLK->STATUS.bit.SYNCBUSY); Serial.println("GCLK done");

//PORT //REG_PORT_PMUX1 |= PORT_PMUX_PMUXEN; //REG_PORT_PINCFG1 |= PORT_PINCFG_PMUXEN; REG_PORT_WRCONFIG1 = PORT_WRCONFIG_PINMASK(2) | //select pin PB02 (EIC02) PORT_WRCONFIG_PMUXEN | //enable peripheral function PORT_WRCONFIG_INEN | //input mode PORT_WRCONFIG_PMUX(0) | //select peripheral function A PORT_WRCONFIG_WRPMUX | //Write to PMUX register PORT_WRCONFIG_WRPINCFG | //Write to PINCFG register (0 << 31); //Select lower pins Serial.println("PORT done");

//EIC REG_EIC_EVCTRL |= EIC_EVCTRL_EXTINTEO2; // Enable event output on external interrupt 2 REG_EIC_CONFIG0 |= EIC_CONFIG_SENSE2_RISE; // Set event detecting rise REG_EIC_INTENCLR = EIC_INTENCLR_EXTINT2; // Clear the interrupt flag on channel 2 REG_EIC_CTRL |= EIC_CTRL_ENABLE; // Enable EIC peripheral //while (EIC->STATUS.bit.SYNCBUSY); Serial.println("EIC done");

//EVSYS REG_EVSYS_CHANNEL |= EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT | //no output EVSYS_CHANNEL_PATH_ASYNCHRONOUS | //async path EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_2) | // Select EIC2 EVSYS_CHANNEL_CHANNEL(1); //Channel 1 REG_EVSYS_USER |= EVSYS_USER_USER(EVSYS_ID_USER_TCC0_EV_1) | //Select USER = TCC0 EVSYS_USER_CHANNEL(2); //Select Channel 1 (N+1) //REG_EVSYS_CTRL |= CTRL_SWRST; Serial.println("EVSYS done");

//TCC0 REG_TCC0_CTRLA &= ~TCC_CTRLA_ENABLE; // Disable TCC0 peripheral REG_TCC0_CTRLBCLR |= TCC_CTRLBCLR_DIR; // Clear DIR bit to count up while (TCC0->SYNCBUSY.bit.CTRLB); // Wait for (write) synchronization REG_TCC0_EVCTRL |= TCC_EVCTRL_TCEI0 | // Enable the TCC event 0 input //TCC_EVCTRL_TCEI1 | // Enable the TCC event 1 input TCC_EVCTRL_MCEI1 | // Enable the match or capture channel 1 event input TCC_EVCTRL_MCEI0 | // Enable the match or capture channel 0 event input TCC_EVCTRL_EVACT1_PPW; // Select PPW REG_TCC0_CTRLA |= TCC_CTRLA_CPTEN1 | // Enable capture on CC1 TCC_CTRLA_CPTEN0 | // Enable capture on CC0 TCC_CTRLA_PRESCALER_DIV1; REG_TCC0_INTENSET = TCC_INTENSET_MC1 | // Enable compare channel 1 (CC1) interrupts TCC_INTENSET_MC0; // Enable compare channel 0 (CC0) interrupts REG_TCC0_CTRLA |= TCC_CTRLA_ENABLE; // Enable TCC0 while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization

NVIC_SetPriority(TCC0_IRQn, 0);
NVIC_EnableIRQ(TCC0_IRQn);
Serial.println("TCC done"); }

void TCC0_Handler()
{ count++; if (TCC0->INTFLAG.bit.MC0) { T = TCC0->CC[0].reg;
} if (TCC0->INTFLAG.bit.MC1); }

Problem

  • The result (T,count) is always zero.
  • if while (EIC->STATUS.bit.SYNCBUSY); is uncommitted, the execution will lock up there.
7E10FC9A
  • 209
  • 1
  • 6

0 Answers0