In this lesson, you will learn how to shift from constantly "checking" a button’s state to having the hardware notify your CPU the exact moment an input changes.
The Problem with Polling
So far, we have handled inputs by "polling"—constantly reading the GPIO data register inside a while(1) loop. This is like standing at your front door, opening it every second to check if a package has arrived. It works, but it wastes the CPU’s energy and prevents it from doing other useful work while waiting.
The Interrupt Approach
Handling GPIO interrupts is like installing a doorbell. Instead of checking the door yourself, you tell the hardware: "Stay in low-power mode, and wake me up only when this pin transitions from high to low (a button press)."
When a physical voltage change occurs on an interrupt-capable GPIO pin, the hardware automatically pauses your main program and jumps to a specific function called an Interrupt Service Routine (ISR). Once the code inside the ISR finishes, the CPU resumes exactly where it left off.
Implementation Logic
To set this up, you typically modify three types of registers:
- Interrupt Mask Register: To enable the specific pin to trigger an interrupt signal.
- Edge Selection Register: To define if you want to trigger on a "rising edge" (low-to-high) or a "falling edge" (high-to-low).
- Interrupt Pending/Clear Register: A register you must reset inside the ISR to acknowledge that the hardware event has been serviced.
// Example: Concept of an ISR structure
void GPIO_PORTA_Handler(void) {
// 1. Check if the specific pin triggered the interrupt
if (GPIO_PENDING_REG & PIN_0_BIT) {
// 2. Perform the action (e.g., toggle an LED)
TOGGLE_LED();
// 3. Clear the interrupt flag so it doesn't trigger again immediately
GPIO_PENDING_REG |= PIN_0_BIT;
}
}
By offloading the "waiting" to the hardware, you free up the CPU to handle complex tasks, background calculations, or enter power-saving modes, all while ensuring that user inputs are captured instantly as they happen.
Key Takeaway: GPIO interrupts eliminate the need for CPU-intensive polling by allowing hardware to trigger an asynchronous service routine only when a signal state change occurs.