ADC Interrupts not working

Hi,

I need to use the Arduino Due ADC with a sample rate of up to 44100 Hz, now I'm testing it with only 1000 Hz, I need two channels, maybe A7 and A6, because A0 is occupied with SPI USART1. I'm using a sketch of code similar to one I've used to write to the DAC but it's not working, because there are no interrupts, and I can't find out why.

Could you please help me? I can't find out what's wrong and analogRead is slow for this application.

Regards,
Danny

fastAnalogRead.ino (3.86 KB)

Have you searched for material related to adc and due?

Like ... Playing With Analog to Digital Converter on Arduino Due · Nice Circuits - Electronics, 3d printing and robots

Also..... could you please explain what this line in your code is meant to do?.....

while (i0 < 1000 || i1 < 1000);

Should add some documentation (ie. comments) in your code.

Also, the lines in that particular section are all commented out .... by the symbols //
Why is a significant portion of the code commented out?

Southpark:
Also..... could you please explain what this line in your code is meant to do?.....

while (i0 < 1000 || i1 < 1000);

To wait until the sample arrays become full.

Southpark:
Have you searched for material related to adc and due?

Like ... Playing With Analog to Digital Converter on Arduino Due · Nice Circuits - Electronics, 3d printing and robots

Also, the lines in that particular section are all commented out .... by the symbols //
Why is a significant portion of the code commented out?

I haven't found any example where the DAC is triggered by the timer counter, I need the timer counter to generate the desired sampling rate.

There are some lines commented because I'm debugging the code.

I tried the example code MarkT posted in the thread "Example of driving ADC and DAC from timer for regular sampling", and I've made a few changes to define the sampling rate and use the A7 and A6 ADC inputs instead of A0, I've also omitted the DAC part, but the code is stuck somewhere, and I can't find out why?

Could you help me, please? I can't find anything wrong in this code.

adcExample.ino (3.42 KB)

Here is an example sketch of ADC sampling (1 channel) and DAC output (1 channel) triggered by a Timer Counter. Adapt this code to your needs and you are done:

/****************************************************************************************************/
/*  1 MHz ADC conversions of 1 analog input (A0) triggered by Timer Counter 0 channel 2 TIOA2       */
/*  1 MHz DAC output on channel 1 (DAC1) triggered by Timer Counter 0 channel 2 TIOA2               */
/****************************************************************************************************/

void setup()
{

  adc_setup();
  dac_setup();
  tc_setup();
}

void loop()
{

}

/*************  Configure adc_setup function  *******************/
void adc_setup() {

  PMC->PMC_PCER1 |= PMC_PCER1_PID37;                    // ADC power ON

  ADC->ADC_CR = ADC_CR_SWRST;                           // Reset ADC
  ADC->ADC_MR |=  ADC_MR_TRGEN_EN                       // Hardware trigger select
                  | ADC_MR_TRGSEL_ADC_TRIG3             // Trigger by TIOA2
                  | ADC_MR_PRESCAL(1);

  ADC->ADC_ACR = ADC_ACR_IBCTL(0b01);                   // For frequencies > 500 KHz

  ADC->ADC_IER = ADC_IER_EOC7;                          // End Of Conversion interrupt enable for channel 7
  NVIC_EnableIRQ((IRQn_Type)ADC_IRQn);                  // Enable ADC interrupt
  ADC->ADC_CHER = ADC_CHER_CH7;                         // Enable Channels 7 = A0
}

void ADC_Handler () {

  /* Todo : Apply any digital filtering before DAC output  */
  /* Beware : Stay in ADC_Handler much less than 1 us  !!! */
  DACC->DACC_CDR = ADC->ADC_CDR[7];                    // Reading ADC->ADC_CDR[i] clears EOCi bit

}

/*************  Configure adc_setup function  *******************/
void dac_setup ()
{

  PMC->PMC_PCER1 = PMC_PCER1_PID38;                   // DACC power ON

  DACC->DACC_CR = DACC_CR_SWRST ;                     // Reset DACC
  DACC->DACC_MR = DACC_MR_TRGEN_EN                    // Hardware trigger select
                  | DACC_MR_TRGSEL(0b011)             // Trigger by TIOA2
                  | DACC_MR_USER_SEL_CHANNEL1         // select channel 1
                  | DACC_MR_REFRESH (1)
                  | DACC_MR_STARTUP_8
                  | DACC_MR_MAXS;

  DACC->DACC_CHER = DACC_CHER_CH1;                   // enable channel 1 = DAC1

}

/*************  Timer Counter 0 Channel 2 to generate PWM pulses thru TIOA2  ************/
void tc_setup() {

  PMC->PMC_PCER0 |= PMC_PCER0_PID29;                      // TC2 power ON : Timer Counter 0 channel 2 IS TC2

  TC0->TC_CHANNEL[2].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1  // MCK/2, clk on rising edge
                              | TC_CMR_WAVE               // Waveform mode
                              | TC_CMR_WAVSEL_UP_RC       // UP mode with automatic trigger on RC Compare
                              | TC_CMR_ACPA_CLEAR         // Clear TIOA2 on RA compare match
                              | TC_CMR_ACPC_SET;          // Set TIOA2 on RC compare match


  TC0->TC_CHANNEL[2].TC_RC = 42;  //<*********************  Frequency = (Mck/2)/TC_RC  Hz = 1 MHz
  TC0->TC_CHANNEL[2].TC_RA = 20;  //<********************   Any Duty cycle in between 1 and TC_RC

  TC0->TC_CHANNEL[2].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN;// Software trigger TC2 counter and enable

}

Ok, thanks! I will adapt the code

I've made a few changes to the code, I'm using DRDY as interrupt flag and I'm using TAGS to read two ADC channels using the LCDR register. If I need to sample two channels at 1 kHz, I have to set the sampling rate at 2 kHz?

a_n_adcExample_edited.ino (3.46 KB)

danny92:
If I need to sample two channels at 1 kHz, I have to set the sampling rate at 2 kHz?

that's right.

Don't Serial.print inside the interrupt handler.

If you read ADC_LCDR in the interrupt handler, set only DRDY bit in ADC_IER because reading ADC_LCDR will not clear EOC bit (the datasheet page 1322 is wrong !)