cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G05 ADC problems adding IN8, IN9 or IN10

GMeta.1
Associate III

Hi.

I'm using an STM32G051 and would like to use 12 ADC channels which are not sequential. I have thus set up the ADC for 'sequencer set to not fully configurable' as show below:

stm32adc.png

Ignore for the moment that IN9 is red, I think I was trying something with one of the comparators to see if that helped.

I'm using the DMA to kick off a new conversion and the callback reports back raw values which I print out as seen below.

If I enable IN0, IN9 or IN10 then I get bad data from the ADC (possibly mixed up channels) as seen below where the VREF+ is being reoprted as over 5V when it should be 3.3V.

VREF+: 5362 mV.
CPU Temperature (STM32): 1870.0 °C.
Sample Temperature: 0.0 °C.
LED feedback current: 0 mV.
raw vref ADC value: 0x3a5.
raw DET0 ADC value: 0x184.
raw DET1 ADC value: 0xfff.
raw DET2 ADC value: 0xffe.
raw DET3 ADC value: 0xffd.
raw DET4 ADC value: 0xfff.
raw DET5 ADC value: 0xffe.
raw DET6 ADC value: 0x5e4.
raw STM32 temp value: 0xffe.
raw LED feedback current value: 0x00e.

If I disable IN8, IN9 and IN10 (but use IN16 making a total of 9 channels) then it works as expected as shown here:

VREF+: 3312 mV.
CPU Temperature (STM32): 26.8 °C.
Sample Temperature: 0.0 °C.
LED feedback current: 0 mV.
raw vref ADC value: 0x5e4.
raw DET0 ADC value: 0x176.
raw DET1 ADC value: 0xffe.
raw DET2 ADC value: 0xfff.
raw DET3 ADC value: 0xffe.
raw DET4 ADC value: 0xfff.
raw DET5 ADC value: 0xffe.
raw STM32 temp value: 0x3a4.
raw LED feedback current value: 0xfff.

Seeing as I'm not using fully configurable mode, it is my understanding that the rank is the same as the channel number, but I don't see how this should affect the data that I read from the DMA buffer. If I am using 9 channels then my DMA buffer has a length of 9. The index I use into this buffer follows the order in which the channels are added in the MX_ADC1_Init() function. For example:

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_1;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_3;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_6;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_7;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_VREFINT;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_16;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

In that example I use index 7 in the DMA buffer to access the raw VREF value. In the example above this all works ok but if I were for example to use IN8 instead of IN16 (still a total of 9 channels) still using an index of 7 for VREF, then all the numbers are incorrect? Just for completeness, here's the channel configuration for that last example using IN8:

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_1;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_3;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_6;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_7;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_VREFINT;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_8;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

Hopefully that's not confusing with my app specific names for the ADC channels. I can modify the output if that's confusing. Doesn't feel like this is specific to the STM32G05 either. The last couple of times I've used an ADC, there have been less than 8 channels, so I was able to use 'fully configurable' mode which I think is easier to understand because you get to explicitly list each channel and assign a rank that you know will equate to an index into the DMA buffer.

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Super User

> The index I use into this buffer follows the order in which the channels are added in the MX_ADC1_Init() function.

This isn't right. The order is the order of the channel numbers.

If you add CH1, VREFINT and CH8, in any order, they will be converted in the order CH1, CH8, VREFINT, since VREFINT is connected to CH13.

So for you, the order is:

(first example): 1, 2, 3, 6, 7, 8, TEMP(VSENSE, 12), VREFINT(13).

(second example): 1, 2, 3, 6, 7, TEMP(VSENSE, 12), VREFINT(13), 16

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

View solution in original post

2 REPLIES 2
TDK
Super User

> The index I use into this buffer follows the order in which the channels are added in the MX_ADC1_Init() function.

This isn't right. The order is the order of the channel numbers.

If you add CH1, VREFINT and CH8, in any order, they will be converted in the order CH1, CH8, VREFINT, since VREFINT is connected to CH13.

So for you, the order is:

(first example): 1, 2, 3, 6, 7, 8, TEMP(VSENSE, 12), VREFINT(13).

(second example): 1, 2, 3, 6, 7, TEMP(VSENSE, 12), VREFINT(13), 16

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

Yes I was starting to work that out earlier when I matched up the numbers with the indices, so thanks for confirming.

It's a shame the HAL stuff doesn't add the channels in the channel order because it's not obvious what the channel numbers are for ADC_CHANNEL_TEMPSENSOR and ADC_CHANNEL_VREFINT, even if you hover the mouse over those macros, unless you know where to look, it's not obvious which part is the channel number.

It also doesn't help that you can't rely on the ordering of the channels in CubeMZ which lists the temperature sensor channel after IN7 and the Vrefint Channel after the temperature sensor (i.e. before IN8).