2015-01-26 02:58 AM
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
2018-07-31 10:57 AM
Is there a solution to this question?
2018-07-31 12:26 PM
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.
2019-02-20 07:55 AM
Hi Clive,
If I use DMA with injected channels will it work?
2019-02-20 08:22 AM
Each Injected channels have its own DR. And you can trigger a sweep conversion from a timer then get a callback. Neat.
2019-02-20 08:28 AM
Can you please elaborate?
2019-02-20 09:24 AM
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.
2019-02-20 10:18 AM
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
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