0
0
Power-electronicsHow-ToBeginner · 4 min read

How to Use ADC with Interrupt in Embedded C

To use ADC with interrupt in embedded C, configure the ADC module and enable its interrupt, then write an ISR (Interrupt Service Routine) to handle the conversion complete event. This allows the CPU to do other tasks while the ADC conversion runs and processes the result only when ready.
📐

Syntax

The basic steps to use ADC with interrupt are:

  • Initialize ADC hardware and configure input channel.
  • Enable ADC interrupt in the interrupt controller.
  • Start ADC conversion.
  • Write an ISR to handle the ADC conversion complete event.

Each part ensures the ADC runs and signals the CPU when data is ready.

c
void ADC_Init(void) {
    // Configure ADC input channel and settings
    ADC_CONTROL_REGISTER = ADC_ENABLE | ADC_INTERRUPT_ENABLE;
}

void ADC_StartConversion(void) {
    ADC_CONTROL_REGISTER |= ADC_START_CONVERSION;
}

void ADC_IRQHandler(void) {
    if (ADC_INTERRUPT_FLAG) {
        int result = ADC_DATA_REGISTER; // Read ADC result
        ADC_INTERRUPT_FLAG = 0;        // Clear interrupt flag
        // Process result here
    }
}
💻

Example

This example shows how to initialize the ADC, enable its interrupt, start a conversion, and handle the result in the ISR.

c
#include <stdint.h>
#include <stdbool.h>

#define ADC_ENABLE           (1 << 0)
#define ADC_INTERRUPT_ENABLE (1 << 1)
#define ADC_START_CONVERSION (1 << 2)
#define ADC_INTERRUPT_FLAG   (1 << 0)

volatile uint16_t ADC_DATA_REGISTER = 0;
volatile uint8_t ADC_CONTROL_REGISTER = 0;
volatile uint8_t ADC_STATUS_REGISTER = 0;

volatile bool adc_conversion_done = false;
volatile uint16_t adc_result = 0;

void ADC_Init(void) {
    // Enable ADC and its interrupt
    ADC_CONTROL_REGISTER = ADC_ENABLE | ADC_INTERRUPT_ENABLE;
}

void ADC_StartConversion(void) {
    // Start ADC conversion
    ADC_CONTROL_REGISTER |= ADC_START_CONVERSION;
}

// Simulated ISR called when ADC conversion completes
void ADC_IRQHandler(void) {
    if (ADC_STATUS_REGISTER & ADC_INTERRUPT_FLAG) {
        adc_result = ADC_DATA_REGISTER; // Read ADC result
        ADC_STATUS_REGISTER &= ~ADC_INTERRUPT_FLAG; // Clear interrupt flag
        adc_conversion_done = true;
    }
}

int main(void) {
    ADC_Init();
    ADC_StartConversion();

    // Wait for ADC conversion to complete
    while (!adc_conversion_done) {
        // CPU can do other tasks here
    }

    // Use adc_result as needed
    // For demonstration, just loop here
    while (1) {}

    return 0;
}
Output
No console output; adc_result holds the ADC value after interrupt
⚠️

Common Pitfalls

  • Forgetting to enable the ADC interrupt in both ADC and interrupt controller.
  • Not clearing the ADC interrupt flag inside the ISR, causing repeated interrupts.
  • Starting a new ADC conversion before the previous one finishes.
  • Accessing ADC result outside the ISR without synchronization, leading to inconsistent data.
c
/* Wrong: Not clearing interrupt flag */
void ADC_IRQHandler(void) {
    int result = ADC_DATA_REGISTER;
    // Missing: ADC_INTERRUPT_FLAG = 0; leads to repeated interrupts
}

/* Correct: Clear interrupt flag */
void ADC_IRQHandler(void) {
    int result = ADC_DATA_REGISTER;
    ADC_INTERRUPT_FLAG = 0; // Clear flag to stop interrupt
}
📊

Quick Reference

StepDescription
Initialize ADCSet ADC input channel and enable ADC module
Enable InterruptTurn on ADC interrupt in ADC and NVIC/interrupt controller
Start ConversionTrigger ADC to start converting analog signal
ISR HandlingWrite ISR to read ADC result and clear interrupt flag
Use ResultProcess ADC data safely after interrupt signals completion

Key Takeaways

Enable ADC and its interrupt before starting conversion to get interrupt-driven results.
Always clear the ADC interrupt flag inside the ISR to avoid repeated interrupts.
Use the ISR to read ADC data and signal main code when conversion is done.
Do not start a new ADC conversion until the previous one finishes and ISR runs.
Keep main code responsive by handling ADC results only when interrupt signals completion.