1
votes

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]));
2
This quote from the CubeMx is definitelly wrong. How 10M requests can be less intensive for the bus matrix than 5M?0___________
I got to this stage but found that the two DMA's had started at different times. I want to use this as dual simultaneous or dual interleaved. However when I do this (and I am setting data length to WORD) I get one data point transferred and the the DMA seems to hang. I have set EOC single conversion in the ADC as well. STM32F446REuser50619

2 Answers

1
votes

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.

1
votes

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);