cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L071 reading multiple ADC channels

LPetr.1
Senior

Hello. We chose STM32L071 CPU without realising that it does not have Scan conversion mode for multiple ADC channels.

Can someone confirm if it is possible to read multiple ADC channels using this CPU?

Please suggest what is the most convenient way to do this.

13 REPLIES 13
MM..1
Chief III
Piranha
Chief II

Opened the reference manual and saw that the ADC can scan multiple channels. Where is the problem?

Can you send me a link? The L071 does not have scan conversion mode which is a mode that is usually used when read multiple channels simultaneously

UPDATE:

I have found where they mention scan mode in the documentation of the STM32L071:

0693W00000LyIVfQAN.png 

However, it wont let me configure this in the cubeMX

LPetr.1
Senior

The following is a schematic:

0693W00000LyI2FQAV.png 

And the cubemx confguration:

0693W00000LyI32QAF.png 

I have tried to read multiple channels with the following code: This is just a snipper from a code, I am not inclugind HAL init functions that are irrelevant

void select_adc_channel(int channel)
{
    ADC_ChannelConfTypeDef sConfig = {0};
    switch (channel)
    {
        case 0:
            sConfig.Channel = ADC_CHANNEL_0;
              sConfig.Rank = 1;
 
              if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
              {
                Error_Handler();
              }
              break;
 
        case 1:
              /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
              */
              sConfig.Channel = ADC_CHANNEL_1;
              sConfig.Rank = 1;
              if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
              {
                Error_Handler();
              }
              break;
              /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
              */
        case 2:
              sConfig.Channel = ADC_CHANNEL_2;
              sConfig.Rank = 1;
              if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
              {
                Error_Handler();
              }
              break;
              /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
              */
        case 3:
              sConfig.Channel = ADC_CHANNEL_3;
              sConfig.Rank = 1;
              if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
              {
                Error_Handler();
              }
              break;
              /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
              */
 
 
        default:
            break;
    }
}
 
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
      for(int i = 0; i< Max_Channels; i++)
      {
          select_adc_channel(i);
          HAL_ADC_Start(&hadc);
          HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY);
          adcValue[i] = HAL_ADC_GetValue(&hadc);
          printf("adc value[%i]=%u \n",i,adcValue[i]);
 
 
      }
      printf("\n");
      HAL_Delay(1000);
  }
  /* USER CODE END 3 */
}

The above does not work. When I short the adc0 pin to ground, all other adc readings change as well:

0693W00000LyI6GQAV.png 

LPetr.1
Senior

Wherever I look, everybody is using the following parameter when dealing with multiple adc channels:

hadc1.Init.ScanConvMode = ENABLE;

This does not seem to be available for STM32L071. So I am hoping that there is another way

LPetr.1
Senior

In the cubemx, I should be able to configure my channels as it shown in this example :

0693W00000LyIMiQAN.png 

However, in my cubemx, I have no such options:

0693W00000LyIMsQAN.png

MM..1
Chief III

Maybe better is read and understand HAL functions , for example part from HAL_ADC_ConfigChannel(

  if (sConfig->Rank != ADC_RANK_NONE)
  {
    /* Enable selected channels */
    hadc->Instance->CHSELR |= (uint32_t)(sConfig->Channel & ADC_CHANNEL_MASK);
    
    /* Management of internal measurement channels: Vlcd (STM32L0x3xx only)/VrefInt/TempSensor */
    /* internal measurement paths enable: If internal channel selected, enable  */
    /* dedicated internal buffers and path.                                     */

as you can see here is |= then every call this add new channel, but dont remove prev. then your select func cant work. Too in HAL source is explain howto use ranks usw.

Thanks for clarifying. But I still cannot fully make sense out of it. What you said is only true when ADC_RANK_NONE is selected. In my case, all channels were assigned RANK 1

hadc->Instance->CHSELR &= ~((uint32_t)(sConfig->Channel & ADC_CHANNEL_MASK));

.

On L0x don’t exist RANK1, read HAL files ...
/** @defgroup ADC_rank ADC rank
* @{
*/
#define ADC_RANK_CHANNEL_NUMBER (0x00001000U) /*!< Enable the rank of the selected channels. Number of ranks in the sequence is defined by number of channels enabled, rank of each channel is defined by channel number (channel 0 fixed on rank 0, channel 1 fixed on rank1, ...) */
#define ADC_RANK_NONE (0x00001001U) /*!< Disable the selected rank (selected channel) from sequencer */
/**
* @}
*/
and you missread in my example code was ! NONE