Arduino anaolgRead in free running mode giving output voltage on input pin

Hi,

I have been trying to create some code to speed up the analogRead on the Due to get 1Mhz read frequency.
I have tried a number of the suggestions but they all end up giving an output voltage on the input pin.

For example:

void setup()
{
ADC->ADC_MR |= 0x80; // these lines set free running mode on adc 7 and adc 6
ADC->ADC_CR=2;
ADC → ADC_CHER = 0x80; // enable ADC on pin A0
}

Line 3 appears to create an output voltage on pin A0

Alternatively I tried:

void setup()
{
PMC->PMC_PCER1 |= PMC_PCER1_PID37; // ADC power ON

ADC->ADC_CR = ADC_CR_SWRST; // Reset ADC
ADC->ADC_MR |= ADC_MR_TRGEN_DIS // Hardware trigger disable
| ADC_MR_FREERUN
| ADC_MR_PRESCAL(0); // Or PRESCAL (1) to limit to 21 MHz

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(ADC_IRQn); // Enable ADC interrupt
ADC->ADC_CHER = ADC_CHER_CH7; // Enable Channel 7 = A0
}

Does anyone know how to have fast 1Mhz analogue reads without ending up with an output voltage on the input pin?

For conversion of periodic signals, add an RC filter with an RC time constant at least 10 times the frequency of the input signal.
Free running mode provides a sampling rate close to 1 Msps. For a precise sampling rate, the ADC peripheral has to be triggered by a Timer Counter or a PWM Event plus a DMA. Example sketches have been provided in the DUE sub forum.

Another example sketch in Free running mode with a DMA (SerialUSB.write() will give the fastest output to a PC):

volatile uint8_t bufn, obufn;
const uint16_t bufsize = 256;
uint16_t buf[4][bufsize];

void setup()
{
  //SerialUSB.begin(250000);
 // while (!SerialUSB);
  pinMode(LED_BUILTIN, OUTPUT);
  adc_setup();
}

void loop() {
  if (obufn != bufn) {
    // SerialUSB.write((uint8_t *)buf[obufn], 512); // send 512 bytes = 256 uint16_t
    obufn = (obufn + 1) & 3;
  }
}

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

  PMC->PMC_PCER1 |= PMC_PCER1_PID37; // Enable ADC

  ADC->ADC_MR = ADC_MR_FREERUN_ON |
                ADC_MR_PRESCAL(1) |
                ADC_MR_STARTUP_SUT8 |
                ADC_MR_SETTLING_AST9 |
                ADC_MR_TRACKTIM(1) |
                ADC_MR_TRANSFER(1);

  ADC->ADC_ACR = ADC_ACR_IBCTL(0b01);

  ADC->ADC_CHER = ADC_CHER_CH0;           // Enable Channel 0 = A7

  ADC->ADC_IER |= ADC_IER_ENDRX ;
  NVIC_SetPriority(SysTick_IRQn, 15);     // SysTick interrupt will not interrupt ADC interrupt
  NVIC_EnableIRQ(ADC_IRQn);               // Enable ADC interrupt

  /*************      PDC/DMA  buffer filling *******************/

  ADC->ADC_RPR = (uint32_t)buf[0];        // DMA buffer
  ADC->ADC_RCR = bufsize;
  ADC->ADC_RNPR = (uint32_t)buf[1];       // next DMA buffer
  ADC->ADC_RNCR = bufsize;
  bufn = obufn = 1;
  ADC->ADC_PTCR |= ADC_PTCR_RXTEN;        // Enable PDC receiver channel request
  ADC->ADC_CR = ADC_CR_START;
}

void ADC_Handler() {                // move DMA pointer to next buffer
  static uint32_t Count;
  // if ( ADC->ADC_ISR & ADC_ISR_ENDRX) {
  bufn = (bufn + 1) & 3;
  ADC->ADC_RNPR = (uint32_t)buf[bufn];
  ADC->ADC_RNCR = bufsize;
  // }

  // For debugging only
  if (Count++ > 3906) { // 3906 = 10E6/256
    Count = 0;
    PIOB->PIO_ODSR ^= PIO_ODSR_P27;
  }
}

I am thinking it might be something to do with the

ADC Channel Offset Register

OFFx:
Offset for channel x 0 = No Offset. 1 = center the analog signal on Vrefin/2 before the gain scaling.
The Offset applied is: (G-1)Vrefin/2 where G is the gain applied (see description of ADC_CGR register).

Not sure how to set this. Does anyone know?

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