AnsweredAssumed Answered

STM32F7 ADC/DMA in DUALMODE

Question asked by Labrado.Jeremy on Dec 30, 2016
Latest reply on Jan 5, 2017 by Keaven

Hi,

I am trying to get the value from the ADC1 and ADC3 simultaneously. I am using the HAL API generated by the STM32Cube.

I have configure the ADC1 and ADC3 in Dual Mode Regular Simyltaneous. Measurement are triggered by Timer 6.

 

I know that the two ADC1 and ADC3 works, I was able to read them independently using the HAL_ADC_Start_DMA(&hadc1,  (uint32_t*)adc1Array, 2) method.

 

I have insert breakpoint on all the IRQ handler and it never stop. It looks like the issue is on the DMA but I cannot solve it.

 

I have search on the internet for the past few days without success. All the question on the community.st.com remain unsolved and i cannot find any example using the HAL with my configuration.

Has anyone got this mode to work using the HAL?

There is some of the relevant code below:

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

uint32_t adc1Array[1024];

 

int main(void)
{

// MCU Configuration----------------------------------------------------------

// Reset of all peripherals, Initializes the Flash interface and the Systick.
HAL_Init();

// Configure the system clock
SystemClock_Config();

// Initialize all configured peripherals
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_ADC3_Init();
MX_DAC_Init();
MX_SPI1_Init();
MX_TIM6_Init();
MX_TIM7_Init();


HAL_TIM_Base_Start(&htim6);

 

 

HAL_ADC_Start(&hadc3);
HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*)adc1Array, 2);


// Infinite loop
while (1)
   {
   HAL_Delay(100);

   }

} /* End of function main() ------------------------------------------------ */

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc3;
DMA_HandleTypeDef hdma_adc1;
DMA_HandleTypeDef hdma_adc3;

ADC_MultiModeTypeDef multimode;

 


/* ADC1 init function */
void MX_ADC1_Init(void)
{

ADC_ChannelConfTypeDef sConfig;
//ADC_MultiModeTypeDef multimode;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 0;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T6_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1; 
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = EOC_SINGLE_CONV;

HAL_ADC_Init(&hadc1);


/**Configure the ADC multi-mode
*/
multimode.Mode = ADC_DUALMODE_REGSIMULT;
multimode.DMAAccessMode = ADC_DMAACCESSMODE_1;
multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_20CYCLES;

HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode);



/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_5;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;

HAL_ADC_ConfigChannel(&hadc1, &sConfig) ;



} /* end of MX_ADC1_Init() ================================================ */

 

 

/* ADC3 init function */
void MX_ADC3_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
//ADC_MultiModeTypeDef multimode;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc3.Instance = ADC3;
hadc3.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc3.Init.Resolution = ADC_RESOLUTION_12B;
hadc3.Init.ScanConvMode = DISABLE;
hadc3.Init.ContinuousConvMode = ENABLE;
hadc3.Init.DiscontinuousConvMode = DISABLE;
hadc3.Init.NbrOfDiscConversion = 0;
hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc3.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T6_TRGO;
hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc3.Init.NbrOfConversion = 1; 
hadc3.Init.DMAContinuousRequests = ENABLE;
hadc3.Init.EOCSelection = EOC_SINGLE_CONV;

HAL_ADC_Init(&hadc3);

/**Configure the ADC multi-mode
*/
multimode.Mode = ADC_DUALMODE_REGSIMULT;
multimode.DMAAccessMode = ADC_DMAACCESSMODE_1;
multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;

HAL_ADCEx_MultiModeConfigChannel(&hadc3, &multimode);

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_4;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;

HAL_ADC_ConfigChannel(&hadc3, &sConfig);

} /* end of MX_ADC3_Init() ================================================ */

 

 

 


/**
* @brief ADC MSP Initialization
* This function configures the hardware resources used in this example:
* - Peripheral's clock enable
* - Peripheral's GPIO Configuration
* @param hadc: ADC handle pointer
* @retval None
*/
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{

GPIO_InitTypeDef GPIO_InitStruct;

if(adcHandle->Instance==ADC1)
{

// Peripheral clock enable
__HAL_RCC_ADC1_CLK_ENABLE();

GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

// Peripheral DMA init

hdma_adc1.Instance = DMA2_Stream0;
hdma_adc1.Init.Channel = DMA_CHANNEL_0;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_adc1.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
hdma_adc1.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_adc1.Init.PeriphBurst = DMA_PBURST_SINGLE;

HAL_DMA_Init(&hdma_adc1);

__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);

}

else if(adcHandle->Instance==ADC3)
{
// Peripheral clock enable
__HAL_RCC_ADC3_CLK_ENABLE();

GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6
|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

// Peripheral DMA init

hdma_adc3.Instance = DMA2_Stream1;
hdma_adc3.Init.Channel = DMA_CHANNEL_2;
hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc3.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc3.Init.Mode = DMA_CIRCULAR;
hdma_adc3.Init.Priority = DMA_PRIORITY_HIGH;
hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_adc3.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
hdma_adc3.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_adc3.Init.PeriphBurst = DMA_PBURST_SINGLE;

HAL_DMA_Init(&hdma_adc3);

__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc3);

}

HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC_IRQn);

HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0 , 0 );
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);

HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0 , 0 );
HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);

} /* end of HAL_ADC_MspInit() ============================================== */

 

 


void ADC_IRQHandler()
{
HAL_ADC_IRQHandler(&hadc3);
 HAL_ADC_IRQHandler(&hadc1);

} /* end of ADC_IRQHandler() ============================================== */

 

 

 

void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();

/* DMA interrupt init */
/* DMA1_Stream5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
/* DMA2_Stream1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);

}

 

 

/**
* @brief This function handles DMA2 stream0 global interrupt.
*/
void DMA2_Stream0_IRQHandler(void)
{

HAL_DMA_IRQHandler(hadc1.DMA_Handle);

}

Outcomes