Lab 9: External Interrupt (EXTI)
Learn hardware interrupt handling - respond to GPIO events instantly without polling. This is a core embedded system skill.
Learning Objectives
By the end of this lab, you will:
- 🎯 Understand interrupt concept and architecture
- 🎯 Configure EXTI (External Interrupt) lines
- 🎯 Use SYSCFG to map GPIO to interrupt lines
- 🎯 Write interrupt handler functions
- 🎯 Enable NVIC interrupts for instant response
Prerequisites
- ✅ Complete Lab 4 (debouncing)
- ✅ Understand GPIO input reading
- ✅ Familiar with interrupts concept
Hardware Required
| Component | Details |
|---|---|
| Microcontroller | STM32F407VG |
| Button | PA0 user button |
| LED | PD12 red LED |
Theory: Interrupt Architecture
Polling vs Interrupts
Polling (what we've done):
while (1) {
if (button_pressed) {
// Expensive: checking constantly
}
}
Problem: Wastes CPU time and energy checking
Interrupt (Lab 9):
// Hardware detects button automatically
Interrupt fires → CPU jumps to handler → Executes code
Problem: None - CPU free until event happens!
EXTI System
GPIO Button (PA0)
↓
SYSCFG (maps PA0 to EXTI0 line)
↓
EXTI0 detector (rising edge, falling edge, both)
↓
Interrupt controller (NVIC)
↓
Interrupt handler function (EXTI0_IRQHandler)
Configuration Steps
1. Enable GPIO clock
2. Configure pin as input (MODER = 00)
3. Enable SYSCFG clock (APB2)
4. Map GPIO to EXTI line (SYSCFG_EXTICR1)
5. Unmask EXTI line (EXTI_IMR)
6. Set edge trigger (EXTI_RTSR for rising edge)
7. Enable interrupt in NVIC (NVIC_ISER0)
8. Write __attribute__ handler function
9. Clear interrupt flag in handler (EXTI_PR)
Demo

Button press → Instant LED toggle via interrupt handler
Complete Code
#define RCC_AHB1ENR *(volatile unsigned int*)(0x40023800 + 0x30)
#define RCC_APB2ENR *(volatile unsigned int*)(0x40023800 + 0x44)
#define GPIOA_MODER *(volatile unsigned int*)(0x40020000 + 0x00)
#define GPIOD_MODER *(volatile unsigned int*)(0x40020C00 + 0x00)
#define GPIOD_ODR *(volatile unsigned int*)(0x40020C00 + 0x14)
#define SYSCFG_EXTICR1 *(volatile unsigned int*)(0x40013800 + 0x08)
#define EXTI_IMR *(volatile unsigned int*)(0x40013C00 + 0x00)
#define EXTI_RTSR *(volatile unsigned int*)(0x40013C00 + 0x08)
#define EXTI_PR *(volatile unsigned int*)(0x40013C00 + 0x14)
#define NVIC_ISER0 *(volatile unsigned int*)(0xE000E100)
// Interrupt handler called when PA0 triggers
void EXTI0_IRQHandler(void) {
if (EXTI_PR & (1 << 0)) {
// Clear pending flag
EXTI_PR |= (1 << 0);
// Toggle LED
GPIOD_ODR ^= (1 << 12);
}
}
int main(void) {
// Enable GPIO clocks
RCC_AHB1ENR |= (1 << 0); // GPIOA
RCC_AHB1ENR |= (1 << 3); // GPIOD
// PA0 as input
GPIOA_MODER &= ~(3 << 0);
// PD12 as output
GPIOD_MODER &= ~(3 << 24);
GPIOD_MODER |= (1 << 24);
// Enable SYSCFG clock
RCC_APB2ENR |= (1 << 14);
// Map PA0 to EXTI0
SYSCFG_EXTICR1 &= ~(0xF << 0); // Clear bits [3:0]
// Leave as 0000 for GPIOA selection
// Unmask EXTI0 (allow interrupt)
EXTI_IMR |= (1 << 0);
// Rising edge trigger (button HIGH)
EXTI_RTSR |= (1 << 0);
// Enable EXTI0 in NVIC (interrupt 6)
NVIC_ISER0 |= (1 << 6);
// Loop (CPU now responds to interrupts)
while (1) {
// Can do other work here
// Interrupt will trigger automatically
}
return 0;
}
How It Works
Setup:
├─ PA0 configured as input
├─ SYSCFG maps PA0 → EXTI0
├─ EXTI0 watches for rising edge
├─ EXTI0_IRQHandler registered
└─ NVIC enabled for EXTI0
User presses button:
PA0 goes HIGH → Hardware detects → Interrupt fires!
↓
CPU saves state
↓
Jumps to EXTI0_IRQHandler()
↓
Handler toggles LED
↓
Handler clears pending flag
↓
CPU resumes main loop
Expected Output
User Action:
├─ Press PA0 button
│ └─ Interrupt fires instantly
│ └─ LED toggles immediately
│ └─ No debouncing yet (see Challenge 1)
├─ Release button
│ └─ Another interrupt may fire (false trigger)
└─ Pattern repeats
Common Mistakes
| Issue | Solution |
|---|---|
| No response | Enable SYSCFG clock (RCC_APB2ENR) |
| Wrong pin | Verify SYSCFG_EXTICR1 configuration |
| Multiple toggles | Add debouncing in handler |
| Interrupt never fires | Check NVIC_ISER0 - enable correct IRQ |
Key Takeaways
✨ Important:
- SYSCFG maps GPIO to EXTI lines
- EXTI detects edge conditions
- Interrupt handler runs automatically
- Must clear flag to prevent retriggering
- NVIC enables interrupt in CPU
Challenge Exercises
Challenge 1: Debounced Interrupt
Add debouncing within the handler function.
Challenge 2: Multiple Buttons
Use PA1 with EXTI1 for second button independently.
Challenge 3: Interrupt Counting
Count how many times interrupt was triggered, display on LEDs.
Next Steps
🚀 Ready for Lab 10? Learn LCD display interfacing to show text and data on screen!
Prerequisites for Lab 10: GPIO control, Parallel communication basics