I found a fix, it is now 1 us, 1 Msps but I cannot find a way to do this on pin A7, everybody is using pin A0
int x; // read value
int myArray[20000];
void setup()
{
Serial.begin(9600); // initialize the serial port:
REG_ADC_MR = 0x10380180; // change from 10380200 to 10380180, 1 is the PREESCALER and 8 means FREERUN
ADC -> ADC_CHER = 0x80; // enable ADC on pin A0
}
void loop() {
int t = micros(); // init time an elapsed time, in micro seconds
for(int i = 0; i < 20000; i++) {
// instrucction to measure
while((ADC->ADC_ISR & 0x80)==0); // wait for conversion
With the code below, I can reach 999 938 Hz in Free Running Mode with Prescal (1) and 1 908 976 Hz with Prescal (0), not bad for ADC conversions followed by DAC conversions of 128 Half words buffers:
/*******************************************************************************************/
/* ADC and DAC in FREE Running Mode and PDC DMA */
/*******************************************************************************************/
volatile uint32_t Timestamp, Oldmicros;
volatile boolean Flag;
volatile uint8_t bufn, bufn_dac;
const uint16_t bufsize = 128; // size must be a power of 2
const uint8_t bufnumber = 4; // bufnumber > 2, better be a power of 2
const uint8_t _bufnumber = bufnumber - 1;
uint16_t buf[bufnumber][bufsize]; // bufnumber buffers of bufsize samples,
void setup()
{
Serial.begin(250000);
pinMode(LED_BUILTIN, OUTPUT);
adc_setup();
dac_setup();
Oldmicros = micros();
}
void loop()
{
if (Flag) {
Flag = false;
Serial.println(Timestamp);
}
}
/************* 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_DIS // Free Running Mode selected
| ADC_MR_FREERUN
| ADC_MR_PRESCAL(0); // Or PRESCAL (1) to reduce ADC frequency to 21 MHz
ADC->ADC_ACR = ADC_ACR_IBCTL(0b01); // For frequencies > 500 KHz
ADC->ADC_IER = ADC_IER_ENDRX; // 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
/********* code for PDC/DMA buffer filling sequence **********/
ADC->ADC_RPR = (uint32_t)buf[1]; // DMA buffer - First one will be buf[1]
ADC->ADC_RCR = bufsize;
ADC->ADC_RNPR = (uint32_t)buf[2]; // next DMA buffer
ADC->ADC_RNCR = bufsize;
bufn = 2;
ADC->ADC_PTCR |= ADC_PTCR_RXTEN; // Enable PDC Receiver channel request
ADC->ADC_CR = ADC_CR_START;
}
/********* Call back function for ADC PDC/DMA **************/
void ADC_Handler () {
bufn = (bufn + 1) & _bufnumber;
ADC->ADC_RNPR = (uint32_t)buf[bufn];
ADC->ADC_RNCR = bufsize;
bufn_dac = (bufn_dac + 1) & _bufnumber;
DACC->DACC_TNPR = (uint32_t)buf[bufn_dac];
DACC->DACC_TNCR = bufsize;
// For debugging only
static uint32_t Count;
if (Count++ == 7812) { //1000000/128 ~7812
Timestamp = micros() - Oldmicros;
Oldmicros = micros();
Flag = true;
Count = 0;
PIOB->PIO_ODSR ^= PIO_ODSR_P27; // Toggle LED_BUILTIN every 1 Hz
}
}
/************* Configure dac_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_DIS // Free Running Mode selected
| DACC_MR_USER_SEL_CHANNEL1 // select channel 1
| DACC_MR_REFRESH (1)
| DACC_MR_STARTUP_8
| DACC_MR_MAXS;
DACC->DACC_ACR = DACC_ACR_IBCTLCH0(0b10)
| DACC_ACR_IBCTLCH1(0b10)
| DACC_ACR_IBCTLDACCORE(0b01);
DACC->DACC_IER = DACC_IER_ENDTX;
DACC->DACC_CHER = DACC_CHER_CH1; // enable channel 1 = DAC1
/************* configure PDC/DMA for DAC *******************/
DACC->DACC_TPR = (uint32_t)buf[0]; // DMA buffer
DACC->DACC_TCR = bufsize;
DACC->DACC_TNPR = (uint32_t)buf[1]; // next DMA buffer
DACC->DACC_TNCR = bufsize;
bufn_dac = 1;
DACC->DACC_PTCR = DACC_PTCR_TXTEN; // Enable PDC Transmit channel request
}
thanks for the code, it is a little long, the code I found is short and simple and it seems to be working.
I am not sure if I understand it well but I need to make a call to ADC_Handler() withing the loop() to take one 1 us reading. it is a little complicated to understand it right away, I am not so good.
ED201:
I am not sure if I understand it well but I need to make a call to ADC_Handler() withing the loop() to take one 1 us reading. it is a little complicated to understand it right away, I am not so good.
No, ADC_Handler gets called when your conversion is complete, -if you enable the interrupt. You set the speed of the adc in its setup registers. No need to call it within the loop().
I came on the same link as ard's, not quite sure you can do shorter than that.