Bohdan Pakhaliuk
Bohdan Pakhaliuk

Reputation: 139

Usage of two DMA ADC channels in dual regular simultaneous mode STM32

I want to implement dual regular simultaneous mode of ADC1,ADC2 and two DMA ADC channels of stm32f303 discovery.

In CubeMX examples:

Usage of two DMA channels (one for ADC master, one for ADC slave) is also possible: this is the recommended configuration in case of high ADC conversions rates and applications using other DMA channels intensively.

According to AN4195

When using the DMA, there are two possible cases: • Use of two separate DMA channels for master and slave. Each ADC (in this case, the MDMA[1:0]) must be kept cleared. The first DMA channel is used to read the master ADC converted data from ADC_DR, and the DMA requests are generated at each EOC event of the master ADC. The second DMA channel is used to read the slave ADC converted data from ADC_DR, and the DMA requests are generated at each EOC event of the slave ADC.

For 1 channel the code:

HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
HAL_ADCEx_Calibration_Start(&hadc2, ADC_SINGLE_ENDED);
HAL_ADC_Start(&hadc2);
HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*)buffer, 3);

But how can we run 2 channels? HAL_ADCEx_MultiModeStart_DMA is for 1 channel as I can understand

Something like for independent mode is not working

HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
HAL_ADCEx_Calibration_Start(&hadc2, ADC_SINGLE_ENDED);

HAL_ADC_Start(&hadc2);

HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC1_data,sizeof(ADC1_data)/sizeof(ADC1_data[0]));  
HAL_ADC_Start_DMA(&hadc2,(uint32_t*)ADC2_data,sizeof(ADC2_data)/sizeof(ADC2_data[0]));

Upvotes: 2

Views: 8380

Answers (2)

0___________
0___________

Reputation: 67476

Funny - great HAL library :). This is my working code: interleaved mode - one DMA transfer half word per two conversions (master and slave). 8-bit resolution. Register version.

DMA1_Channel1 -> CPAR = (uint32_t)&(ADC12_COMMON -> CDR);
DMA1_Channel1 -> CMAR = (uint32_t)&obuff[0][0];
DMA1_Channel1 -> CNDTR = 1 * 1024;
DMA1_Channel1 -> CCR = DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_EN | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_TEIE | (DMA_CCR_PL_Msk);

ADC12_COMMON -> CCR = (0b11 << ADC12_CCR_MDMA_Pos) | (0b111 << ADC12_CCR_MULTI_Pos);

ADC1 -> CFGR = ADC_CFGR_DMAEN | (0b10 << ADC_CFGR_RES_Pos);
ADC1 -> CFGR &= ~(ADC_CFGR_EXTEN_Msk | ADC_CFGR_EXTSEL_Msk);  // software trigger only, converting as fast as possible
ADC1 -> CFGR |= ADC_CFGR_CONT;
ADC1 -> SMPR1 = 0;
ADC1 -> SMPR2 = 0;

ADC1 -> SQR1 &= ~(ADC_SQR1_L_Msk);
ADC1 -> SQR1 &= ~(ADC_SQR1_SQ1_Msk);
ADC1 -> SQR1 |= (1 << ADC_SQR1_SQ1_Pos);

ADC2 -> CFGR = ADC_CFGR_DMAEN | (0b10 << ADC_CFGR_RES_Pos);
ADC2 -> SMPR1 = 0;
ADC2 -> SMPR2 = 0;

ADC2 -> SQR1 &= ~(ADC_SQR1_L_Msk);
ADC2 -> SQR1 &= ~(ADC_SQR1_SQ1_Msk);
ADC2 -> SQR1 |= (1 << ADC_SQR1_SQ1_Pos);
ADC1 -> CR |= ADC_CR_ADSTART;

DMA1_Channel1 interrupt is called when DMA finishes transfers.

Upvotes: 2

user14719940
user14719940

Reputation: 21

I'm not 100% sure, if this also applies to the F3 series, but I've written this toturial for the F103C8 regarding ADC dual regular simultanous mode: http://www.bepat.de/2020/11/27/stm32f103c8-adc-dual-regular-simultaneous-mode/ maybe you'll find it helpfull.

To cut a long story short: I guess you are starting the ADCs the wrong way. ADC2 needs to be started in normal mode BEFORE ADC1 starts with

HAL_ADC_Start(&hadc2);

ADC1 is started afterwards with:

HAL_ADCEx_MultiModeStart_DMA(&hadc1, ADC_Buffer, ADC_BufferSize);

Upvotes: 2

Related Questions