cancel
Showing results for 
Search instead for 
Did you mean: 

How to control main while loop using EOC flag of ADC in continuos mode? Apparently ADC_SAMPLETIME_**** is not affecting ADC sampling time

CGuar.1
Associate

For a given application I am trying to control the main loop speed thorugh the ADC sampling rate. My objective is targeting a fast embedded control application so I plan to go in the 100kHz-10MHz range (yes, I am aware of the STM32H7 limitations for GPIO manipulation at high loop frequency). Relevant parts of my main.c are:

  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_ADC2_Init();
 
  HAL_ADC_Start(&hadc1);
  HAL_ADC_Start(&hadc2);
 
 
 
  while (1)
  {
 
	  g_MeasurementNumber++;
 
	  GPIOE->BSRR = (1<<1); //set to high
	 while((ADC1->ISR == (0<<2))){ //wait for EOC   
	 };
         g_ADCValue0 = ADC1 ->DR;
 
	 while((ADC2->ISR == (0<<2))){ //wait for EOC
	 };
         g_ADCValue = ADC2 ->DR;
 
	 GPIOE->BSRR = (1<<17); //set to low 1+16
}

There, GPIOE registers are manipulated for generating a signal I can easily measure in the oscilloscope. ADC1 and ADC2 are configured for continuous acquisition with data override, and values in DR registers are coherent with the applied voltage.

The thing is that the while loop is done at around 3 MHz without any effect of the ADC clock prescaler or sampling period selected. What I am expecting is that, when one of the channels is set to a different sampling frequency (e.g. below: ADC2 set to ADC_CLOCK_ASYNC_DIV256 and ADC_SAMPLETIME_810CYCLES_5), the complete main loop cycle time is affected.

I have tried wih EOC flag ISR(2), EOS flag ISR(3) -SW cleared afterwards-, and countless configurations, including using a single ADC and varying bit depth, so there is something I am doing wrong. I checked in SMPR1 register that sampling information is correctly sent to the ADC registers. I am incrrectly interpreting (or accessing) EOC flag?

static void MX_ADC1_Init(void)
{
 
  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};
 
  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV6;
  hadc1.Init.Resolution = ADC_RESOLUTION_16B;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SEQ_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_OVERWRITTEN;
  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_2;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_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 */
 
}
 
/**
  * @brief ADC2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC2_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};
  /** Common config
  */
  hadc2.Instance = ADC2;
  hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV256;
  hadc2.Init.Resolution = ADC_RESOLUTION_16B;
  hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc2.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  hadc2.Init.LowPowerAutoWait = DISABLE;
  hadc2.Init.ContinuousConvMode = ENABLE;
  hadc2.Init.NbrOfConversion = 1;
  hadc2.Init.DiscontinuousConvMode = DISABLE;
  hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc2.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
  hadc2.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  hadc2.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc2.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc2) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_3;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  sConfig.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
}

1 ACCEPTED SOLUTION

Accepted Solutions
CGuar.1
Associate

OK... just needed to review my bitwise comparison skills:

not

(ADC1->ISR == (0<<2))

but

((ADC1->ISR & (1<<2))==0)

or

((ADC1->ISR & ADC_ISR_EOC)==0)

View solution in original post

1 REPLY 1
CGuar.1
Associate

OK... just needed to review my bitwise comparison skills:

not

(ADC1->ISR == (0<<2))

but

((ADC1->ISR & (1<<2))==0)

or

((ADC1->ISR & ADC_ISR_EOC)==0)