top of page

10-STM32 ADC Polling Example

Updated: May 9, 2024


ree

Previous Tutorial

Example 10

Next Tutorial


ree

This project demonstrates the use of the ADC (Analog-to-Digital Converter) on the STM32L476 microcontroller to read the analog voltage from a potentiometer.

The ADC converts the analog voltage into a digital value, which is then used to adjust the duty cycle of an LED using PWM (Pulse Width Modulation).

The LED brightness changes proportionally with the voltage applied to the potentiometer, allowing for dynamic control of the LED intensity.


In this session, we will solve two examples together, focusing solely on their usage. Additionally, we will reinforce our knowledge using PWM signals and UART. At the end, I'll leave you with a homework question.


ree


1. ADC Initialization:

  • First, you need to initialize the ADC peripheral. This involves configuring parameters such as resolution, sampling frequency, and channel selection.

  • HAL provides a function HAL_ADC_Init() to initialize the ADC peripheral. You need to create and configure a ADC_HandleTypeDef structure with the desired ADC settings and pass it to HAL_ADC_Init().


2. Starting ADC Conversion:

  • After initializing the ADC peripheral, you can start the ADC conversion process.

  • HAL provides a function HAL_ADC_Start() to start the ADC conversion. This function takes the ADC handle (ADC_HandleTypeDef) as an argument and initiates the conversion process.

HAL_ADC_Start(&hadc1);

3. Polling for ADC Conversion Completion:

  • Once the ADC conversion is started, you can poll the ADC status to check if the conversion is complete.

  • HAL provides a function HAL_ADC_PollForConversion() to poll for ADC conversion completion. This function takes the ADC handle, timeout value (or HAL_MAX_DELAY for indefinite wait), and returns HAL_OK when the conversion is complete.

 HAL_ADC_PollForConversion(&hadc1, Timeout);

4. Reading ADC Value:

  • After the conversion is complete, you can read the converted ADC value.

HAL provides a function HAL_ADC_GetValue() to retrieve the converted ADC value. This function takes the ADC handle and returns the converted digital value.

adc_value=HAL_ADC_GetValue(&hadc1);

Required Parts For Example:

  1. STM32L476 development board.

  2. Potentiometer (to generate analog voltage).

  3. LED (to control brightness).

  4. 200 ohm Resistors for ADC and PWM circuitry.

  5. Breadboard (optional).


CUBEIDE Configuration Steps:


CUBEIDE Configuration Steps:

  • Create a new project in CUBEIDE.

  • Select the STM32L476 microcontroller variant.

  • Configure ADC peripheral settings, such as resolution, sampling frequency, and channel selection, using the CubeMX configuration tool.

  • Configure PWM (TIM) peripheral settings for LED control.

  • Generate initialization code and project configuration.


Set ADC:

ree

SET TIMER:

ree
"Learn from yesterday, live for today, hope for tomorrow. The important thing is not to stop questioning." -- Albert Einstein

CODE:


ADC_HandleTypeDef hadc1;
TIM_HandleTypeDef htim2;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM2_Init(void);

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

    uint32_t adcValue = 0;
    uint32_t pwmValue = 0;

    HAL_ADC_Start(&hadc1); // Start ADC conversion
    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

 while (1) {
 // Polling ADC for conversion completion
 if (HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY) == HAL_OK) {
 adcValue = HAL_ADC_GetValue(&hadc1); // Read ADC value
 pwmValue = adcValue * 100 / 4095; // Scale ADC value to PWM range (0-100)
 TIM2->CCR1 = (adc_value<<4);
        }
    }
}

void SystemClock_Config(void) {
    // System Clock Configuration
    // Add code to configure system clock if needed
}

static void MX_GPIO_Init(void) {
    // GPIO Initialization
    // Add code to initialize GPIO pins if needed
}

static void MX_ADC1_Init(void) {
    // ADC Initialization
    // Add code to initialize ADC if needed
}

static void MX_TIM2_Init(void) {
    // TIM2 PWM Initialization
    // Add code to initialize TIM2 for PWM if needed
}

Result


  • The STM32L476 ADC polling project demonstrates dynamic LED brightness control based on the voltage input from a potentiometer.

  • As the voltage from the potentiometer changes, the ADC converts it into a digital value.

  • The digital value is then used to adjust the PWM duty cycle of the LED, resulting in varying brightness levels.

  • This example showcases the practical application of ADC and PWM peripherals in STM32 microcontrollers for analog input processing and LED control, offering a versatile platform for various applications such as lighting control, motor speed regulation, and sensor interfacing.






STM32 ADC Polling Example with UART


In the example above, we changed the brightness of an LED using ADC. Now, let's use the same example to visualize the ADC value and voltage value on the serial monitor with UART. Additionally, let's use a LOGIC analyzer to visualize the duty cycle changes of our signals on the computer.


Required Parts For Example:

  1. STM32L476 development board.

  2. Potentiometer (to generate analog voltage).

  3. LED (to control brightness).

  4. 200 ohm Resistors for ADC and PWM circuitry.

  5. Breadboard (optional).


CUBEIDE Configuration Steps:


CUBEIDE Configuration Steps:

  • Create a new project in CUBEIDE.

  • Select the STM32L476 microcontroller variant.

  • Configure ADC peripheral settings, such as resolution, sampling frequency, and channel selection, using the CubeMX configuration tool.

  • Configure PWM (TIM) peripheral settings for LED control.

  • Configure UART peripheral settings for SERIAL Communication

  • Generate initialization code and project configuration.


Set ADC:

ree

SET TIMER:

ree

SET UART:

ree

CODE:


ADC_HandleTypeDef hadc1;
TIM_HandleTypeDef htim2;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM2_Init(void);

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

    uint32_t adcValue = 0;
    uint32_t pwmValue = 0;
    char msg[50]={'\0'};

    HAL_ADC_Start(&hadc1); // Start ADC conversion
    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

 while (1) {
	  HAL_ADC_Start(&hadc1);
	  HAL_ADC_PollForConversion(&hadc1, 1000);

	  adc_value=HAL_ADC_GetValue(&hadc1);

	  TIM2->CCR1 = (adc_value<<4);
	  HAL_Delay(100);

	  sprintf(msg, "Value=%d \r\n", adc_value);
	  HAL_UART_Transmit(&huart2, (uint8_t*)msg, sizeof(msg), 100);
        }
    }
}

void SystemClock_Config(void) {
    // System Clock Configuration
    // Add code to configure system clock if needed
}

static void MX_GPIO_Init(void) {
    // GPIO Initialization
    // Add code to initialize GPIO pins if needed
}

static void MX_ADC1_Init(void) {
    // ADC Initialization
    // Add code to initialize ADC if needed
}

static void MX_TIM2_Init(void) {
    // TIM2 PWM Initialization
    // Add code to initialize TIM2 for PWM if needed
}

In this example, I can recommend a product for logic analysis. There are many products available on the market for this purpose, and you can use whichever you prefer. However, the one I use is the AZ-DELIVERY logic analyzer, and I use a program called LOGIC-2 with it.


ree




Now it's your turn.
What I'm asking from you this time is to create an example using not just one ADC channel, but three ADC channels. In other words, there will be three potentiometers and three LEDs. Each potentiometer will control the brightness of one LED. Let's see if you can do it! Those who can accomplish this, share your methods in the comments. Those who can't, feel free to ask questions in the comments.


ree

Previous Tutorial

Tutorial 10

Next Tutorial


ree



Comments


bottom of page