Arduino zero timer interrupt period error

hi. I'm building an mcu that samples the EMG at 2kHz rate. So, to set the timer interrupt to 2kHz, I entered the Clock Counter(CC) reg as 48M/(64*2k)-1 = 374, and an interrupt event occurs at a rate of approximately 6~800Hz.
The code is referenced from that URL. microcontroller - SAMD21 1μs timer handler taking longer than the timer period? - Electrical Engineering Stack Exchange

What's wrong?



/* ========== Variables ========== */
#define LED         13
#define PIN         7
#define DATA_LENGTH 2000
#define ANALOG_PIN  A0
volatile uint8_t flag=0;
/*  0:  LED
 *  1:  EMG 
 *  2:  
*/
volatile uint16_t idx=0;
uint16_t emg[DATA_LENGTH];
unsigned long long t;

/* ========== Interrupt ========== */
void TC5_Handler(){
  // Pulse toggle
  if((flag&1) == 1){
    flag &= 254;digitalWrite(PIN,LOW);
  }else{
    flag |= 1;digitalWrite(PIN,HIGH);
  }
  // ADC
  emg[idx] = analogRead(ANALOG_PIN);
  Serial.println(emg[idx]);
  if (++idx == DATA_LENGTH){
    flag |= 2;idx = 0;
  }
  TC5->COUNT16.INTENSET.bit.MC0 = 1;
  
}

/* ========== Main ========== */
void setup(){
  // Serial setup
  Serial.begin(230400);
  delay(100);

  // timer setup
  // Enable generic clock for Timer/Counter 4 and 5
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 |
      GCLK_CLKCTRL_ID(GCM_TC4_TC5);
  while (GCLK->STATUS.bit.SYNCBUSY);
  
  // Perform software reset
  TC5->COUNT16.CTRLA.reg = TC_CTRLA_SWRST;
  while (TC5->COUNT16.STATUS.reg & TC_STATUS_SYNCBUSY);
  while (TC5->COUNT16.CTRLA.bit.SWRST);
  
  // Configure TC5
  TC5->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 |     // Counter of 16 bits
                           TC_CTRLA_WAVEGEN_MFRQ |     // Match frequency
                           TC_CTRLA_PRESCALER_DIV64;    // Prescaler of 1 (no division)
  TC5->COUNT16.CC[0].reg = F_CPU / 64 / 2000 -1; // Trigger @ 2kHz
  while (TC5->COUNT16.STATUS.bit.SYNCBUSY);
  
  // Configure interrupt
  uint32_t oldISER = NVIC->ISER[0];
  NVIC->ICER[0] |= ~0ul;  // Disable all interrupts
  NVIC->ICPR[0] = 1ul << TC5_IRQn;            // Clear pending timer interrupt
  NVIC->ISER[0] = 1ul << (TC5_IRQn & 0x1f);   // Enable TC5 interrupt
  TC5->COUNT16.INTENSET.bit.MC0 = 1;          // Match/Compare 0 interrupt
  while (TC5->COUNT16.STATUS.bit.SYNCBUSY);
  
  // Start counter
  TC5->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE;  // Enable TC5
  while (TC5->COUNT16.STATUS.bit.SYNCBUSY);
  
  // GPIO setup
  pinMode(LED,OUTPUT);
  pinMode(PIN,OUTPUT);
  digitalWrite(LED,LOW);
  digitalWrite(PIN,LOW);

  // ADC setup
  analogReadResolution(12);

}
void loop(){
  if ((flag&2)==2){
    flag &= 253;
  }
  digitalWrite(LED, HIGH);
  delay(250);
  digitalWrite(LED, LOW);
  delay(250);
}

You should not be performing Serial operations from an interrupt. Remove that and see if it helps.

Even though serial operations are removed, it does not work normally.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.