Skip to main content
TAndr.1
Associate II
April 28, 2020
Question

stm32f407 transfer the same ADC data several times

  • April 28, 2020
  • 8 replies
  • 1539 views

I config ADC with DMA and TIM2. By TIM2 overflow starts ADC process for ADC1 ADC2 and ADC3 simultaneously. DMA collect ADC data and store to RAM. In debug i see that DMA for ADC1 transfer the same ADC data several times.

For example:

ADC1: 32, 32, 32, 32, 32, 32, 32 11, 11, 11, 11, 11

ADC2: 32, 11

ADC3: 32, 11

Problem not with ADC1. I arrange interrupt after end of conversion. It's interrupts by TIM2.

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 if(hadc->Instance==ADC1)
 {
	 memset(arrADC1, 0, ARR_LEN * sizeof(arrADC1[0]));
 __HAL_RCC_ADC1_CLK_ENABLE();
 
 __HAL_RCC_GPIOB_CLK_ENABLE();
 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);
 
 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_MEDIUM;
 hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
 if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
 {
 Error_Handler();
 }
 
 __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
 HAL_ADC_Start_DMA(hadc, (uint32_t *)arrADC1, ARR_LEN);
 }
 else if(hadc->Instance==ADC2)
 {
	 memset(arrADC2, 0, ARR_LEN * sizeof(arrADC1[0]));
 __HAL_RCC_ADC2_CLK_ENABLE();
 
 __HAL_RCC_GPIOC_CLK_ENABLE();
 
 GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 hdma_adc2.Instance = DMA2_Stream2;
 hdma_adc2.Init.Channel = DMA_CHANNEL_1;
 hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY;
 hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE;
 hdma_adc2.Init.MemInc = DMA_MINC_ENABLE;
 hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
 hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
 hdma_adc2.Init.Mode = DMA_CIRCULAR;
 hdma_adc2.Init.Priority = DMA_PRIORITY_HIGH;
 hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
 if (HAL_DMA_Init(&hdma_adc2) != HAL_OK)
 {
 Error_Handler();
 }
 
 __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc2);
 }
 else if(hadc->Instance==ADC3)
 {
	 memset(arrADC3, 0, ARR_LEN * sizeof(arrADC1[0]));
 __HAL_RCC_ADC3_CLK_ENABLE();
 
 __HAL_RCC_GPIOA_CLK_ENABLE();
 
 GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
 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_LOW;
 hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
 if (HAL_DMA_Init(&hdma_adc3) != HAL_OK)
 {
 Error_Handler();
 }
 __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc3);
 HAL_ADC_Start_DMA(hadc, (uint32_t *)arrADC3, ARR_LEN );
 }
}

This topic has been closed for replies.

8 replies

TDK
April 28, 2020

The code you linked does not initialize the ADC channels. This can be done with HAL_ADC_ConfigChannel calls in HAL.

It also doesn't call HAL_ADC_Init which I'm pretty sure is required.

"If you feel a post has answered your question, please click ""Accept as Solution""."
TAndr.1
TAndr.1Author
Associate II
April 28, 2020

All code below

TAndr.1
TAndr.1Author
Associate II
April 28, 2020
static void MX_ADC1_Init(void)
{
 
 /* USER CODE BEGIN ADC1_Init 0 */
 //ADC1->CR1 |= ADC_CR1_EOCIE;
 /* USER CODE END ADC1_Init 0 */
 
 ADC_MultiModeTypeDef multimode = {0};
 ADC_ChannelConfTypeDef sConfig = {0};
 
 /* USER CODE BEGIN ADC1_Init 1 */
 HAL_NVIC_SetPriority(ADC_IRQn, 4, 0);
 HAL_NVIC_EnableIRQ(ADC_IRQn);
 /* USER CODE END ADC1_Init 1 */
 /** 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 = ENABLE;
 hadc1.Init.ContinuousConvMode = DISABLE;
 hadc1.Init.DiscontinuousConvMode = DISABLE;
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
 hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO;
 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc1.Init.NbrOfConversion = 2;
 hadc1.Init.DMAContinuousRequests = ENABLE;
 hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
 if (HAL_ADC_Init(&hadc1) != HAL_OK)
 {
 Error_Handler();
 }
 /** Configure the ADC multi-mode 
 */
 multimode.Mode = ADC_TRIPLEMODE_REGSIMULT;
 multimode.DMAAccessMode = ADC_DMAACCESSMODE_1;
 multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
 if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
 {
 Error_Handler();
 }
 /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
 */
 sConfig.Channel = ADC_CHANNEL_8;
 sConfig.Rank = 1;
 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 
 sConfig.Channel = ADC_CHANNEL_9;
 sConfig.Rank = 2;
 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN ADC1_Init 2 */
 ADC1->CR1 |= ADC_CR1_EOCIE;
 /* USER CODE END ADC1_Init 2 */
 
}
 
/**
 * @brief ADC2 Initialization Function
 * @param None
 * @retval None
 */
static void MX_ADC2_Init(void)
{
 
 /* USER CODE BEGIN ADC2_Init 0 */
 
 /* USER CODE END ADC2_Init 0 */
 
 ADC_ChannelConfTypeDef sConfig = {0};
 
 /* USER CODE BEGIN ADC2_Init 1 */
 
 /* USER CODE END ADC2_Init 1 */
 /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
 */
 hadc2.Instance = ADC2;
 hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
 hadc2.Init.Resolution = ADC_RESOLUTION_12B;
 hadc2.Init.ScanConvMode = ENABLE;
 hadc2.Init.ContinuousConvMode = DISABLE;
 hadc2.Init.DiscontinuousConvMode = DISABLE;
 hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc2.Init.NbrOfConversion = 2;
 hadc2.Init.DMAContinuousRequests = ENABLE;
 hadc2.Init.EOCSelection = ADC_EOC_SEQ_CONV;
 if (HAL_ADC_Init(&hadc2) != HAL_OK)
 {
 Error_Handler();
 }
 /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
 */
 sConfig.Channel = ADC_CHANNEL_11;
 sConfig.Rank = 1;
 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
 if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN ADC2_Init 2 */
 sConfig.Channel = ADC_CHANNEL_12;
	sConfig.Rank =2;
	sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
	if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
	{
	 Error_Handler();
	}
 /* USER CODE END ADC2_Init 2 */
 
}
 
/**
 * @brief ADC3 Initialization Function
 * @param None
 * @retval None
 */
static void MX_ADC3_Init(void)
{
 
 /* USER CODE BEGIN ADC3_Init 0 */
 
 /* USER CODE END ADC3_Init 0 */
 
 ADC_ChannelConfTypeDef sConfig = {0};
 
 /* USER CODE BEGIN ADC3_Init 1 */
 
 /* USER CODE END ADC3_Init 1 */
 /** 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 = ENABLE;
 hadc3.Init.ContinuousConvMode = DISABLE;
 hadc3.Init.DiscontinuousConvMode = DISABLE;
 hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc3.Init.NbrOfConversion = 2;
 hadc3.Init.DMAContinuousRequests = ENABLE;
 hadc3.Init.EOCSelection = ADC_EOC_SEQ_CONV;
 if (HAL_ADC_Init(&hadc3) != HAL_OK)
 {
 Error_Handler();
 }
 /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
 */
 sConfig.Channel = ADC_CHANNEL_1;
 sConfig.Rank = 2;
 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
 if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 
 sConfig.Channel = ADC_CHANNEL_2;
 sConfig.Rank = 1;
 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
 if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
 {
	Error_Handler();
 }
 /* USER CODE BEGIN ADC3_Init 2 */
 
 /* USER CODE END ADC3_Init 2 */
 
}

TAndr.1
TAndr.1Author
Associate II
April 28, 2020
HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc, ADC_ChannelConfTypeDef* sConfig)
{
 __IO uint32_t counter = 0U;
 ADC_Common_TypeDef *tmpADC_Common;
 
 /* Check the parameters */
 assert_param(IS_ADC_CHANNEL(sConfig->Channel));
 assert_param(IS_ADC_REGULAR_RANK(sConfig->Rank));
 assert_param(IS_ADC_SAMPLE_TIME(sConfig->SamplingTime));
 
 /* Process locked */
 __HAL_LOCK(hadc);
 
 /* if ADC_Channel_10 ... ADC_Channel_18 is selected */
 if (sConfig->Channel > ADC_CHANNEL_9)
 {
 /* Clear the old sample time */
 hadc->Instance->SMPR1 &= ~ADC_SMPR1(ADC_SMPR1_SMP10, sConfig->Channel);
 
 /* Set the new sample time */
 hadc->Instance->SMPR1 |= ADC_SMPR1(sConfig->SamplingTime, sConfig->Channel);
 }
 else /* ADC_Channel include in ADC_Channel_[0..9] */
 {
 /* Clear the old sample time */
 hadc->Instance->SMPR2 &= ~ADC_SMPR2(ADC_SMPR2_SMP0, sConfig->Channel);
 
 /* Set the new sample time */
 hadc->Instance->SMPR2 |= ADC_SMPR2(sConfig->SamplingTime, sConfig->Channel);
 }
 
 /* For Rank 1 to 6 */
 if (sConfig->Rank < 7U)
 {
 /* Clear the old SQx bits for the selected rank */
 hadc->Instance->SQR3 &= ~ADC_SQR3_RK(ADC_SQR3_SQ1, sConfig->Rank);
 
 /* Set the SQx bits for the selected rank */
 hadc->Instance->SQR3 |= ADC_SQR3_RK(sConfig->Channel, sConfig->Rank);
 }
 /* For Rank 7 to 12 */
 else if (sConfig->Rank < 13U)
 {
 /* Clear the old SQx bits for the selected rank */
 hadc->Instance->SQR2 &= ~ADC_SQR2_RK(ADC_SQR2_SQ7, sConfig->Rank);
 
 /* Set the SQx bits for the selected rank */
 hadc->Instance->SQR2 |= ADC_SQR2_RK(sConfig->Channel, sConfig->Rank);
 }
 /* For Rank 13 to 16 */
 else
 {
 /* Clear the old SQx bits for the selected rank */
 hadc->Instance->SQR1 &= ~ADC_SQR1_RK(ADC_SQR1_SQ13, sConfig->Rank);
 
 /* Set the SQx bits for the selected rank */
 hadc->Instance->SQR1 |= ADC_SQR1_RK(sConfig->Channel, sConfig->Rank);
 }
 
 /* Pointer to the common control register to which is belonging hadc */
 /* (Depending on STM32F4 product, there may be up to 3 ADCs and 1 common */
 /* control register) */
 tmpADC_Common = ADC_COMMON_REGISTER(hadc);
 
 /* if ADC1 Channel_18 is selected for VBAT Channel ennable VBATE */
 if ((hadc->Instance == ADC1) && (sConfig->Channel == ADC_CHANNEL_VBAT))
 {
 /* Disable the TEMPSENSOR channel in case of using board with multiplixed ADC_CHANNEL_VBAT & ADC_CHANNEL_TEMPSENSOR*/ 
 if ((uint16_t)ADC_CHANNEL_TEMPSENSOR == (uint16_t)ADC_CHANNEL_VBAT)
 {
 tmpADC_Common->CCR &= ~ADC_CCR_TSVREFE;
 }
 /* Enable the VBAT channel*/
 tmpADC_Common->CCR |= ADC_CCR_VBATE;
 }
 
 /* if ADC1 Channel_16 or Channel_18 is selected for Temperature sensor or 
 Channel_17 is selected for VREFINT enable TSVREFE */
 if ((hadc->Instance == ADC1) && ((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) || (sConfig->Channel == ADC_CHANNEL_VREFINT)))
 {
 /* Disable the VBAT channel in case of using board with multiplixed ADC_CHANNEL_VBAT & ADC_CHANNEL_TEMPSENSOR*/
 if ((uint16_t)ADC_CHANNEL_TEMPSENSOR == (uint16_t)ADC_CHANNEL_VBAT)
 {
 tmpADC_Common->CCR &= ~ADC_CCR_VBATE;
 }
 /* Enable the Temperature sensor and VREFINT channel*/
 tmpADC_Common->CCR |= ADC_CCR_TSVREFE;
 
 if((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR))
 {
 /* Delay for temperature sensor stabilization time */
 /* Compute number of CPU cycles to wait for */
 counter = (ADC_TEMPSENSOR_DELAY_US * (SystemCoreClock / 1000000U));
 while(counter != 0U)
 {
 counter--;
 }
 }
 }
 
 /* Process unlocked */
 __HAL_UNLOCK(hadc);
 
 /* Return function status */
 return HAL_OK;
}

TAndr.1
TAndr.1Author
Associate II
April 28, 2020

I use 3 DMA stream and 3 data buffer. In debug all stream DMA registers are similar. But data buffer for master ADC1 filled by repeated data.

TAndr.1
TAndr.1Author
Associate II
April 28, 2020

On picture - in arrADC3 - data from two adc channels. It OK. But in arrADC1 - repeated data from only one channel!0693W000000Wb07QAC.png

waclawek.jan
Super User
April 28, 2020

Read out and post content of ADC and DMA registers.

JW

TAndr.1
TAndr.1Author
Associate II
April 28, 2020

0693W000000WcUSQA0.png0693W000000WcUNQA0.png0693W000000WcUIQA0.png0693W000000WcUDQA0.png