cancel
Showing results for 
Search instead for 
Did you mean: 

Controlling the ADC Sampling Rate

Rogers.Gary
Senior II
Posted on December 23, 2014 at 19:32

I've posted on this before, thought I'd nailed it correct, but did not, as there are inconsistent results. I am using the Discovery STM32F4 development board, along with IAR compiler/workbench.

Can someone please point me to a previous post (if there is one) or alternately, sample code, or alternately, pseudo-code that would explain the correct procedure to set up the ADC for an exact sampling rate? Since this is critical in any DSP operations, there must be a way to control that? I realize a timer interrupt is one way - but how about allowing the ADC to ''self-interrupt'', and then set a HW interrupt? If that can be done, can someone provide a link or sample code?

Would be a nice ''ST'' Christmas present all wrapped up under the Discovery STM32F4 development board  8--)

Thanks, and best wishes to everyone for a wonderful Christmas break.

Gary

#adc #stm32f4 #sampling-rate
12 REPLIES 12
Posted on December 23, 2014 at 20:33

You can use a TIM to trigger the ADC(s) at a paced rate.

Search on ADC+TIM+DMA, I've posted lots of examples.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on December 23, 2014 at 20:41

Hey, thanks clive1. I will search them through and try what I can find. Will let you know how it goes.

Posted on December 23, 2014 at 20:43

[DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/stm32f207%20ADC%2BTIMER%2BDMA%20%20Poor%20Peripheral%20Library%20Examples&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=3425]https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex_mx_stm32%2Fstm32f207%20ADC%2BTIMER%2BDMA%20%20Poor%20Peripheral%20Library%20Examples&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=3425

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Problem%20with%20ADC%20DMA%20and%20timer&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=2...

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/ADC%20trigger%20on%20timer%20update&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=924

[DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Timer4%20trigger%20for%20ADC&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=2529]https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex_mx_stm32%2FTimer4%20trigger%20for%20ADC&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=2529

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Triggering%20ADC%20Sampling%20by%20Timer%20Events&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=62

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on December 24, 2014 at 19:21

clive1,

Of the samples, I tried this one as it seems the closest applicable solution to what I am trying to achieve:

hello clive 1:

Of the links you posted, the one that seems to be the closest to what I am trying to achieve ends in ''views=924'' It's the third one.

I am using it pretty much verbatim on the Discovery (MB997C) board, and the SystemClock is 168MHz.

However, the LED is toggling at 52.5KHz

Here are the clock and peripheral speeds:

SYSCLK_Frequency = 168000000

HCLK_Frequency = 168000000

PCLK1_Frequency = 42000000

PCLK2_Frequency = 84000000

I tried adjusting the values in  ''TIM2_Configuration'' but the LED always toggles at the same rate.

Can you tell me what might be misconfigured such that the LED is not toggling at 500Hz? It's exactly 105 times faster than it should be.

Thanks!

Rogers.Gary
Senior II
Posted on December 24, 2014 at 19:40

clive1,

Sorry to bother - it's now working. I had some ''straggler'' code from my other code that wasn't commented out.

I'm going to work with this, and may end up with a couple more questions. But this is a very good start. Thanks!

Rogers.Gary
Senior II
Posted on December 24, 2014 at 20:15

clive1,

Instead of asking about both TIMER and ADC, let me ask just about the timer, which is where I am having problems getting to interrupt at the correct rate.

For example, how do I set these:

TIM_TimeBaseStructure.TIM_Period = ?;

TIM_TimeBaseStructure.TIM_Prescaler = ?;

To achieve, let's say, 500Hz interrupt rate, and 1000Hz interrupt rate?

Posted on December 24, 2014 at 21:58

The timer is used to control the sample rate, the interrupt rate from the DMA is then a factor of how many samples the ADC is coded to make at each trigger, and the depth of the buffer. The HT interrupt occurring when half the buffer is full. In cases where the HT/TC interrupt are used we typically double the buffer size so the ping/pong buffers can be accessed without worrying that DMA with taint the content as it continues in the background.

For 1 sample made at 1000 Hz (1 KHz), we have a buffer of 1000 (TC) or 2000 (HT+TC) samples, and the interrupt would get to 1 Hz. How you configure the sample rate, and decimated interrupt rate depends on what your needs are, and expectations for processing, etc.

For the TIM Trigger:

For a counter to have N states, it starts at 0 and counts up to N-1, the counter recognizes the N-1 state and the next state will be 0. The register is thus programed with N-1 rather than N.

TIM Update Frequency = TIM Clock / (P * Q)

Where Prescaler = P - 1, and Period = Q - 1

The base TIM Clock will depend on the AHB divider for the bus to which it's attached.

TIM2 on on APB1, the typical prescaler for that is 4, where the input for the timer is 2. See the Clock Tree diagram for this relationship. Thus the TIM Clock will nominally be 84 MHz (168 MHz / 2)

Therefore to get the time base ticking at 1 MHz, the prescaler needs to be 84 - 1, a period of 1000 - 1 will get the update down to 1 KHz.

Edit: Corrected 1000 KHz reference to 1000 Hz (1 KHz)
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on December 25, 2014 at 02:00

clive1,

Thank you for the detailed explanation. This is much easier to understand in context with the examples. With this information, I can work with the timer interrupt and should be able to figure it out from there. It will also help with the ADC.

You have been a great help with my questions, and as with everyone on this forum, am thankful for your patience and assistance. The STM32 is a complex beast, and to have someone with your depth of understanding is great. Technical manuals are good, but they don't help to see the ''big picture'', where only experience and  knowledge make that happen.

Sincere best wishes for a great Christmas with your family!  8--)

Gary

Rogers.Gary
Senior II
Posted on January 08, 2015 at 18:55

clive1,

All is well, the Timer interrupt and DC/DMA transfer is working.

However, here is an issue I cannot seem to easily resolve. Using the supplied ADC clock dividers, all of the values that the ADC runs at end up as weird sample rates.

To verify the rate I was getting, I set and tested the ADC_SampleTime, which ended up at ADC_SampleTime_480Cycles

I also set the ADC_Prescaler  to ADC_Prescaler_Div8. To test the rate, I had nothing else in the interrupt handler except a toggling LED and verified the sample rate at exactly 10680Hz.

When the interrupt is complete, I then transfer buffers and set a flag: the Timer interrupt runs slightly faster and when the flag is set, can process the buffer. So the question is, I have a buffer of 10680 sample I need to decimate to an even number of base 2 for FFT processing - i.e., 2048 or 4096.

What's the best way to do this?

Thanks!