cancel
Showing results for 
Search instead for 
Did you mean: 

ADC sample rate impossible to set precisely (calculations added)

Robmar
Senior III

I realise that with ADC timer triggered DMA of 32 samples, you can set the timer precisely, but not the ADC​ per sample clock, so the samples get bunched up or stretched in the frame. The number of clocks per sample is limited, adjusting the APB2 clock hardly helps. A bit more flexibility on sample clocks would be really useful, I guess there is no easy solution?

Objective: capture ADC samples spread evenly at 96 KS/s on STM32F407VG with 8MHz xtal

Reference: STM32F406VG datasheet.

Overview:-

To capture samples from two independent ADCs at 96 KS/s, Timer3 is set to generate

an event every 1/3 mS, i.e. 333.3r uS

ABP1 Clk 84 MHz drives Timer3 from a 42MHz clk via a fixed x2 multiplier.

ADC-DMA is triggered and set to take 32 samples:

APB2 (PCLK2 + prescaler /4,/6,/8) clk drives ADCs at 84 MHz: Period 11.904 nS

Okay, so 3,000 triggers of 32 samples pers second.

1. 3K triggers the ADC-DMA every 333.3r uS

2. 32 samples every 333.3r uS gives 10.416r uS per ADC sample.

3. a1) ADC clk at 84 MHz has a clk period of 11.904761 nS or 0.011904761 uS,

  b1) Prescaler of 8 reduces this to 10.5 MHZ, and a clk period of 0.095238088 uS

  c1) Prescaler 6 clk reduces to 14 MHz and a clk of 0.07142857 uS. 

  d1) Prescaler 4 clk reduces to 21 MHz and a clk of 0.04761904 uS. 

  e1) Prescaler 2 (MX deselected not peritted) clk ... 42MHz ...

  

  b1-R) P8: We need 10.416 uS worth of clocks per sample, giving 109.375008312501 clks at 10.5 MHz

  c1-R) P6: -""-, giving 145.82400291648 clks at 14 MHz

  d1-R) P4: -""-, giving 218.736034997776 clks at 21 MHz

  e1-R) P2: -""-, giving 437.472 clks at 42 MHz (MX deselected)

Each samples takes 15 clks + (3, 15, 28, 56, 84, 112, 144, 480 sample time clks selectable)

Best match: Prescaler 8, our 96KHz sampling rate requires 109.375 clks per 32 sample trigger, subtracting the ADC sample time of 15 for 16-bit conversion = 94.375 clks, nearest selection is Sample time of 84 + 15 = 99, an increase in sample rate by 10.375 clks per sample.

This increase in the sample rate will require a significant non-standard change to my DSP code. A single transfer per trigger would solve this if there was a way that the ADC-DMA could increment the memory address, but so far I can't see that is supported.

43 REPLIES 43

Its working circular DMA​ mode, but the ADC couldn't be set to complete 32 samples in exactly 333.3r uS due to sample clock options.

​So the ADC-DMA in DMA continuous requests mode can be set to do one transfer per timer trigger and increment the target address for the next ADC completion + trigger?

I'd thought that the DMA continuous requests ​mode incremented memory only during each run.

So how do I set it up, EOC at end of single, HAL_HDC_Start_DMA with length of 1 just once called at start for both ADCs, then HAL_Tim_Start to get both ADCs starting synchronised?

How does the MCU know to increment the address each trigger, and when to reset, like every 32 runs?​

AScha.3
Chief III
  • sorry, but what should be the real target of this ? 96k makes me think on hi-end audio , 96/24 recording.

if this is it about, first take a matching clock. i took AS318 low jitter osc. 49.152MHz as master clock;

( on H743 cpu ) , THEN you can talk about speed and precision and so on.

not when beginning with useless clock.

If you feel a post has answered your question, please click "Accept as Solution".

The clock is stable enough, and the 32F407VG already over £20 compared to the Arduino 328P which works perfectly well with dual ADC sampling in the very same application. I already have the code working perfectly but not at the exact target sample rate.

The aim is to sample efficiency with minimal CPU loading.​

The DMA doesn't care whether the ADC converts sequences or single conversions. It just transfers the data, when the data is ready, and increments addresses as configured. All of it is explained in the reference manual in the TIM, ADC, DMA chapters respectively.

Looking through the details, won't the single sample trigger method need an interrupt every sample to transfer the sample to the buffer. My code won't have time to handle it's other tasks and dual ADC sampling on top without automated DMA support​.

​Can't see any way the ADC -DMA will handle single transfers automatically to a buffer.

gbm
Lead III

You seem to ignore what I and Jan wrote. The ADC sampling time setting is (almost) irrelevant to your problem. Just set the timer to the required sampling frequency, line 96 or 192 kHz, which will trigger the SINGLE ADC conversion with the required frequency. Please re-read my and Jan's post. And yes, it's much easier to do this without HAL, at register level.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

Sorry but I think that's incorrect. ADC-DMA can do automatically repeating multiple or single transfers, but on single it doesn't have info on the buffer size because hal_adc_startDma​ is called with size set to 1, else it will transfer "size" samples to memory each trigger, not just one sample.

In the ADC params there is no entry to set a single transfer per trigger of size n samples with memory inc.​ per trigger.

If there is a way​ to do this please explain

Please re-read my comments I think I wasn't clear

So, one memory incremented automatic transfer per trigger, how exactly?

Call hal_adc_start_dma() with size=1, but how does it know the target buffer size to increment the address each dma transfer?

Call the function with size 32 and it will just transfer 32 samples each trigger!

The "number of conversions" entry in MX relates to polling ADC inputs, it's not a special trigger-by-trigger dma to incremented memory mode.

Think about it, there is not an indicated way to do this in any document.​

 I would like to be wrong about this so please say where this mode is exactly activated because for the life of me I can't see its in the datasheet, STM's app notes, or YouTube videos

> else it will transfer "size" samples to memory each trigger, not just one sample

That's just your fantasy, not the reality. Read what people have written for you!

Actually the PLL on MCU is usable up to approximately 16-bit resolution in the audio range. But for 12-bit resolution up to 48 kHz signal an 810 ps jitter is acceptable, which is way worse than the internal PLL.

https://www.maximintegrated.com/en/design/design-tools/calculators/general-engineering/jitter.html

By the way, @Robmar​ , do you actually need 96 kHz sample rate? Are you making some non-audio signal acquisition device?