cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G0B1 ADC DMA multichannel

jagauthier
Associate III

Having some trouble with reading ADC channels on this unit only when using multiple channels. I have no problem using a single channel, but as soon as I expand it to two, or more, my readings are just garbage.

Code for working single channel:

  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.LowPowerAutoPowerOff = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;
  hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_160CYCLES_5;
  hadc1.Init.OversamplingMode = ENABLE;
  hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
  hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_NONE;
  hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
  hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_LOW;
 
  sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

Them my own code: [relevant snips]

#define ADC_CHANNELS 1
uint32_t dmaBuffer[ADC_CHANNELS];
HAL_ADC_Start_DMA(&hadc1, &dmaBuffer, ADC_CHANNELS);

Values I read from dmaBuffer are exactly as I expect them to be.

Now, when I extend this to a secondary channel:

  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.LowPowerAutoPowerOff = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 2;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;
  hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_160CYCLES_5;
  hadc1.Init.OversamplingMode = ENABLE;
  hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
  hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_NONE;
  hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
  hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_LOW;
 
  sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
 
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_VREFINT;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

My custom code:

#define ADC_CHANNELS 2
uint32_t dmaBuffer[ADC_CHANNELS];
 
HAL_ADC_Start_DMA(&hadc1, dmaBuffer, ADC_CHANNELS);
 

The value in dmaBuffer[0] is "garbage" and dmaBuffer[1] is always 0.

I am not sure what's going on with this,. Any advice?

1 ACCEPTED SOLUTION

Accepted Solutions
Kamil Duljas
Senior III

You get garbage because all data fit in first 32 bits - 16 bits as first conversion, next 16 bits as second conversion.

look at your DMA settings. Data width is propably HALF_WORLD (uint16_t) but your buffer is uint32_t. Change your buffer on uint16_t like this:

#define ADC_CHANNELS 2
uint16_t dmaBuffer[ADC_CHANNELS];
 
HAL_ADC_Start_DMA(&hadc1, (uint16_t*)dmaBuffer, ADC_CHANNELS);

Dudo

View solution in original post

3 REPLIES 3
Kamil Duljas
Senior III

You get garbage because all data fit in first 32 bits - 16 bits as first conversion, next 16 bits as second conversion.

look at your DMA settings. Data width is propably HALF_WORLD (uint16_t) but your buffer is uint32_t. Change your buffer on uint16_t like this:

#define ADC_CHANNELS 2
uint16_t dmaBuffer[ADC_CHANNELS];
 
HAL_ADC_Start_DMA(&hadc1, (uint16_t*)dmaBuffer, ADC_CHANNELS);

Dudo
jagauthier
Associate III

You're right. However, passing a uint16_t to HAL_ADC_Start throws an warning because it's expecting uint32_t. So there are 2 solutions.

Define the dma buffer as 16 bit, and cast is 32, or define the DMA buffer to a word.

Both worked. Thanks for the tip!

Kamil Duljas
Senior III

@Community member​ please marks best answer and we are closing topic 🙂

Dudo