Setting up ISR for ADC on Zero

Hi geryuu123,

Here's an example of how transfer a number of ADC samples to a memory array using an Interrupt Service Routine (ISR) with the ADC in free run mode:

// Use the SAMD21's ISR to transfer ADC results to buffer array in memory
#define SAMPLE_NO 8                                  // Define the number of ADC samples

volatile uint16_t adcResult[SAMPLE_NO] = {};         // ADC results buffer
volatile bool resultsReady = false;                  // Results ready flag

void setup() {
  SerialUSB.begin(115200);                           // Start the native USB port
  while(!SerialUSB);                                 // Wait for the console to open

  ADC->INPUTCTRL.bit.MUXPOS = 0x0;                   // Set the analog input to A0
  while(ADC->STATUS.bit.SYNCBUSY);                   // Wait for synchronization
  ADC->SAMPCTRL.bit.SAMPLEN = 0x00;                  // Set max Sampling Time Length to half divided ADC clock pulse (2.66us)
  ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV512 |      // Divide Clock ADC GCLK by 512 (48MHz/512 = 93.7kHz)
                   ADC_CTRLB_RESSEL_12BIT |          // Set the ADC resolution to 12 bits
                   ADC_CTRLB_FREERUN;                // Set the ADC to free run
  while(ADC->STATUS.bit.SYNCBUSY);                   // Wait for synchronization  
  NVIC_SetPriority(ADC_IRQn, 0);    // Set the Nested Vector Interrupt Controller (NVIC) priority for the ADC to 0 (highest) 
  NVIC_EnableIRQ(ADC_IRQn);         // Connect the ADC to Nested Vector Interrupt Controller (NVIC)
  ADC->INTENSET.reg = ADC_INTENSET_RESRDY;           // Generate interrupt on result ready (RESRDY)
  ADC->CTRLA.bit.ENABLE = 1;                         // Enable the ADC
  while(ADC->STATUS.bit.SYNCBUSY);                   // Wait for synchronization
  ADC->SWTRIG.bit.START = 1;                         // Initiate a software trigger to start an ADC conversion
  while(ADC->STATUS.bit.SYNCBUSY);                   // Wait for synchronization
}

void loop()
{
  if (resultsReady)
  {                         
    for (uint16_t i = 0; i < SAMPLE_NO; i++)           // Display the results on the console
    {
      SerialUSB.print(i + 1);
      SerialUSB.print(F(": "));
      SerialUSB.println(adcResult[i]);
    }
    SerialUSB.println();
    delay(1000);                                       // Wait for 1 second
    resultsReady = false;                              // Clear the resultsReady flag
    ADC->CTRLA.bit.ENABLE = 1;                         // Enable the ADC
    while(ADC->STATUS.bit.SYNCBUSY);                   // Wait for synchronization
    ADC->SWTRIG.bit.START = 1;                         // Initiate a software trigger to start an ADC conversion
    while(ADC->STATUS.bit.SYNCBUSY);                   // Wait for synchronization
  }
}

void ADC_Handler()
{
  static uint16_t counter = 0;                       // Results counter
  
  if (ADC->INTFLAG.bit.RESRDY)                       // Check if the result ready (RESRDY) flag has been set
  { 
    ADC->INTFLAG.bit.RESRDY = 1;                     // Clear the RESRDY flag
    while(ADC->STATUS.bit.SYNCBUSY);                 // Wait for read synchronization
    adcResult[counter++] = ADC->RESULT.reg;          // Read the result;
    if (counter == SAMPLE_NO)                        // Once the required number of samples have been made
    {
      ADC->CTRLA.bit.ENABLE = 0;                     // Disable the ADC
      while(ADC->STATUS.bit.SYNCBUSY);               // Wait for synchronization
      counter = 0;                                   // Reset the counter
      resultsReady = true;                           // Set the resultsReady flag
    }
  }
}