cancel
Showing results for 
Search instead for 
Did you mean: 

Best way to sample ADC at 48kHz for buffer manipulations (FFT, etc)?

NNagy.1
Senior

I'm trying to make a guitar pedal using the ADC on my F767ZI. I want to be able to perform an FFT and other functions on a buffer of data sampled at 48kHz.

I wanted to use the ADC DMAs and use the equation Tconv = 12.5cycles + SampleTime, but I have not been able to generate an exact PCLK rate in CubeMX to get the ADC sample rate at 48kHz precisely.

Am I better of using a 48kHz timer interrupt to read a sample from the DMA(?) and using some sort of global FIFO buffer? I worry that that might be overkill but at least I would know the sample rate is accurate.

16 REPLIES 16

Maybe "crude" was too crude here and I should have simply said "simple". I used FreeRTOS and a queue in a similar project (with GUI,...) which is safe and better scalable if there are more than one periodic task to be executed.

On the other hand, if it is really only one task, it could be even executed in the interrupt handler without doing harm.

volatile has ist uses but also pitfalls (which are more prevalent when caches and multi-core come into play).

KnarfB

Thanks for the explanation.

JW

@KnarfB​ 

Looks like for my board the only option I get in CubeMX under ADC "External Trigger Conversion Source" is EXTI Line 11 (doesn't give me any option to set the source to a timer)

0693W00000FCoL3QAL.pngshould look like this (for the nucleo board), see also chip reference manual:

hth

KnarfB

Not sure what I changed, but now I'm seeing the same as your screenshot. All is good!

a remark on quality: There is alot of digital noise in an MCU. There are some STM app notes about ADCC accuracy, tips and recommendations. But, for best results, you cannot beat an external audio ADC and a carefully layouted PCB.

Ironically - and I learned this the hard way - trying this polling method caused my DAC to not output anything.

Once I commented out the setting inputBufPtr to NULL in processDSP() and the check in main(), ie once I set the while() loop to call processDSP(), then the DAC output the expected waveform, albeit very noisily.

However, I spent hours before that with the polling in place, and was getting absolutely nothing.

Just to make sure I'm interpreting what you suggested correctly, this was my code:

void processDSP() {
	for (int i = 0; i < DATA_SIZE; i++) {
		outBufPtr[i] = inBufPtr[i];
	}
	inBufPtr = NULL;
}
 
int main(void)
{
  HAL_Init();
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC3_Init();
  MX_DAC_Init();
  MX_TIM6_Init();
  HAL_TIM_Base_Start_IT(&htim6);
  HAL_ADC_Start_DMA(&hadc3, (uint32_t*)&adcBuffer, BUFFER_LEN);
  HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)&dacBuffer, BUFFER_LEN, DAC_ALIGN_12B_R);
 
  while (1)
  {
	if(inBufPtr == NULL) {
		continue;
	}
	processDSP();
  }
}