Skip to main content
Visitor II
April 28, 2020
Question

stm32f407 transfer the same ADC data several times

  • April 28, 2020
  • 7 replies
  • 1505 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.

    7 replies

    Super User
    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.

    TAndr.1Author
    Visitor II
    April 28, 2020

    All code below

    TAndr.1Author
    Visitor 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.1Author
    Visitor 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.1Author
    Visitor 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.1Author
    Visitor 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

    Super User
    April 28, 2020

    Read out and post content of ADC and DMA registers.

    JW

    TAndr.1Author
    Visitor II
    April 28, 2020

    0693W000000WcUSQA0.png0693W000000WcUNQA0.png0693W000000WcUIQA0.png0693W000000WcUDQA0.png