HomeSTM32STM32 ADC SeriesSTM32 ADC Part 1 – Single Channel Polling Mode

STM32 ADC Single Channel Polling Mode

In this tutorial we will learn how to use STM32 ADC in single channel polling mode. We will configure the ADC using CubeMX and HAL to read analog signals. With polling mode, the microcontroller waits until the conversion is complete and then reads the value. This method is easy to understand and works well for basic projects where you need to measure only one input. We will also test the setup on different STM32 boards and explain the example code step by step.

This is the 1st tutorial in the STM32 ADC series. I am going to use the STM32H750 based development board for this series because it has advanced ADC features. But I will also cover the configuration changes required for some of the popular series that includes STM32F103C8 and STM32F446RE.

STM32 ADC Polling Mode Video Tutorial

This tutorial shows how to configure and read STM32 ADC in single channel Polling mode using CubeMX. You’ll learn how to set up the ADC clock, write the code, and check results step by step. To make things even clearer, I’ve also created a video walkthrough that demonstrates the full process in action. Follow the written guide here while watching the video for a better understanding.

Watch the Video

Hardware Required for STM32 ADC Tutorial

To follow this tutorial, you will need the following hardware:

  • STM32F446 Dev Board (e.g., STM32F4, STM32F7, STM32H7, or any board with ADC support)
  • Potentiometer (to provide an analog input signal)
  • Breadboard (for easy circuit connections)
  • Jumper Wires (male-to-male for connections)
  • USB Cable (to connect the STM32 board to the PC for programming and debugging)

What is ADC Polling Mode in STM32

When we use ADC polling mode in STM32, the microcontroller starts a conversion and then waits until the conversion is complete. After that, it reads the digital value from the ADC data register. This method is simple to use and does not need interrupts or DMA. However, it keeps the CPU busy while waiting, so it is not the best choice for real-time applications.

Definition and working of ADC polling mode

ADC polling mode means the code runs in a loop and checks the status flag until the conversion is finished. Once the flag is set, the program reads the ADC value and continues.

Advantages of ADC polling mode

Polling mode is easy to set up and works well when you only need to read a single channel. It helps beginners understand how ADC works in STM32 without adding complex code.

Limitations of ADC polling mode

Since the CPU waits for the conversion to finish, it cannot do other tasks at the same time. This makes polling mode less efficient for projects that require multitasking or continuous data processing.

STM32 ADC Features and Board Comparison

Different STM32 boards come with slightly different ADC features. The main settings such as resolution, sampling time, and channel selection remain the same, but each series has its own limits. Understanding these features helps you configure the ADC correctly for your project.

Here’s a simple comparison table of STM32 ADC features for F103, F446, and H750 boards:

STM32 SeriesADC ResolutionSampling SpeedChannelsBest Use Case
STM32F10312-bit (0–4095)Basic speedMultiple channelsBeginner projects, single or simple multi-channel readings
STM32F44612-bitHigher speed than F1Multiple channelsApplications needing faster sampling and better accuracy
STM32H75012-bit+ (advanced ADC)Very high speedMultiple channels with advanced modesSignal processing, real-time control, high-performance projects

STM32F103 ADC Configuration

To configure ADC on STM32F103 in single channel polling mode, we will use CubeMX and HAL library. The process includes setting up the clock, enabling the ADC, and selecting the input channel.

Clock setup for STM32F103 ADC

The image below shows the clock configuration for the STM32F103C8T6.

STM32F103 Clock Configuration  for ADC in STM32CubeMX

The system is clocked by the external 8MHz crystal and we can use the PLL to run the system at maximum 72 MHz. Further the ADC prescaler (6 in the image) can be used to set the ADC clock (12MHz in the image) at desired frequency.

The STM32F103C8T6 supports the ADC clock upto a maximum frequency of 14MHz.


ADC Configuration

The image below shows the ADC Configuration in STM32F103C8.

STM32F103 ADC Configuration

I have selected the ADC1 Channel 0 and you can see the pin PA0 is configured as the ADC1_IN0 pin. The ADC is configured in the independent mode. In this mode, the ADC1 can be used independently and we do not need any other ADC for it.

ADC Resolution

The STM32F103C8T6 ADC does not have the option to configure the ADC Resolution. By default the Resolution is 12 bit and it is fixed. You can find this information in the reference manual of the MCU. The image below is from pg 215 of the STM32F103C8 reference manual.

STM32F103 ADC Resolution

ADC Data Alignement

Since the ADC Resolution is 12bit, the data is stored in a 16 bit Data Register. The Data Alignment controls whether we want to align the data to the left or right of this array. The image below shows the available data alignment in STM32F103 ADC.

STM32F103 ADC Data Alignment

We will keep the Data alignment to the Right, as it is easier to process the data.


ADC Scan Conversion mode

This mode is used to scan a group of analog channels. This mode will be automatically selected if you are converting 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.

Since we are using single channel in this tutorial, we will keep this mode disabled.


ADC 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. In case of single channel, the same channel will be converted again and again.

We are using the polling mode in this tutorial, where we will manually call the ADC to start the conversion. So we will keep this disabled for this tutorial.


ADC Regular/Injected Conversion

The ADC can be used in either the Regular conversion Mode or injected conversion mode. The Regular conversion mode is simple as it sounds, basically the normal ADC mode we use. Whereas in the injected mode, we can ‘inject’ a sequence of conversions in between the regular conversions. The injected channels has higher priority, so the ADC will pause the conversion for the regular sequence, then first convert the injected sequence, and it will resume the regular sequence afterwards.


ADC External Trigger Source

The Trigger Source can be used to start the conversion. We can use the timer’s output to trigger the ADC conversion, and hence we can also control the conversion rate. For now we will set this trigger to be launched by the software, so that we can manually start the conversion when needed.


ADC Rank

The Rank section is used to configure the individual channel. When using multiple channels, we can configure the sequence of conversion here. Also we can set the sampling time for each channel. The sampling time is set in ADC CYCLES, and the higher the cycles, the more time ADC will take to sample each channel.

I am setting the maximum sampling time as here we are using a simple potentiometer and time requirement is not an issue. To understand more about how to sample the ADC at a fixed rate, check out the ADC sampling time tutorial.

STM32F446 ADC Configuration

Clock setup for STM32F446 ADC

The image below shows the clock configuration for the ADC in STM32F446RE.

STM32F446RE ADC Clock Configuration

The system is clocked by the external 8MHz crystal and we can use the PLL to run the system at maximum 180 MHz. There is no separate ADC Clock shown in the clock configuration.

If we check the block diagram at pg 16 of the STM32F446RE Datasheet, we can see that the ADC1 is connected to the APB2 Clock. The image is shown below.

STM32F446RE Clock Diagram

As per our current clock configuration, the APB2 clock is at 90MHz.


ADC Configuration

The image below shows the ADC configuration.

STM32F446RE ADC Configuration

I have selected the ADC1 Channel 0 and you can see the pin PA0 is configured as the ADC1_IN0 pin. The ADC is configured in the independent mode. In this mode, the ADC1 can be used independently and we do not need any other ADC for it.

ADC Prescaler

We have the option to configure the clock Prescaler for the ADC. Our current APB2 clock is at 90MHz, and if we set the prescaler to 6, the ADC clock will be reduced to 90/6 = 15MHz.


ADC Resolution

The F446RE has the option to configure the ADC Resolution. We can set the Resolution to 6its, 8bits, 10bits or 12bits. The higher the resolution is, the more accurate will be the ADC data, but the ADC will take more time to sample and convert the result.

Here I have configured the resolution to 12bits.

The rest of the configuration is similar to what we have seen in the F103C8. We have the Data alignment, Scan conversion mode, continuous conversion mode, regular conversion, rank, sampling time etc. So I will cover the ones which are different here.


ADC DMA Continuous Request

This feature is used along with the DMA. Basically while using the DMA to fetch the data from the ADC, we can enable this feature to allow the DMA to continuously request the data from the ADC. This way we do not need to call the DMA again after it has finished receiving the data.


End of Conversion Section

The end of conversion flag (EOC) shows that the conversion is finished and the data is ready to be processed. We can choose whether this flag sets after each channel is converted or only after a sequence of channels is converted in the case of multiple channels.

Since we are using a single channel in this tutorial, either of the options are fine. But you need to be careful while using the multiple channels. This flag should be configured as according to how you want to the process the data. For example, if you are converting 10 channels and set the EOC for each channel, the interrupt will trigger 10 times for each sequence.

STM32H750 ADC Configuration

Clock setup for STM32H750 ADC

The image below shows the clock configuration for ADC in STM32H750.

STM32H750 Clock Configuration

The external 25 MHz crystal clocks the system, and we use the PLL to run it at a maximum of 480 MHz. The PLL2p clocks the ADC, and we can configure it separately. With the current setup, the ADC clock runs at 15 MHz.


ADC Configuration

Below is the image showing the ADC configuration.

STM32H750 ADC Configuration

I have selected ADC1 Channel 3 in the Single Ended Mode. The single Ended mode is the Normal ADC mode we have available in the above mentioned MCUs also. In this mode, the ADC measures the voltage on the input pin. Other than this, we have another option to configure the ADC in the Differential mode. Where the ADC will measure the voltage different between the two inputs.

We will cover the differential mode in the future tutorials.

ADC Prescaler

We have the option to configure the clock Prescaler for the ADC. Our ADC clock runs at 15 MHz, and when we set the prescaler to 10, the ADC clock decreases to 1.5 MHz.


ADC Resolution

The H750 has the option to configure the ADC Resolution as well. We can set the Resolution to 8bits, 10bits, 12bits, 14bits or 16bits. The higher the resolution is, the more accurate will be the ADC data, but the ADC will take more time to sample and convert the result.

Here I have configured the resolution to 16bits.

The rest of the configuration is similar to what we have seen in the F446RE. We have the Scan conversion mode, continuous conversion mode, End of Conversion, regular conversion, rank, sampling time etc. So I will cover the ones which are different here.


Left Bit Shift

The Left Bit Shift (LSHIFT) is a way to shift the converted value towards the left. The result may be negative, so the output data is signed. We will keep it disabled for now and might cover it in the future tutorials.


Converted Data Management Mode

The mode specifies what to do with the converted data. We can transfer the converted data using the DMA, or transfer the data to the DFSDM Register (Digital Filter for Sigma-Delta Modulator) or leave the data in the ADC DR (Data Register).

We are not using the DMA transfer right now, so we will leave the data in the DR (Data Register).


ADC Oversampling

We will not cover the oversampling for now, so ignore any configuration related to that. The ADC oversampling technique is covered in a separate post.

STM32 ADC Wiring Diagram

The image below shows the connection between STM32H750 and the Potentiometer.

Potentiometer connected to STM32

The pin connection is described in the table below.

Potentiometer PinConnected To
VCC3.3V on STM32
GNDGND on STM32
OUTPA6 (ADC1_INP3) Pin

Example Code: Polling Mode ADC Read

This STM32 ADC example demonstrates how to read analog input using polling mode. The same code is compatible with all the STM32 MCUs. The code will remain the same for all the STM32 MCUs. If there are any changes, I will specify in this section itself.

Definitions

Let’s define some variables, which we will use in the main function later.

uint16_t ADC_VAL = 0;
int value = 0;

long map(long x, long in_min, long in_max, long out_min, long out_max)
{
  return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min;
}

We define ADC_VAL as a 16-bit variable, and we use it to store the converted ADC value. Even if we select 10-bit, 12-bit, or 14-bit resolution, we still declare ADC_VAL as a 16-bit variable.

We will use the map function to map the converted ADC value to our desired range. The mapped value will be stored in the value variable, which I have defined as an integer here.


The main function

Below is the main function.

int main()
{
   .....
   .....
   while (1)
   {
      HAL_ADC_Start(&hadc1);
      HAL_ADC_PollForConversion(&hadc1, 100);
      ADC_VAL = HAL_ADC_GetValue(&hadc1);
      HAL_ADC_Stop(&hadc1);
      value = map(ADC_VAL, 0, 65535, 0, 100);
      HAL_Delay (500);
   }
}

We want to measure the ADC continuously, so we will write our code in the while loop. Below are the steps to get the ADC data in polling method.

  1. First, START the ADC.
  2. Next, Poll for the conversion to complete. Here I have set the timeout to 100ms. If the ADC does not finish the conversion within this time, the function will timeout.
  3. Then, Read the converted value and store it in the ADC_VAL variable.
  4. Finally, STOP the ADC.

We now have the converted data stored in the ADC_VAL variable. We will use the map function to map the converted value to 0 to 100 range. Since I have set the ADC resolution to 16bits, the maximum value of the ADC_VAL variable will be 216-1 = 65535. Similarly, the maximum value for the 12bits resolution will be 212-1 = 4095 and the same for the 10bits resolution will be 210-1 = 1023.

The while loop will run every 500ms, therefore we will keep getting the updated data continuously.

Result of STM3 ADC Single Channel Polling Mode

The gif below shows the ADC values obtained by moving the potentiometer, in the STM32CubeIDE debugger.

Debugging STM32 ADC single channel polling mode in CubeIDE with potentiometer input connected on development board

When you move the slider to the right, the ADC_VAL increases towards 65535 and the value variable rises towards 100. Similarly, when you move the slider to the left, the ADC_VAL decreases and the value variable drops towards 0.

Conclusion

In this tutorial we learned how to use STM32 ADC in single channel polling mode with CubeMX and HAL. We configured the clock, selected the channel, and adjusted the resolution and sampling time. After running the example code, we tested the output using a potentiometer and verified the results in debugging mode. Polling mode is easy to understand and works well for simple projects, but it is not efficient for multitasking applications. For advanced use cases, you can later explore ADC with interrupts or DMA.

Next Tutorials in the STM32 ADC Series

1 2

PROJECT DOWNLOAD

Info

You can help with the development by DONATING Below.
To download the project, click the DOWNLOAD button.

STM32 ADC Polling Mode – Common Questions and Answers

Subscribe
Notify of

0 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments