ADC interrupt-driven reading in Embedded C - Time & Space Complexity
We want to understand how the time cost changes when reading analog data using interrupts.
How does the program's work grow as more ADC readings happen?
Analyze the time complexity of the following code snippet.
volatile int adc_value = 0;
void ADC_IRQHandler(void) {
adc_value = ADC_ReadData();
ADC_ClearInterruptFlag();
}
int main(void) {
ADC_EnableInterrupt();
while(1) {
// main loop does other work
}
}
This code reads ADC values using an interrupt handler that runs when a conversion finishes.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The ADC interrupt handler runs each time a conversion completes.
- How many times: It runs once per ADC conversion, which depends on how often the ADC triggers.
Each ADC conversion triggers the interrupt once, so the work grows directly with the number of conversions.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 interrupt calls |
| 100 | 100 interrupt calls |
| 1000 | 1000 interrupt calls |
Pattern observation: The total work increases in a straight line as the number of ADC readings increases.
Time Complexity: O(n)
This means the time spent grows directly with the number of ADC readings taken.
[X] Wrong: "The interrupt handler runs only once, so time cost is constant."
[OK] Correct: The interrupt runs every time the ADC finishes a conversion, so the total time grows with the number of conversions.
Understanding how interrupt-driven code scales helps you write efficient embedded programs that handle real-time data smoothly.
"What if we changed the ADC to trigger interrupts only every 10th conversion? How would the time complexity change?"
Practice
Solution
Step 1: Understand ADC interrupt-driven reading
ADC interrupt-driven reading allows the CPU to continue other work while waiting for ADC conversion to complete.Step 2: Identify the main benefit
This method improves efficiency by not blocking the CPU during ADC conversion.Final Answer:
The CPU can perform other tasks while ADC conversion happens -> Option AQuick Check:
Interrupt-driven ADC = CPU multitasking [OK]
- Thinking ADC conversion speed increases
- Assuming interrupts disable other interrupts
- Believing ADC resolution changes automatically
Solution
Step 1: Identify variable sharing between ISR and main code
Variables shared between interrupt handlers and main code must be declared volatile to prevent compiler optimization issues.Step 2: Choose the correct declaration
Using 'volatile int adc_value;' ensures the variable is read fresh each time and not cached.Final Answer:
volatile int adc_value; -> Option DQuick Check:
Shared variable = volatile [OK]
- Omitting volatile causing stale reads
- Using const which prevents modification
- Using static which limits scope but not volatility
volatile int adc_result = 0;
void ADC_ISR(void) {
adc_result = ADC_Read();
ADC_ClearInterruptFlag();
}Solution
Step 1: Analyze the interrupt handler code
The handler reads the ADC value using ADC_Read() and stores it in adc_result, then clears the interrupt flag.Step 2: Understand the effect on adc_result
After the interrupt, adc_result holds the latest ADC conversion value read by ADC_Read().Final Answer:
The latest ADC conversion value -> Option CQuick Check:
ISR updates adc_result with new ADC value [OK]
- Confusing volatile with zero initialization
- Assuming adc_result remains unchanged
- Ignoring ADC_ClearInterruptFlag() role
volatile int adc_val;
void ADC_ISR(void) {
adc_val = ADC_Read();
// Missing ADC_ClearInterruptFlag();
}Solution
Step 1: Review the ISR code
The ISR reads ADC value but does not clear the interrupt flag.Step 2: Understand interrupt flag importance
Not clearing the interrupt flag causes the interrupt to trigger repeatedly, leading to an infinite loop of interrupts.Final Answer:
ADC_ClearInterruptFlag() is missing, causing repeated interrupts -> Option BQuick Check:
Clear interrupt flag to stop repeated ISR calls [OK]
- Forgetting to clear interrupt flag
- Thinking volatile is incorrect here
- Expecting ISR to return a value
Solution
Step 1: Check ADC reading and condition
void ADC_ISR(void) { int val = ADC_Read(); if (val > 500) { adc_value = val; } ADC_ClearInterruptFlag(); }reads ADC value into a local variable, then updates global adc_value only if val > 500.Step 2: Verify interrupt flag clearing
void ADC_ISR(void) { int val = ADC_Read(); if (val > 500) { adc_value = val; } ADC_ClearInterruptFlag(); }clears the interrupt flag after processing, which is correct to prevent repeated interrupts.Final Answer:
Updates adc_value only if ADC reading exceeds 500 and clears interrupt flag -> Option AQuick Check:
Read ADC, check >500, update, clear flag [OK]
- Clearing interrupt flag before reading ADC
- Checking old adc_value instead of new ADC reading
- Not clearing interrupt flag causing repeated interrupts
Ready to prove it?
Pass the test and this pattern moves unknown
