cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H750VBT6 ADC 4 channels using DMA

Zain
Associate III

I am using stm32h750vbt6 for 4 channels adc conversion using dma, unable to do so. I have done it in stm32f407 but couldn't implement in this controller. The buffer that ive assigned to dma always says zero. I am using stm32cubemx to generate code and stm32cubeide for compiling the code. Any help would be appreciated, i am stuck here for a day now. Thanks

7 REPLIES 7
FBL
ST Employee

Hello @Zain​,

Could you please share your ADC configuration, your DMA streams configuration?

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.


I'm out of offce with limited access to my emails.
Happy New Year!
Zain
Associate III

static void MX_ADC1_Init(void)

{

 /* USER CODE BEGIN ADC1_Init 0 */

 /* USER CODE END ADC1_Init 0 */

 ADC_MultiModeTypeDef multimode = {0};

 ADC_ChannelConfTypeDef sConfig = {0};

 /* USER CODE BEGIN ADC1_Init 1 */

 /* USER CODE END ADC1_Init 1 */

 /** Common config

 */

 hadc1.Instance = ADC1;

 hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;

 hadc1.Init.Resolution = ADC_RESOLUTION_16B;

 hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;

 hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

 hadc1.Init.LowPowerAutoWait = DISABLE;

 hadc1.Init.ContinuousConvMode = ENABLE;

 hadc1.Init.NbrOfConversion = 1;

 hadc1.Init.DiscontinuousConvMode = DISABLE;

 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;

 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

 hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;

 hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;

 hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;

 hadc1.Init.OversamplingMode = DISABLE;

 if (HAL_ADC_Init(&hadc1) != HAL_OK)

 {

  Error_Handler();

 }

 /** Configure the ADC multi-mode

 */

 multimode.Mode = ADC_MODE_INDEPENDENT;

 if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)

 {

  Error_Handler();

 }

 /** Configure Regular Channel

 */

 sConfig.Channel = ADC_CHANNEL_18;

 sConfig.Rank = ADC_REGULAR_RANK_1;

 sConfig.SamplingTime = ADC_SAMPLETIME_64CYCLES_5;

 sConfig.SingleDiff = ADC_SINGLE_ENDED;

 sConfig.OffsetNumber = ADC_OFFSET_NONE;

 sConfig.Offset = 0;

 sConfig.OffsetSignedSaturation = DISABLE;

 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

 {

  Error_Handler();

 }

 /* USER CODE BEGIN ADC1_Init 2 */

 /* USER CODE END ADC1_Init 2 */

}

static void MX_DMA_Init(void)

{

 /* DMA controller clock enable */

 __HAL_RCC_DMA1_CLK_ENABLE();

 /* DMA interrupt init */

 /* DMA1_Stream0_IRQn interrupt configuration */

 HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);

 HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);

}

Zain
Associate III

@F.Belaid​ 

TDK
Guru

And the rest of the code?

Are the buffers in DMA-accessible space? Check DMA error flags, check software state machine status.

If you feel a post has answered your question, please click "Accept as Solution".
Zain
Associate III

{

HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adcout, ADCLENGTH);

}

HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_t Length)

{

 HAL_StatusTypeDef tmp_hal_status;

 uint32_t tmp_multimode_config = LL_ADC_GetMultimode(__LL_ADC_COMMON_INSTANCE(hadc->Instance));

 /* Check the parameters */

 assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));

 /* Perform ADC enable and conversion start if no conversion is on going */

 if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)

 {

  /* Process locked */

  __HAL_LOCK(hadc);

  /* Ensure that multimode regular conversions are not enabled.  */

  /* Otherwise, dedicated API HAL_ADCEx_MultiModeStart_DMA() must be used. */

  if ((tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)

    || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_SIMULT)

    || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_ALTERN)

    )

  {

   /* Enable the ADC peripheral */

   tmp_hal_status = ADC_Enable(hadc);

   /* Start conversion if ADC is effectively enabled */

   if (tmp_hal_status == HAL_OK)

   {

    /* Set ADC state                            */

    /* - Clear state bitfield related to regular group conversion results  */

    /* - Set state bitfield related to regular operation          */

    ADC_STATE_CLR_SET(hadc->State,

             HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR | HAL_ADC_STATE_REG_EOSMP,

             HAL_ADC_STATE_REG_BUSY);

    /* Reset HAL_ADC_STATE_MULTIMODE_SLAVE bit

     - if ADC instance is master or if multimode feature is not available

     - if multimode setting is disabled (ADC instance slave in independent mode) */

    if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)

      || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)

      )

    {

     CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);

    }

    /* Check if a conversion is on going on ADC group injected */

    if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) != 0UL)

    {

     /* Reset ADC error code fields related to regular conversions only */

     CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));

    }

    else

    {

     /* Reset all ADC error code fields */

     ADC_CLEAR_ERRORCODE(hadc);

    }

    /* Set the DMA transfer complete callback */

    hadc->DMA_Handle->XferCpltCallback = ADC_DMAConvCplt;

    /* Set the DMA half transfer complete callback */

    hadc->DMA_Handle->XferHalfCpltCallback = ADC_DMAHalfConvCplt;

    /* Set the DMA error callback */

    hadc->DMA_Handle->XferErrorCallback = ADC_DMAError;

    /* Manage ADC and DMA start: ADC overrun interruption, DMA start,   */

    /* ADC start (in case of SW start):                  */

    /* Clear regular group conversion flag and overrun flag        */

    /* (To ensure of no unknown state from potential previous ADC     */

    /* operations)                            */

    __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS | ADC_FLAG_OVR));

    /* Process unlocked */

    /* Unlock before starting ADC conversions: in case of potential     */

    /* interruption, to let the process to ADC IRQ Handler.         */

    __HAL_UNLOCK(hadc);

    /* With DMA, overrun event is always considered as an error even if

      hadc->Init.Overrun is set to ADC_OVR_DATA_OVERWRITTEN. Therefore,

      ADC_IT_OVR is enabled. */

    __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR);

    /* Enable ADC DMA mode*/

#if defined(ADC_VER_V5_V90)

    if (hadc->Instance == ADC3)

    {

     LL_ADC_REG_SetDMATransferMode(hadc->Instance, ADC3_CFGR_DMACONTREQ((uint32_t)hadc->Init.DMAContinuousRequests));

     LL_ADC_EnableDMAReq(hadc->Instance);

    }

    else

    {

     LL_ADC_REG_SetDataTransferMode(hadc->Instance, ADC_CFGR_DMACONTREQ((uint32_t)hadc->Init.ConversionDataManagement));

    }

#else

    LL_ADC_REG_SetDataTransferMode(hadc->Instance, (uint32_t)hadc->Init.ConversionDataManagement);

#endif

    /* Start the DMA channel */

    tmp_hal_status = HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData, Length);

    /* Enable conversion of regular group.                 */

    /* If software start has been selected, conversion starts immediately. */

    /* If external trigger has been selected, conversion will start at next */

    /* trigger event.                            */

    /* Start ADC group regular conversion */

    LL_ADC_REG_StartConversion(hadc->Instance);

   }

   else

   {

    /* Process unlocked */

    __HAL_UNLOCK(hadc);

   }

  }

  else

  {

   tmp_hal_status = HAL_ERROR;

   /* Process unlocked */

   __HAL_UNLOCK(hadc);

  }

 }

 else

 {

  tmp_hal_status = HAL_BUSY;

 }

 /* Return function status */

 return tmp_hal_status;

}

/**

 * @brief Stop ADC conversion of regular group (and injected group in

 *     case of auto_injection mode), disable ADC DMA transfer, disable

 *     ADC peripheral.

 * @note: ADC peripheral disable is forcing stop of potential

 *     conversion on ADC group injected. If ADC group injected is under use, it

 *     should be preliminarily stopped using HAL_ADCEx_InjectedStop function.

 * @note  Case of multimode enabled (when multimode feature is available):

 *     HAL_ADC_Stop_DMA() function is dedicated to single-ADC mode only.

 *     For multimode, the dedicated HAL_ADCEx_MultiModeStop_DMA() API must be used.

 * @param hadc ADC handle

 * @retval HAL status.

 */

S.Ma
Principal

Well, H7 is beyond a typical MCU like the F4 or L4, with more complex features, demanding veteran coders... so doing things requiree more efforts to get done.

Zain
Associate III

Okie so i was able to solve the problem as i increased the sampling time to 870 something, now i don't know why it needed that much time for 16Bit conversion.