11-STM32 ADC Interrupt Method
- ramazanycel
- May 9, 2024
- 3 min read
This project demonstrates the use of ADC interrupts on the STM32L476 microcontroller to read analog voltages from a potentiometer.
The analog voltage from the potentiometer is converted into a digital value using the ADC.
The digital value is then transmitted via UART to a PC, allowing the user to monitor the ADC value in real-time.
ADC interrupts are used to asynchronously handle ADC conversion completions, allowing the microcontroller to perform other tasks while waiting for the ADC to finish.
Here's a breakdown of the steps involved in implementing ADC interrupts with HAL functions:
ADC Initialization: Initialize the ADC peripheral using HAL_ADC_Init().
ADC Channel Configuration: Configure the ADC channel and associated GPIO pin.
Interrupt Configuration: Enable ADC interrupt using HAL_ADC_Start_IT().
Interrupt Service Routine (ISR): Implement the ADC interrupt service routine (HAL_ADC_ConvCpltCallback()), which is called when the ADC conversion is complete.
Data Transmission: Transmit the converted ADC value via UART to a PC.
Error Handling: Handle any errors that may occur during ADC conversion.
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if(hadc->Instance == ADC1)
{
ADC_Value=HAL_ADC_GetValue(&hadc1);
adc_valid=1;
}
}
Required Parts For Example:
STM32L476 development board.
Potentiometer.
USB-to-Serial converter (if connecting to a PC).
PC with UART terminal software (e.g., PuTTY, RealTerm, Tera Term).
CUBEIDE Configuration Steps:
Create a new project in CUBEIDE.
Select the STM32L476 microcontroller variant.
Configure ADC peripheral settings, including resolution, sampling frequency, and channel selection, using the CubeMX configuration tool.
Configure UART peripheral settings for serial communication with the PC.
Generate initialization code and project configuration.
Set ADC:
SET UART:
"Take up one idea. Make that one idea your life -- think of it, dream of it, live on that idea. Let the brain, muscles, nerves, every part of your body be full of that idea, and just leave every other idea alone. This is the way to success." -- Swami Vivekananda
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);
#define SYSTICK_LOAD (SystemCoreClock/1000000U)
#define SYSTICK_DELAY_CALIB (SYSTICK_LOAD >> 1)
#define DELAY_US(us) \
do { \
uint32_t start = SysTick->VAL; \
uint32_t ticks = (us * SYSTICK_LOAD)-SYSTICK_DELAY_CALIB; \
while((start - SysTick->VAL) < ticks); \
} while (0)
#define DELAY_MS(ms) \
do { \
for (uint32_t i = 0; i < ms; ++i) { \
DELAY_US(1000); \
} \
} while (0)
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if(hadc->Instance == ADC1)
{
ADC_Value=HAL_ADC_GetValue(&hadc1);
adc_valid=1;
}
}
int main(void) {
char msg[50]={'\0'};
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM2_Init();
HAL_ADC_Start_IT(&hadc1);
while (1)
{
if(adc_valid == 1)
{
adc_valid=0;
HAL_ADC_Start_IT(&hadc1);
}
sprintf(msg, "ADC_Value=%d \r\n", ADC_Value);
HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), 100);
DELAY_MS(500);
}
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 interrupt project demonstrates real-time monitoring of the ADC value from a potentiometer on a PC via UART communication.
As the potentiometer is adjusted, the ADC value is continuously converted and transmitted to the PC.
This example showcases the practical application of ADC interrupts with HAL functions in STM32 microcontrollers for analog input processing and serial communication, offering a versatile platform for various applications such as sensor interfacing, data logging, and more.
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.
Comments