Skip to main content
LPetr.1
Senior
April 15, 2022
Question

STM32L071 reading multiple ADC channels

  • April 15, 2022
  • 13 replies
  • 4656 views

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.

This topic has been closed for replies.

13 replies

MM..1
Super User
April 15, 2022
Piranha
Principal III
April 16, 2022

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

LPetr.1
LPetr.1Author
Senior
April 19, 2022

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
LPetr.1Author
Senior
April 19, 2022

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
LPetr.1Author
Senior
April 19, 2022

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
LPetr.1Author
Senior
April 19, 2022

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
Super User
April 19, 2022

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.

LPetr.1
LPetr.1Author
Senior
April 20, 2022

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));

.

MM..1
Super User
April 20, 2022
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
MM..1
Super User
April 20, 2022

I dont test but try

 for(int i = 0; i< Max_Channels; i++) select_adc_channel(i);
 while (1)
 {
 /* USER CODE END WHILE */
 
 /* USER CODE BEGIN 3 */
HAL_ADC_Start(&hadc);
 
 for(int i = 0; i< Max_Channels; i++)
 {
 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);
 }

if continuos enabled then too start adc move before while ...

LPetr.1
LPetr.1Author
Senior
April 21, 2022

Thanks for the response. I dont understand the code. Why would you want to call select_adc_channel(i); outside a for loop where the adc conversion happens? If I understand it correctly, before you step into while loop, you will simply call select_adc_channel multiple times and do nothing else. Shouldnt it be:

 while (1)
 {
 /* USER CODE END WHILE */
 
 /* USER CODE BEGIN 3 */
HAL_ADC_Start(&hadc);
 
 for(int i = 0; i< Max_Channels; i++)
 {
 select_adc_channel(i);
 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);
 }

MM..1
Super User
April 21, 2022
Ahhh I explain, you ask scan mode. This works mark all channels to scan group, normaly generated code do this, but you write own func,
then I show you how use this func. For() before while mark required channels...once
After this in while do job.
Selecting channels after start ADC is error... Check HAL returned values!
LPetr.1
LPetr.1Author
Senior
April 21, 2022

Thanks