Skip to main content
Visitor II
May 13, 2022
Question

STM32H750 ADC+DMA Continuous mode PC2_C and PC3_C sampling data is unstable

  • May 13, 2022
  • 3 replies
  • 1933 views

I'm having some ADC+DMA sampling problems with the H750.  

When the ADC+DMA is working, in continuous mode, PC2_C(ADC3_CH0) gets 16bit sampling data which is unstable and constantly jumps between 10000+ and 30000+. I guess there is a problem with the code configuration.  

However, the channel PF9(ADC3_CH2) with the same configuration is very stable with only a very small fluctuation.  

The ADC clock frequency is 10Mhz.

I checked the errata but could not find a solution.  

In HW, both VDDA and Vref+ have a pair of decoupling capacitors near H750, and each ADC channel also has a low-pass filter. 

The following is the sample data of PC2_C

0693W00000Npv4xQAB.png 

bsp_adc.c

#include "bsp_adc.h"
 
ADC_HandleTypeDef hadc3;
DMA_HandleTypeDef hdma_adc3;
 
 
/* ADC3 init function */
void MX_ADC3_Init(void)
{
 ADC_ChannelConfTypeDef sConfig = {0};
 
 /** Common config 
 */
 hadc3.Instance = ADC3;
 hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16;
 hadc3.Init.Resolution = ADC_RESOLUTION_16B;
 hadc3.Init.ScanConvMode = ADC_SCAN_ENABLE;
 hadc3.Init.EOCSelection = ADC_EOC_SEQ_CONV;
 hadc3.Init.LowPowerAutoWait = DISABLE;
 hadc3.Init.ContinuousConvMode = ENABLE;
 hadc3.Init.NbrOfConversion = 6;
 hadc3.Init.DiscontinuousConvMode = DISABLE;
 hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
 hadc3.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
 hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
 hadc3.Init.OversamplingMode = DISABLE;
 if (HAL_ADC_Init(&hadc3) != HAL_OK)
 {
 ////Error_Handler();
 }
 /** Configure Regular Channel 
 */
 sConfig.Channel = ADC_CHANNEL_0;
 sConfig.Rank = ADC_REGULAR_RANK_1;
 //sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;
	sConfig.SamplingTime = ADC_SAMPLETIME_387CYCLES_5;
 sConfig.SingleDiff = ADC_SINGLE_ENDED;
 sConfig.OffsetNumber = ADC_OFFSET_NONE;
 sConfig.Offset = 0;
 if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
 {
 ////Error_Handler();
 }
 /** Configure Regular Channel 
 */
 sConfig.Channel = ADC_CHANNEL_1;
 sConfig.Rank = ADC_REGULAR_RANK_2;
 if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
 {
 ////Error_Handler();
 }
 /** Configure Regular Channel 
 */
 sConfig.Channel = ADC_CHANNEL_2;
 sConfig.Rank = ADC_REGULAR_RANK_3;
 if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
 {
 ////Error_Handler();
 }
 /** Configure Regular Channel 
 */
 sConfig.Channel = ADC_CHANNEL_8;
 sConfig.Rank = ADC_REGULAR_RANK_4;
 if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
 {
 ////Error_Handler();
 }
 /** Configure Regular Channel 
 */
 sConfig.Channel = ADC_CHANNEL_3;
 sConfig.Rank = ADC_REGULAR_RANK_5;
 if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
 {
 //////Error_Handler();
 }
 /** Configure Regular Channel 
 */
 sConfig.Channel = ADC_CHANNEL_13;
 sConfig.Rank = ADC_REGULAR_RANK_6;
 if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
 {
 ////Error_Handler();
 }
 
}
 
static uint32_t HAL_RCC_ADC12_CLK_ENABLED=0;
 
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
 
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 
	if(adcHandle->Instance==ADC3)
 {
 /* USER CODE BEGIN ADC3_MspInit 0 */
 
 /* USER CODE END ADC3_MspInit 0 */
 /* ADC3 clock enable */
 __HAL_RCC_ADC3_CLK_ENABLE();
 
 __HAL_RCC_GPIOF_CLK_ENABLE();
 __HAL_RCC_GPIOH_CLK_ENABLE();
 __HAL_RCC_GPIOC_CLK_ENABLE();
 /**ADC3 GPIO Configuration 
 PF6 ------> ADC3_INP8
 PF7 ------> ADC3_INP3
 PF9 ------> ADC3_INP2
 PH2 ------> ADC3_INP13
 PC2_C ------> ADC3_INP0
 PC3_C ------> ADC3_INP1 
 */
 GPIO_InitStruct.Pin = RCB_REV_Pin|IF_BOARD_REV_Pin|VAA5_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = AEC_REV_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(AEC_REV_GPIO_Port, &GPIO_InitStruct);
 
 HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC2, SYSCFG_SWITCH_PC2_OPEN);
 
 HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC3, SYSCFG_SWITCH_PC3_OPEN);
 
 /* ADC3 DMA Init */
 /* ADC3 Init */
 hdma_adc3.Instance = DMA1_Stream2;
 hdma_adc3.Init.Request = DMA_REQUEST_ADC3;
 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_WORD;
 hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
 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(adcHandle,DMA_Handle,hdma_adc3);
 
 /* USER CODE BEGIN ADC3_MspInit 1 */
 
 /* USER CODE END ADC3_MspInit 1 */
 }
}
 
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
 
 if(adcHandle->Instance==ADC3)
 {
 /* USER CODE BEGIN ADC3_MspDeInit 0 */
 
 /* USER CODE END ADC3_MspDeInit 0 */
 /* Peripheral clock disable */
 __HAL_RCC_ADC3_CLK_DISABLE();
 
 /**ADC3 GPIO Configuration 
 PF6 ------> ADC3_INP8
 PF7 ------> ADC3_INP3
 PF9 ------> ADC3_INP2
 PH2 ------> ADC3_INP13
 PC2_C ------> ADC3_INP0
 PC3_C ------> ADC3_INP1 
 */
 HAL_GPIO_DeInit(GPIOF, RCB_REV_Pin|IF_BOARD_REV_Pin|VAA5_Pin);
 
 HAL_GPIO_DeInit(AEC_REV_GPIO_Port, AEC_REV_Pin);
 
 /* ADC3 DMA DeInit */
 HAL_DMA_DeInit(adcHandle->DMA_Handle);
 /* USER CODE BEGIN ADC3_MspDeInit 1 */
 
 /* USER CODE END ADC3_MspDeInit 1 */
 }
}

    This topic has been closed for replies.

    3 replies

    Super User
    May 13, 2022

    What is the source of the ADC "async" clock?

    There is a nasty Cube bug in ADC clock source configuration.

    If your init code is affected, will have to wait for fix.

    RWu.2Author
    Visitor II
    May 16, 2022

    Thanks for your reply. The ASYNC clock source is adc_ker_ck_input. This project was created with MX 5, so the bug in MX 6.5 and IDE 1.9 shouldn't exist.

    Explorer II
    May 13, 2022

    Are you sure about 10Mhz sampling frequency?

    Check DM00609692 and dm00628458:

    0693W00000Npvw1QAB.png0693W00000Npvw6QAB.pngin Cube IDE configurator: SystemCore → RCC → Product Revision → rev.Y / rev.V

    (must provide 2x frequency revision V compared to revision Y).

    RWu.2Author
    Visitor II
    May 16, 2022

    Sorry, 10Mhz sampling frequency is my mistake, 10Mhz should be Fadc_ker_ck. The configuration of Rev V and Rev Y in RCC is something I didn't pay attention to before, and I also chose the wrong Rev. Thank you for reminding me. I will do some tests to see if this change solves my problem.

    Explorer II
    May 16, 2022

    You can attach your IOC file if problem still exists. Make sure that "PC2_C(ADC3_CH0)" is not connected to something else (some IC). Also, some glitches may occur if you configure input as differential, but input signal do not satisfy this:

    0693W00000Nq1djQAB.pngThere is still possibility that there is some bug in your code. Have you tried simplest possible read of ADC value without DMA?

    Visitor II
    January 20, 2025

    Hello,

    I have similar problems with PC2_C pin.
    It is read through ADC DMA in circular mode (ADC3_CH0).
    Sometimes I got not correct voltage measurments. I am measuring CT clamp voltage.
    Maybe someone solved such issue? It is difficult to change pin, because HW already released.
    I would like to still use DMA for this ADC pin.

        HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC2, SYSCFG_SWITCH_PC2_OPEN);
        /* ADC3 DMA Init */
        /* ADC3 Init */
        hdma_adc3.Instance = DMA1_Stream1;
        hdma_adc3.Init.Request = DMA_REQUEST_ADC3;
        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();
        }

      hadc3.Instance = ADC3;
      hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;
      hadc3.Init.Resolution = ADC_RESOLUTION_16B;
      hadc3.Init.ScanConvMode = ADC_SCAN_ENABLE;
      hadc3.Init.EOCSelection = ADC_EOC_SEQ_CONV;
      hadc3.Init.LowPowerAutoWait = DISABLE;
      hadc3.Init.ContinuousConvMode = ENABLE;
      hadc3.Init.NbrOfConversion = 7;
      hadc3.Init.DiscontinuousConvMode = DISABLE;
      hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
      hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
      hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
      hadc3.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
      hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
      hadc3.Init.OversamplingMode = DISABLE;
      if (HAL_ADC_Init(&hadc3) != HAL_OK)
      {
        Error_Handler();
      }

      /** Configure Regular Channel
      */
      sConfig.Channel = ADC_CHANNEL_0;
      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(&hadc3, &sConfig) != HAL_OK)
      {
        Error_Handler();
      }