STM32F4: How to get data from multiple channels sampled from a single ADC?
This should be a comment to ask you if you want my solution, which includes 3 ADCs x 3 Channels = 9 signals, by utilizing DMA peripheral and no HAL libraries. Since my rep is &lt; 50, I cannot make that comment, so I will provide the code for the above :P

It utilizes a Master-Slave technique, with ADC1 set as the master and ADC2 and 3 as slaves. Interrupts occur based on TIM2 frequency, which can be modified.

Hope it helps :)



μC Board: STM32F429ZI-Discovery

IDE: μVision V5.13.0.0



TIM2 Enable

#define ADC_PER 4499

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

TIM_BaseStruct_ST.TIM_Prescaler = 0;
TIM_BaseStruct_ST.TIM_CounterMode = TIM_CounterMode_Up;
// 899 =&gt; 100kHz, 2249 =&gt; 40kHz, 4499 =&gt; 20kHz, 8999 =&gt; 10kHz
TIM_BaseStruct_ST.TIM_Period = ADC_PER; 
TIM_BaseStruct_ST.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseInit(TIM2, &amp;TIM_BaseStruct_ST);
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);


ADC Clock Enable

#include "stm32f4xx_adc.h"
RCC_APB2PeriphClockCmd (RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd (RCC_APB2Periph_ADC2, ENABLE);
RCC_APB2PeriphClockCmd (RCC_APB2Periph_ADC3, ENABLE);


ADC set to Triple Mode, DMA Enable, No Prescaler

ADC_CommonInitTypeDef ADC_CommonInitStructure;

ADC_CommonInitStructure.ADC_Mode          = ADC_TripleMode_RegSimult;
ADC_CommonInitStructure.ADC_Prescaler     = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;
ADC_CommonInit (&amp;ADC_CommonInitStructure);


3 conversions for each ADC, hence 9 in total.
Highest resolution of 12 bits, right data alignment and event trigger by TIM2 interrupts.

ADC_InitTypeDef ADC_InitStructure;

ADC_InitStructure.ADC_ScanConvMode       = ENABLE;
ADC_InitStructure.ADC_NbrOfConversion    = 3;
ADC_InitStructure.ADC_Resolution         = ADC_Resolution_12b;
ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

TIM_SelectOutputTrigger (TIM2, TIM_TRGOSource_Update);
ADC_InitStructure.ADC_ExternalTrigConv     = ADC_ExternalTrigConv_T2_TRGO;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;

ADC_Init(ADC1, &amp;ADC_InitStructure);
ADC_Init(ADC2, &amp;ADC_InitStructure);
ADC_Init(ADC3, &amp;ADC_InitStructure);


Set each channel to the right pin, with 15 cycles for sampling the signal

ADC_RegularChannelConfig (ADC1, ADC_Channel_13, 1, ADC_SampleTime_15Cycles);
ADC_RegularChannelConfig (ADC1, ADC_Channel_8,  2, ADC_SampleTime_15Cycles);
ADC_RegularChannelConfig (ADC1, ADC_Channel_6,  3, ADC_SampleTime_15Cycles);

ADC_RegularChannelConfig (ADC2, ADC_Channel_0,  1, ADC_SampleTime_15Cycles);
ADC_RegularChannelConfig (ADC2, ADC_Channel_10, 2, ADC_SampleTime_15Cycles);
ADC_RegularChannelConfig (ADC2, ADC_Channel_14, 3, ADC_SampleTime_15Cycles);

ADC_RegularChannelConfig (ADC3, ADC_Channel_15, 1, ADC_SampleTime_15Cycles);
ADC_RegularChannelConfig (ADC3, ADC_Channel_9,  2, ADC_SampleTime_15Cycles);
ADC_RegularChannelConfig (ADC3, ADC_Channel_3,  3, ADC_SampleTime_15Cycles);


DMA Clock Enable.

Setup DMA data transport, base address, matrix size, half word data transfer and circular mode.

Enable Stream4 of DMA2.

#include "stm32f4xx_dma.h"
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

DMA_InitTypeDef DMA_InitStructure;

DMA_InitStructure.DMA_DIR     = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_Channel = DMA_Channel_0;

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&amp;ADC-&gt;CDR;
DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_Memory0BaseAddr    = (uint32_t)(&amp;adc[0]);
DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_BufferSize = 9;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_Init(DMA2_Stream4, &amp;DMA_InitStructure)


Setup and enable interrupt event of DMA

NVIC_InitTypeDef ADCNVICConfig;
ADCNVICConfig.NVIC_IRQChannel = DMA2_Stream4_IRQn;
ADCNVICConfig.NVIC_IRQChannelPreemptionPriority = 0;
ADCNVICConfig.NVIC_IRQChannelSubPriority = 1;
ADCNVICConfig.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&amp;ADCNVICConfig);

ADC_DMACmd(ADC1, ENABLE);
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
DMA_ITConfig(DMA2_Stream4, DMA_IT_TC, ENABLE);

DMA_Cmd(DMA2_Stream4, ENABLE); 


Setup ADC1 as Master and ADC2 and ADC3 as Slaves, enable DMA and all ADCs.

ADC_DMACmd(ADC1, ENABLE);
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);

ADC_Cmd(ADC1, ENABLE);
ADC_Cmd(ADC2, ENABLE);
ADC_Cmd(ADC3, ENABLE);