I'm trying to program the ADC on the M0 pro. My goal is to capture an ADC sample every 0.5ms on 6 channels. But right now I'm trying to implement an ADC interrupt on just one channel AIN[0].
I've been following the code samples at: ForceTronics: Utilizing Advanced ADC Capabilities on Arduino’s with the SAMD21 (Zero, MKR1000, etc) Part 1
The problem I'm having in my code is that ADC interrupt is not triggered at all. I'm not sure what I'm doing wrong. I'm setting up the clocks, and then initializing the ADC and then setting up the interrupt. But when I try to test the interrupt by toggling a I/O pin, the interrupt is NOT triggered. Any guidance is much appreciated. Thank you!!!
void adc_init(void){
// Configure clock source and clock generators (gclk.h)------------------------
GCLK->GENDIV.reg = GCLK_GENDIV_ID(5) | // Select GLCK5
GCLK_GENDIV_DIV(1); // Select prescalar 1
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for SYNC
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(5) | // Select GCLK5
GCLK_GENCTRL_SRC_DFLL48M | // Select GCLK SRC
GCLK_GENCTRL_IDC | // Improve duty cycle for odd div factors
GCLK_GENCTRL_GENEN; // Enable GCLK5
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for SYNC
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_GEN_GCLK5 | // Select GLCK5
GCLK_CLKCTRL_ID_ADC | // Connect to ADC
GCLK_CLKCTRL_CLKEN;
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for SYNC
// Configure power manager (pm.h)-------------------------------------------
PM->APBCMASK.reg = PM_APBCMASK_ADC; // Setup Power manager for ADC peripheral
PM->APBCSEL.reg = PM_APBCSEL_APBCDIV_DIV1; // Select prescalar 1
// ADC configuration (adc.h) ----------------------------------------------
ADC->CTRLA.reg &= ~ADC_CTRLA_ENABLE; // Disable ADC peripheral
while(ADC->STATUS.bit.SYNCBUSY); // Wait of sync
ADC->REFCTRL.reg = ADC_REFCTRL_REFCOMP | // REF buffer offset compensation enable
ADC_REFCTRL_REFSEL_INT1V; //1.0V REF selected
ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_1;
ADC->SAMPCTRL.reg = ADC_SAMPCTRL_SAMPLEN(0x00);
ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV4 | // ADC CLK prescalar 4
ADC_CTRLB_RESSEL_12BIT | // 12-bit ADC result
ADC_CTRLB_FREERUN; // ADC free run mode
while(ADC->STATUS.bit.SYNCBUSY);
ADC->WINCTRL.reg = ADC_WINCTRL_WINMODE_DISABLE; // Disable window monitor mode
while(ADC->STATUS.bit.SYNCBUSY);
ADC->INPUTCTRL.reg = ADC_INPUTCTRL_GAIN_1X | // ADC gain factor x1
ADC_INPUTCTRL_INPUTSCAN(0x0)| // Number of channels included in scan
ADC_INPUTCTRL_MUXPOS_PIN0 | // Positive MUX input selection
ADC_INPUTCTRL_MUXNEG_GND;
while(ADC->STATUS.bit.SYNCBUSY);
// Configure ADC interrupts ------------------------------------------
ADC->INTENCLR.reg = ADC_INTENCLR_RESRDY; // Clear result ready interrupt
ADC->INTENSET.reg = ADC_INTENSET_RESRDY; // Set result ready interrupt
NVIC_SetPriority(ADC_IRQn, 3); // Set the Nested Vector Interrupt Controller (NVIC) priority for TCC1 to 0 (highest)
NVIC_EnableIRQ(ADC_IRQn); // Connect ADC to Nested Vector Interrupt Controller (NVIC)
// Input and output pins---------------------------------------------------
PORT->Group[PORTA].PINCFG[2].bit.PMUXEN = 1; // Peripheral mux enable PWM
PORT->Group[PORTA].PMUX[1].reg = PORT_PMUX_PMUXE_B; // Enable PMUX group B Even pins
// Enable ADC--------------------------------------------------------------
ADC->CTRLA.reg = ADC_CTRLA_ENABLE; // Enable ADC peripheral
while(ADC->STATUS.bit.SYNCBUSY); // Wait of sync
ADC->SWTRIG.reg = ADC_SWTRIG_START; // Start ADC conversion
while(ADC->STATUS.bit.SYNCBUSY); // Wait for sync
}
void ADC_Handler(void){
PORT->Group[PORTA].OUTTGL.reg = PORT_PA21;
if (ADC->INTFLAG.bit.RESRDY && ADC->INTENSET.bit.RESRDY) { // A overflow caused the interrupt
ADCresult = ADC->RESULT.reg;
ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY; // reset interrupt flag
}
}