cancel
Showing results for 
Search instead for 
Did you mean: 

Controlling DMA clock in regular simultaneous ADC

juergen239955_stm1
Associate II
Posted on September 14, 2012 at 03:36

Dear colleagues,

        The CPU is an STM32F407IG, and I am using the standard peripheral libraries for STM32F4xx (both answers in the context of the library or the registers directly are appreciated).

        I'm using ADC1 and ADC2 in regular simultaneous mode to measure two independent signals at the same time. I set the ADC clock to 18MHz based on the peripheral timer:

RCC_PCLK2Config(RCC_HCLK_Div2);

and

ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4.

Then I use DMA2_Stream0 to copy the data to an array

__IO uint16_t ADCDualConvertedValue[2]

, all of which works nicely.

The question is whether there is an elegant way to control the dma transfer rate. I guess I could leave it at 16 MHz (same as ADC) and add a separate timer-based interrupt to read out the target array. But that sounds like a waste of resources, and I was looking for a way to control the DMA clock. Ultimately, a measurement frequency of only up to 1 kHz is needed. Any hints which direction to take?

Thanks in advance,

JJ
4 REPLIES 4
frankmeyer9
Associate II
Posted on September 14, 2012 at 09:10

The DMA is 'clocked' by the frequency of EOC events of the ADC. It just transfers the contents of the ADC result register to the location you defined in the initialization.

There are ADC+DMA examples projects in the peripheral libs, wich you have seen probably.

I guess I could leave it at 16 MHz (same as ADC) and add a separate timer-based interrupt to read out the target array. But that sounds like a waste of resources, and I was looking for a way to control the DMA clock.

 

That would be a waste, indeed.

A better way is to configure a ''End Of Transfer'' interrupt for the DMA channel. It generates an interrupt each time its target address reaches the configured target buffer size, before setting the target transfer address back to the start (assuming circular mode).

I'm quite sure there is an example in the F10x peripheral libs, which should at least explain the concept.

juergen239955_stm1
Associate II
Posted on September 15, 2012 at 01:10

Just to make sure: all you're proposing is to set up a sufficiently large buffer with DMA_BufferSize = f_ADC/f_my_sampling, correct? That can still be quite a sizable buffer, 16k entries for 16MHz ADC frequency and the 1kHz I'm actually interested in. Seems quite large, especially if I'm concerned about memory usage.

Any alternatives?

JJ

Posted on September 15, 2012 at 04:14

Why wouldn't you just trigger the start of conversion using one of the timer triggers, and just pace them that way?

I can't see why you couldn't use small circular DMA buffers, and interrupt on the TC and/or HT

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
frankmeyer9
Associate II
Posted on September 15, 2012 at 20:13

Just to make sure: all you're proposing is to set up a sufficiently large buffer with DMA_BufferSize = f_ADC/f_my_sampling, correct?

 

No.

I would suggest to size the buffer according the number of channels you want to convert. Say you want 8 different channels, use a buffer of 8 words, or multiples of 8 words.

When you configure the DMA in circular mode with ''transmission completed'' interrupt, you have one set (or <n> sets) of values for each channel ready for processing when the interrupt fires.

1 kHz is not really a challenging sampling frequency, but you might need to make sure that you do not interfere with the DMA. That means, either process the values before the DMA begins to overwrite them, or copy it away.