STM32 HAL ADC Tutorial: Read Sensor Data Easily

Reading sensor values is one of the most common tasks in embedded systems. Many beginners using STM32 struggle to configure ADC because the registers and datasheets look complex. If you have ever tried to read an analog value and only got zeros or random numbers, you’re not alone. The good news is that with STM32 HAL ADC functions, reading sensors becomes simple.

In this tutorial, we will cover STM32 HAL ADC setup in CubeIDE, code examples, and testing with real sensors.

What is ADC in STM32?

ADC stands for Analog to Digital Converter. It converts real-world analog signals, like voltage from a sensor, into digital numbers that the microcontroller can understand.

Key Features of STM32 ADC:

  • Resolution: 12-bit (0–4095 values).

  • Multiple input channels (up to 16 or more depending on MCU).

  • Single and continuous conversion modes.

  • Supports DMA for faster sampling.

For example, if using a 3.3V reference:

  • 0V = 0 (digital value)

  • 3.3V = 4095 (digital value)

  • 1.65V ≈ 2047


Why Use STM32 HAL ADC?

  • HAL functions save time by handling low-level register details.

  • CubeIDE generates initialization code automatically.

  • Easy to scale for multiple channels.

  • Works with sensors like temperature, light, or potentiometers.


Hardware Setup

Requirements:

  • STM32 development board (e.g., STM32F103 Blue Pill, STM32F4 Discovery).

  • USB cable for programming.

  • Potentiometer or analog sensor (e.g., LM35 temperature sensor).

  • Jumper wires.

Wiring Example:

  • Connect potentiometer middle pin → ADC input pin (e.g., PA0).

  • Connect one side to 3.3V, other side to GND.


Configuring ADC in CubeIDE

Step 1: Create Project

  • Open STM32CubeIDE, select your MCU or board.

Step 2: Enable ADC

  • In Pinout view, select PA0 and set it to ADC1_IN0.

Step 3: ADC Settings

  • Resolution: 12-bit.

  • Mode: Single conversion.

  • Continuous conversion: Disabled (for simple test).

  • Scan conversion: Disabled.

Step 4: Generate Code

  • CubeIDE creates MX_ADC1_Init() function in adc.c.


STM32 HAL ADC Example Code

Single Channel ADC Read

#include "main.h"

ADC_HandleTypeDef hadc1;

uint32_t adcVal;

int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();

while (1) {
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
adcVal = HAL_ADC_GetValue(&hadc1);
HAL_Delay(500);
}
}

Explanation:

  • HAL_ADC_Start() starts ADC.

  • HAL_ADC_PollForConversion() waits until conversion finishes.

  • HAL_ADC_GetValue() returns the digital value (0–4095).


Multiple Channel ADC

uint32_t adcVal1, adcVal2;

while (1) {
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
adcVal1 = HAL_ADC_GetValue(&hadc1);

HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
adcVal2 = HAL_ADC_GetValue(&hadc1);

HAL_Delay(500);
}

Here we read two channels in sequence.


ADC with DMA

DMA allows ADC to sample values continuously without CPU blocking.

uint32_t adcBuffer[2];

int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();

HAL_ADC_Start_DMA(&hadc1, adcBuffer, 2);

while (1) {
// adcBuffer[0] → channel 1 value
// adcBuffer[1] → channel 2 value
}
}

This is useful for sensors that need constant sampling.


Testing STM32 HAL ADC

  1. Flash code to STM32 board.

  2. Open serial terminal (UART debug enabled).

  3. Print ADC values:

char msg[20];
sprintf(msg, "ADC Value: %lurn", adcVal);
HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);
  1. Rotate the potentiometer or change sensor input.

  2. Check ADC values (0–4095) changing in the terminal.


Common ADC Errors and Fixes

  • Always reads 0: Check wiring, ensure pin set to analog input.

  • Random noisy values: Use proper grounding and decoupling capacitors.

  • Full scale (4095 always): Input might be directly tied to VCC.

  • Slow response: Enable DMA for faster reads.


Practical Applications of STM32 HAL ADC

  • Reading temperature sensors (LM35, TMP36, NTC thermistors).

  • Light intensity (LDR sensors).

  • Joystick input.

  • Battery voltage monitoring.

  • Analog signal sampling for audio or sensors.


Pros and Cons of HAL ADC

Pros

  • Easy configuration with CubeIDE.

  • HAL handles register complexity.

  • Supports DMA for efficient sampling.

Cons

  • Slightly slower than direct register programming.

  • Less control compared to LL drivers.


FAQ on STM32 HAL ADC

What is STM32 HAL ADC used for?
It reads analog signals like sensors and converts them into digital values.

What resolution does STM32 ADC have?
Most STM32 ADCs are 12-bit (0–4095 values).

Can STM32 ADC read multiple channels?
Yes, by enabling scan mode or DMA.

What voltage range does STM32 ADC support?
Typically 0 to 3.3V, depending on the board.

How fast is STM32 ADC?
It can sample up to several MHz depending on the MCU.

Can I use DMA with STM32 ADC?
Yes, STM32 HAL supports ADC with DMA for continuous sampling.

Why does my ADC always read 0?
Check if the pin is set to analog mode and wired correctly.

How do I convert ADC value to voltage?
Voltage = (ADC_Value / 4095.0) * 3.3 (for 3.3V reference).

Does STM32 support external ADC reference voltage?
Yes, many STM32 chips support external reference pins.

Is STM32 HAL ADC good for audio signals?
Yes, but use DMA for fast sampling.


Conclusion

In this tutorial, we explained how to use STM32 HAL ADC to read sensor data. We covered CubeIDE setup, single-channel and multi-channel examples, and advanced DMA usage. With this knowledge, you can connect STM32 to real-world sensors like temperature, light, or voltage monitors.

If you want more STM32 tutorials and projects, check ControllersTech for step-by-step guides with code and hardware examples.

Leave a Reply

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