cancel
Showing results for 
Search instead for 
Did you mean: 

reading multiple adc channels, no dma

Sietse
Associate III
Posted on January 26, 2015 at 11:58

Hello List,

I,m struggling with reading, without DMA, from multiple channels. Every, say, 10 msec I call:

var1 = Get_ADC_Value(11);
var2 = Get_ADC_Value(12);

Both variables ALWAYS get the same value, that is the value from the first called channel, here The function (partly) is:

int16_t Get_ADC_Value(uint8_t Channel)
{
uint16_t ADC_Val; //Stores the calculated ADC value
switch(Channel)
{
case 11:
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_84Cycles);
ADC_SoftwareStartConv(ADC1);
while(ADC_GetSoftwareStartConvStatus(ADC1) != RESET){ADC_Val = 0;}
ADC_Val = ADC_GetConversionValue(ADC1);
break;
case 12:
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_84Cycles);
ADC_SoftwareStartConv(ADC1);
while(ADC_GetSoftwareStartConvStatus(ADC1) != RESET){ADC_Val = 0;}
ADC_Val = ADC_GetConversionValue(ADC1);
break;
.... other channels

The configuration:

void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure ADC Channel 11, 12, 15, and 14 as analog input */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_5 | GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* ADC Common configuration *************************************************/
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);
/* ADC1 regular channel 10 to 15 configuration ************************************/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Init(ADC2, &ADC_InitStructure);
/* Enable ADC1 to ADC3*/
ADC_Cmd(ADC1, ENABLE);
ADC_Cmd(ADC2, ENABLE);
}

Clocks are also enabled. All in all completely standard, but .... Hopefully someone can help me. Thanks in advance, Sietse #stm32f4-adc-multichannel
7 REPLIES 7
Soumya Subramanya
Associate II

Is there a solution to this question?

Yes, use DMA, or use Multiple ADC, perhaps injected channels.

Perhaps change your paradigm to fit how the hardware works most efficiently as apposed to methods that worked well for 8051 designs.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Hi Clive,

If I use DMA with injected channels will it work?

S.Ma
Principal

Each Injected channels have its own DR. And you can trigger a sweep conversion from a timer then get a callback. Neat.

Can you please elaborate?

Possibly, it's not a solution I'm invested in.

The normal DMA mode is to keep reading from the same peripheral registers, so not sure how well reading from multiple registers will work for you.

Why can't you just use the regular ADC+DMA arrangement? If you want two samples taken at the same instant, bond a pair of ADC resources.

Just open your mind to possible ways to use the hardware, and not be trapped in the old mindset of "Start ADC, wait for EOC, rinse and repeat"

Use DMA and IRQ to process data when everything is already ready to act on, use deeper buffers to decimate the IRQ loading.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
S.Ma
Principal

Get a Timer generate a pulse every 10 msec, feed this signal to the injected ADC channel trigger pin (say the falling edge kick the conversions):

Use this to kick a sequential conversion on the chosen injected channels.

Get an interrupt when the sequence is completed.

Eg: Ref Man STM32L4R5:

Conversion modes

  • The ADC can convert a single channel or can scan a sequence of channels

Interrupt generation at ADC ready, the end of sampling, the end of conversion (regular

or injected), end of sequence conversion (regular or injected), analog watchdog 1, 2 or

3 or overrun events

  • Data can be routed to DFSDM for post processing
  • 4 dedicated data registers for the injected channels
  • input events) for both regular and injected conversions