STM32 ADC single channel

This tutorial will cover the ADC in STM32. We will be using a single channel, where one potentiometer is connected.

We will use all the possible ways of reading the ADC values. And those are PollForConversion, Interrupt and the DMA.

Before we start conversions, Let’s see some of the concepts we are going to use in ADC

Single conversion mode

In Single conversion mode the ADC does one conversion and than stops. You can select single conversion in CubeMx by setting continuousconversionmode as DISABLED.

Continuous conversion mode

In continuous conversion mode ADC starts another conversion as soon as it finishes one. This method is more efficient if you want to convert continuously. You can select continuous conversion by setting continuousconversionmode as ENABLED.

Scan mode

This mode is used to scan a group of analog channels. This mode will be automatically selected if you are doing conversions for more than 1 channel. A single conversion is performed for each channel of the group. After each end of conversion the next channel of the group is converted automatically. If the continuousconversionmode is ENABLED, conversion does not stop at the last selected group channel but continues again from the first selected group channel. When using scan mode, DMA bit must be set and the direct memory access controller is used to transfer the converted data of regular group channels to SRAM after each update of the ADC_DR register.

Conversion time

According to the datasheet, the total conversion time is calculated as follows:
Tconv = Sampling time + 12.5 cycles
Example: With an ADCCLK = 14 MHz and a sampling time of 1.5 cycles: Tconv = 1.5 + 12.5 = 14 cycles = (14cycles/14MHz) = 1 µs

There is an entire article on the Conversion Time and Frequency calculation. You can read it

Single channel using Poll for conversion

The CUBEMX Setup for the Poll For Conversion is shown Below. Here I am using only 1 channel and the continuous conversion is DISABLED.

Also the sampling time is 13.5 cycles which is around 1 us, as the ADC clock is 12MHz.

The code is as follows

HAL_ADC_Start(&hadc1); // start the adc 

HAL_ADC_PollForConversion(&hadc1, 100); // poll for conversion 

adc_val = HAL_ADC_GetValue(&hadc1); // get the adc value 

HAL_ADC_Stop(&hadc1); // stop adc 

HAL_Delay (500); // wait for 500ms
  • Pollforconversion is the easiest way to get the ADC values
  • Here we will keep monitoring for the conversion in the blocking mode using HAL_ADC_PollForConversion
  • Once the conversion is complete, we can read the value using HAL_ADC_GetValue
  • And finally we will stop the ADC.

Single channel using INTERRUPT

Pollforconversion uses blocking mode to monitor for the conversion and is not an efficient way to use ADC. Using Interrupt is an alternate way to do so and let’s see How to use it

First we need to enable continuous conversion mode otherwise after single conversion, ADC will stop and we have to restart it.
Also make sure you enable the interrupt in the NVIC tab as shown below

First we have to start the ADC in the interrupt mode by using the function below

HAL_ADC_Start_IT (&hadc1);

Now whenever the conversion is complete, a callback function is called and we are going to write the rest of the code inside it

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) 
  adc_val = HAL_ADC_GetValue(&hadc1); 
  /*If continuousconversion mode is DISABLED uncomment below*/ 
  //HAL_ADC_Start_IT (&hadc1); 
  • HAL_ADC_GetValue reads the value from ADC and stores it in the variable adc_val.
  • Also note that if the continuousconversion mode is disabled, ADC will stop here and we have to again start the conversion in interrupt mode.

Single channel using DMA

DMA is another way of getting data from ADC. Like interrupt mode, DMA method also works in a non-blocking mode.
That means we can use the rest of the program while the DMA would be keep fetching the value in the background and when needed, we can get the value.

DMA in Single Channel is Pointless, and it’s more useful in multi channel mode.

In DMA method, whenever the conversion is complete, the ADC values are saved in the buffer, and we can read them anytime we want. The setup for the DMA is shown below

  • Circular DMA mode will ensure that the DMA will never stop
  • Even after the conversion is complete, the counter will be reloaded and the DMA will start again automatically
  • The Data width should selected as WORD / Half WORD, as the resolution is 12 bit

To start the ADC in DMA mode we have to use the function below

HAL_ADC_Start_DMA (&hadc1, &buffer, 1);

This will start the ADC1 in DMA mode and the converted value will be stored in the buffer.

We can read the buffer at any point in the code and get the ADC value

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
   adc_val = buffer;


Here The potentiometer is connected to he PA0, which is ADC Channel 0.


Check out the Video Below


You can help with the development by DONATING
To download the code, click DOWNLOAD button and view the Ad. The project will download after the Ad is finished.

13 Comments. Leave new

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.


Adblocker detected! Please consider reading this notice.

We've detected that you are using AdBlock Plus or some other adblocking software which is preventing the page from fully loading.

We don't have any banner, Flash, animation, obnoxious sound, or popup ad. We do not implement these annoying types of ads!

We need money to operate the site, and almost all of it comes from our online advertising.

Please add to your ad blocking whitelist or disable your adblocking software.