cancel
Showing results for 
Search instead for 
Did you mean: 

Help me understand how to fix this issues with ADC scan feature

sd.1
Associate II

Hello,

I'm using a STM32G431 MCU ADCs in dual mode. I'm trying to get control of the sampling rate and have found a frustrating issue. I don't need to scan multiple channels. Though the only way to get maximum sampling rate, or to have any control over the sampling rate via prescaler, is to enable scan mode. That would be an acceptable work around, but scan mode introduces its own unwanted artifacts into the samples. In scan mode, though I can get the rate I want, I have the extra data from the scanned channels which I do not need.

If I don't use scan mode, the sampling rate is fixed somewhere around 300ksps which is not fast enough. Besides that, slowing the sampling rate is apparently not possible via prescaler in this case.

Any ideas how I can do these conversions, without scan mode, while having full control of the adc clock?

void
MX_ADC1_Init
(
void
)
{
 
 
 
  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};
 
  hadc1.Instance = ADC1;
 
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.GainCompensation = 0;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.EOCSelection =ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 5;//ADC_BUFFER_LEN;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = DISABLE;
 
/*  oversmp.Ratio=ADC_OVERSAMPLING_RATIO_16;
  oversmp.RightBitShift =0;
  oversmp.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
  oversmp.OversamplingStopReset = ADC_REGOVERSAMPLING_RESUMED_MODE;
  hadc1.Init.Oversampling =oversmp;*/
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
  }
  // Configure the ADC multi-mode
 
  multimode.Mode = ADC_DUALMODE_REGSIMULT;
    multimode.DMAAccessMode = ADC_DMAACCESSMODE_12_10_BITS;
    multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_1CYCLE;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
  }
// Configure Regular Channel
 
  sConfig.Channel = ADC_CHANNEL_15;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_6CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    //Error_Handler();
  }
 
 
  HAL_ADC_Start(&hadc2);
 
}
//=============================================================================
/**
@return
- none
 
Initializes adc2
 
*/
void
MX_ADC2_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
  */
  hadc2.Instance = ADC2;
 
  hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
  hadc2.Init.Resolution = ADC_RESOLUTION_12B;
  hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc2.Init.GainCompensation = 0;
  hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc2.Init.EOCSelection =ADC_EOC_SINGLE_CONV;
  hadc2.Init.LowPowerAutoWait = DISABLE;
  hadc2.Init.ContinuousConvMode = ENABLE;
  hadc2.Init.NbrOfConversion = 1;//ADC_BUFFER_LEN;
  hadc2.Init.DiscontinuousConvMode = DISABLE;
 
  hadc2.Init.DMAContinuousRequests = DISABLE;
  hadc2.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  hadc2.Init.OversamplingMode = DISABLE;
  /*hadc2.Init.Oversampling =oversmp;*/
  if (HAL_ADC_Init(&hadc2) != HAL_OK)
  {
   // Error_Handler();
  }
 
  sConfig.Channel = ADC_CHANNEL_17;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_6CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  {
    //Error_Handler();
  }
 
 
 
 
  /* USER CODE END ADC1_Init 2 */
  HAL_ADC_Start(&hadc2);
}

I've attached a picture of the data for reference. Thanks!

1 ACCEPTED SOLUTION

Accepted Solutions

> the sampling rate is fixed somewhere around 300ksps 

This limit might be given by you attempting to poll the ADC using possibly slow Cube/HAL functions.

Maybe you want to use Continuous mode and DMA.

JW

View solution in original post

3 REPLIES 3

> the sampling rate is fixed somewhere around 300ksps 

This limit might be given by you attempting to poll the ADC using possibly slow Cube/HAL functions.

Maybe you want to use Continuous mode and DMA.

JW

sd.1
Associate II

Thanks for your suggestion. That could be the case and I will try continuous mode, seems like a good idea. But I figured, even though there is HAL overhead, the DMA should be doing its process regardless since I am only looking at conversions at DMA EOC interrupt.

sd.1
Associate II

Hey, thanks for the continuous mode tip, it solved my problem! I think stopping/starting the dma/adc may have been causing the issue.