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);
}