How to read multichannel ADC in STM32

THIS MIGHT NOT WORK WITH THE NEWER CUBEMX VERSIONS. CHECK OUT THE UPDATED METHOD HERE

Description

I have already posted articles about ADC in STM32 using PollforConersion, Interrupt and DMA methods. But in all those articles, I used single channel of the ADC. So today We will see How to read multichannel ADC in STM32.

The process remains same as using in single channel, with some addons though. Let’s get into it

First we need to set up the channels, we want to read, under ADC. Here I will read Channels 0, 1 and internal temperature sensor (16).

ADC Channels

1.) USING PollforConversion Method

In the ADC configuration, Enable SCAN CONVERSION and Continuous Conversion, If you don’t know what they are, please go to the links in the first paragraph.

ADC Configuration

Setup is complete now.. Just open the project and follow along.

First we need to define some variables to store the values of the ADC

uint32_t adc1, adc2, adc3, temperature;

The process is simple here. All you need to do is start ADC -> read adc1 value -> read adc2 value -> read adc3 value and stop ADC. So here its goes

HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
adc1 = HAL_ADC_GetValue(&hadc1);

HAL_ADC_PollForConversion(&hadc1, 100);
adc2 = HAL_ADC_GetValue(&hadc1);

HAL_ADC_PollForConversion(&hadc1, 100);
temp_val = HAL_ADC_GetValue(&hadc1);
temperature = (((temp_val*vsense)-.76)/.0025)+25;
HAL_Delay (200);

HAL_ADC_Stop (&hadc1);

The value returned by channel 16 need to be converted inorder to get the temperature. The formula and the relative values are given in the datasheet. I am using NUCLEOF401RE and the following is extracted from the datasheet.

So we can define Vsense as 3.3/1023 because we are using 10 bit resolution for the ADC.

float vsense = 3.3/1023;

2.) USING DMA METHOD

To use DMA, we need to enable the DMA continuous request in the ADC configuration. Also enable the interrupt and setup the DMA as shown below->

Enable DMA request

Enable interrupt

Setup DMA in circular mode

Generate the project and open it.

uint32_t adc[3], buffer[3], temperature;  // define variables
float vsense = 3.3/1023;

Now we have to write a conversion complete function. It will be called whenever the conversion of the ADC values is completed.

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	for (int i =0; i<3; i++)
	{
	   adc[i] = buffer[i];  // store the values in adc[]
	}

        temperature = (((adc[2]*vsense)-.76)/.0025)+25;
}

Start the ADC in DMA mode in the main function.

HAL_ADC_Start_DMA(&hadc1, buffer, 3);

As to show that it works completely independent, I will blink a LED inside the while loop and the ADC values will be received separately from the while loop.

  while (1)
  {
	HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_5);
	HAL_Delay (1000);
  }

THIS code is for DMA method

CHECK OUT THE UPDATED METHOD HERE

uint32_t adc[3], buffer[3], temperature;
float vsense = 3.3/1023;

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	for (int i =0; i<3; i++)
	{
	  adc[i] = buffer[i];
	}

	temperature = (((adc[2]*vsense)-.76)/.0025)+25;
}	

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();

	HAL_ADC_Start_DMA(&hadc1, buffer, 3);

  while (1)
  {

	HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_5);
	HAL_Delay (1000);

  }

}

Result

Check out the VIDEO Below

DOWNLOAD

You can buy me a coffee sensor 🙂

To download the CODE, Goto

, , , , , , ,

20
Leave a Reply

avatar
13 Comment threads
7 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
13 Comment authors
MaxGarypeterrobertoju Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Alireza
Guest
Alireza

Hi, i have a problem with this code!
I’ve created code just like you,,, and work properly,, but in my case, in while, my code lock and don’t blinking led
Plz help me
Thx

Himanshu Saxena
Guest
Himanshu Saxena

Can you please share the reference manual which you used in your video

Abolfazl
Guest
Abolfazl

I appreciate your comprehensive posts about STM32 MCU ADC .
could you please help me?

I’m using stm32f103 MCU. the datasheet declare that the highest sampling rate of this MCU is 1M sps. is it possible to reach to this rate?

Sunrise
Guest
Sunrise

In code 1, adc1 and adc2 are both scanned for hadc1, is this correct for multichannel? Do I need to create one more hadc2 if need to use keyline2?

Sunrise
Guest
Sunrise

In code1, adc1 and adc2 both are scanned for hadc1, is it correct for multichannel reading? If keys are in different keyline then should it be scanned for hadc2?

nur malso
Guest
nur malso

Hello,
I use a Stm32F303 and the first example dosent work for me.
Wenn I use the following Code

halADC2 = HAL_ADC_Start(&hadc2);
halADC4 = HAL_ADC_Start(&hadc4);

HAL_ADC_PollForConversion(&hadc2,100);
test1 = HAL_ADC_GetValue(&hadc2);

HAL_ADC_PollForConversion(&hadc4,100);
test2 = HAL_ADC_GetValue(&hadc4);

HAL_ADC_PollForConversion(&hadc4,100);
test3 = HAL_ADC_GetValue(&hadc4);
HAL_ADC_Stop(&hadc4);

then the Variables “test2” and “test3” have the same values

any sugestions?

Mouadili
Guest
Mouadili

Bonjour Monsieur,

Je n’arrive pas a telecharger le code pourriez vous svp partager avec moi le lien qui marche .

Cuong
Guest
Cuong

hello . I have a problem with this code . it is used to read mutildplex channel of ADC module. The value of the first channel is right but the value of other channels is wrong . Can you tell me the soloution for this problem ?
HELP ME!
http://codepad.org/T9rQ5o8d

ju
Guest
ju

Hi! I have a question about ADC conversion for multiple channels: is there any way to read several channels with the ADC working in interrupt mode (so with HAL_ADC_Start_IT) ? or is it only possible with the DMA controller?
Thanks in advance for your answer

roberto
Guest
roberto

The code should check the ret of the poll, in my tests the second poll return timeout, maybe is my current hal version, but I’m quite confident that the configuration is the same. The second poll returns a timeout, and the values returned are clearly the same as the first.
Is this mode really possible with the polling? For who doesn’t want to consume dma resource, and prefers to not select in own code rank channel something already defined in cube, this polling mode would be really useful.

peter
Guest
peter

Thank you man. I apreciated your tutorial. The pool for conversion method did not work for me (also the cubemx was missing some parameters that you have). I tried the DMA approach and it worked like a charm!
I have to lower the interrupt priorities though as it messes with my uart interrupts.
Thanks again for the clear explanation.

Gary
Guest
Gary

Great, straight to the point. Most useful I have found, thanks!

Max
Guest
Max

As posted above, the code 1 for polling doesn’t actually work. I suspected that when the example was so basic with no validation. Any plans on fixing the code so it works? This page is highly ranked on Google, so you’ll avoid misleading and wasting a lot of users time following a non-working example claimed as working. Thanks

Menu