cancel
Showing results for 
Search instead for 
Did you mean: 

Question about continuous sampling of multiple ADC channels

sjenyart
Associate II
Posted on October 01, 2012 at 21:54

I would like to continuously sample multiple (~5) channels, preferably with no CPU triggering after the initial setup.  I had been thinking that we would just set up a continuous regular group and then pass back pointers to the the data registers and/or copy the conversions back in the IRQs on a per-channel basis for provision to the application on demand.

However, browsing the docs, my understanding is that all channels in the regular channel group will write their conversions to the same data register meaning that each channel will overwrite the previous channel's conversion and an EOC will occur with only the last regular channel in the SQR having data stored.

I am new to ARMs but this seems odd to me. I would expect to have a data register for each channel or perhaps a queued DR buffer. Am I missing something?

It looks like the best option, given what I would like to do, will be to set up only a single channel in the regular group and then chain up to 4 injected channels to that EOC by  setting CONT and JAUTO (Auto-injection, since the injected group has a DR for each channel in the group).

Any thoughts?

#adc
13 REPLIES 13
sjenyart
Associate II
Posted on October 01, 2012 at 21:56

Sorry for the double post.  Got an error page after the first submission.

Posted on October 01, 2012 at 22:10

Any thoughts?

You'll want to be using DMA for multiple ADC channels. Set up a circular buffer big enough to hold the channels, or perhaps multiple instances, and use the TC and HT DMA interrupts to process the values.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sjenyart
Associate II
Posted on October 04, 2012 at 22:13

Perfect.  Had not considered that I would have to use the DMA for this but I see that section 10.8.1 indicates as much.

Followup question.  I have sequenced the ADC channels, populated the L bits with the number of conversions, and set up the DMA transfer and NDTR but only the first transfer is occuring.  If I place the ADC in CONT mode, the correct number of transfers occur but only the first channel's conversions are transferring.  That is, I get three values from the first channel in my sequence but none from the other two.  If your experience with the peripherals in question trigger any comment on this, I'd appreciate it.

Thanks very much.

Side note, I believe there are two typos in 10.8.1 :

1) Not really a typo, but a clarity issue, first sentence: ''Since converted regular channel values are stored into a unique data register, it is useful to use DMA for conversion of more than one regular channel. This avoids the loss of the data already stored in the ADC_DR register.''  Makes it sound like each channel has a ''unique'' DR- ''shared'' or ''common'' might be a better word choice.

2) ''DMA_SxRTR'' is not a register.

sjenyart
Associate II
Posted on October 04, 2012 at 22:58

Actually, I figured out my issue here.  I needed to do this in scan mode, rather than continuous.

Thanks for the help.

terence-b
Associate II
Posted on December 12, 2012 at 10:20

Hi,

I also need to have two ADC channels to be converted. Currently, I already have one channel

which is being converted pretty fine. Now I need another one.

I am using DMA2 channel 2 to continuously convert ADC3 channel 12 in DMA circular mode.

My presently converted value is set to the memory base address as follows:

DMA_InitStructure.DMA_Memory0BaseAddr = &main_ADC3ConvertedValue_ui16

Can you please help on how I shall go about this i.e. to have also another channel converted.

Best regards,

Terence 

Posted on December 12, 2012 at 13:39

Make a bigger buffer (array) into which to store your multiple measurements, increase the DMA transfer size to reflect this, and program the multiple ADC channels, and ordering, into the ADC.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
terence-b
Associate II
Posted on December 17, 2012 at 08:09

Can you please me more clear? 

Before I was only using ADC3 channel 12 in conjunction with DMA2 Stream 0, and it was working fine.

Lately, I tried to configure ADC3 channel 13 in conjunction with DMA2 Stream1 (since DMA2 Stream 0 & Stream 1 are connected with ADC3). This is now affecting the other ADC channel i.e. the other channel is not working correctly any more (keeps reading 0).

Thanks,

Terence 

Posted on December 17, 2012 at 15:55

Why would you need two DMA channels/streams? Is it architecturally possible from a single ADC?

What I described earlier would presumably look like this:

__IO uint16_t ADC3ConvertedValues[2]; // << TWO VALUE, ONE FOR EACH CHANNEL
// ..
void ADC3_DMA_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable ADC3, DMA2 and GPIO clocks ****************************************/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
/* DMA2 Stream0 channel0 configuration **************************************/
DMA_InitStructure.DMA_Channel = DMA_Channel_2;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValues[0]; // << AN ARRAY WITH TWO VALUES
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 2; // << TWO VALUES
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
DMA_Cmd(DMA2_Stream0, ENABLE);
/* Configure ADC3 Channel12 (PC2) & 13 (PC3) pin as analog input ******************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* ADC Common Init **********************************************************/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC3 Init ****************************************************************/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 2; // << SO TWO CHANNELS
ADC_Init(ADC3, &ADC_InitStructure);
// DEFINE TWO CHANNELS WITH RANK#
/* ADC3 regular channel12 configuration *************************************/
ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 1, ADC_SampleTime_56Cycles);
/* ADC3 regular channel13 configuration *************************************/
ADC_RegularChannelConfig(ADC3, ADC_Channel_13, 2, ADC_SampleTime_56Cycles);
/* Enable DMA request after last transfer */
ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);
/* Enable ADC3 DMA */
ADC_DMACmd(ADC3, ENABLE);
/* Enable ADC3 */
ADC_Cmd(ADC3, ENABLE);
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
terence-b
Associate II
Posted on December 18, 2012 at 07:38

Thanks a lot for your reply. I now realised that this forum section is for the F3. But I'm using the F4.