Two ways an embedded system notices something happened. One keeps asking. The other gets tapped on the shoulder.
Every microcontroller eventually has to answer the same question: how do I know when a pin changes state, a timer expires, or a byte arrives on a UART line? There are exactly two strategies. Polling has the main loop actively check, over and over, whether anything happened. Interruptsflip that around — the hardware itself taps the CPU on the shoulder the instant the event occurs. They sound like a minor implementation detail. In practice, the choice changes what your firmware can and can't reliably detect.
Picture a pin that briefly pulses high for a few microseconds — a sensor firing, a rotary encoder tick, an incoming signal edge — then goes back low. The main loop is busy doing other work (reading other sensors, updating a display, running a control calculation) and only gets back around to checking this particular pin once every pass through the loop. Whether that brief pulse gets noticed at all depends entirely on which of the two strategies below is watching for it.
A polling loop's ability to catch an event is bounded by how often it gets back around to checking. If the loop body takes, say, 2 ms to run one full pass and an event lasts only 50 μs, there is a real window in every single pass where that event could occur, complete, and vanish without ever overlapping a check. Interrupts remove that timing dependency entirely: the interrupt hardware watches the pin (or timer, or UART register) continuously and independently of whatever the CPU happens to be doing, so the moment the condition is met, the CPU's normal instruction stream is paused, a short interrupt service routine (ISR) runs to handle the event, and execution resumes at the exact instruction it was on — as if nothing happened, except now the event has been recorded or acted on.
Not quite. Interrupts buy responsiveness and CPU efficiency, but they come with real design costs that polling simply doesn't have. An ISR has to be kept short and fast — heavy work inside one delays every other interrupt and can wreck timing elsewhere in the system. Any variable shared between an ISR and the main loop needs careful handling (the volatile keyword, disabling interrupts briefly, or atomic access) or you risk a race condition where the main loop reads a value mid-update. And too many interrupts firing too frequently can themselves overwhelm a system — an "interrupt storm" that starves the main loop, or lower-priority interrupts, of any CPU time at all. For a genuinely simple, low-speed, or highly deterministic-timing job — reading a slow-changing sensor once every 100 ms inside a simple loop, for instance — plain polling is often the more appropriate, more maintainable, and equally effective choice. The right answer depends on how fast and frequent the event is, and how much timing determinism the application actually needs — not a blanket rule that interrupts win.
Explains the two fundamental ways an embedded system detects that something happened: polling, where the main loop actively checks a flag or pin every pass, and interrupts, where hardware notifies the CPU the instant an event occurs. Covers why polling can miss very brief events, why interrupts are more responsive but add design complexity, and how to choose between them.
In a polling design, the main loop reads a status flag or an input pin's state on every single pass, regardless of whether anything has actually happened. It is simple to write and simple to reason about — you always know exactly where in the loop the check happens, which makes timing fully deterministic. The tradeoff is twofold: CPU cycles are spent checking on every pass even when nothing has occurred, and any event briefer than one loop iteration can start and end entirely between two checks, going completely undetected. A fast pulse, a quick button bounce, or a short-lived signal edge can all slip through a polling loop that simply wasn't looking at the right moment.
In an interrupt-driven design, dedicated hardware watches for the triggering condition — a pin changing state, a timer reaching zero, a UART receiving a byte — independently of what the CPU's main program is doing. The moment that condition is met, the CPU's normal execution is automatically paused, a short interrupt service routine (ISR) runs to handle the event, and execution resumes exactly where it left off. Because the hardware is watching continuously rather than on a schedule, even very brief events are caught, as long as the interrupt hardware itself can register them — and the CPU is free to do other useful work between events instead of constantly checking.
Polling wins when timing needs to be fully predictable and the event being watched is slow, infrequent, or non-critical — reading a temperature sensor once every 100 ms, for example, where there is no real risk of missing anything and no benefit to added complexity. Interrupts win when an event is brief, fast, or high-priority relative to the main loop's pass time — a rotary encoder tick, an incoming communication byte, a safety-critical limit switch. The catch with interrupts is design discipline: an ISR must be kept short so it doesn't block other interrupts or delay the main loop, any variable shared between an ISR and the main loop needs volatile or atomic-access handling to avoid race conditions, and firing interrupts too frequently can create an "interrupt storm" that starves the rest of the system of CPU time. Neither approach is universally correct — the right choice depends on the event's speed and frequency and how much timing determinism the application actually needs.
In principle, yes — if the loop is guaranteed to always complete a full pass faster than the shortest possible event duration, polling can catch everything. In practice this is hard to guarantee once the loop body does variable-length work (conditional branches, communication calls, other sensor reads), which is exactly why interrupts exist for events that are fast or unpredictable relative to loop timing.
Not exactly. A common pattern is for the ISR to do the minimum work needed (e.g., set a flag or store a value) and then let the main loop check that flag on its own schedule and do the heavier processing. This keeps the ISR short while still guaranteeing the event itself was captured the instant it happened.
A race condition happens when the main loop reads a variable at the same moment an ISR is in the middle of updating it, producing a value that is neither the old nor the new state — for example, a multi-byte counter read half-updated. Declaring the shared variable volatile prevents the compiler from caching a stale copy in a register, and briefly disabling interrupts (or using an atomic read) during the access prevents the ISR from interrupting mid-read.
An interrupt storm is when interrupts fire so frequently, or so many different interrupt sources are active at once, that the CPU spends nearly all its time entering and exiting ISRs instead of running the main program — or higher-priority interrupts repeatedly preempt lower-priority ones before they can finish. The system can appear to hang or become unresponsive even though it is technically "working," just entirely on interrupt handling.
No. For slow, infrequent, or non-critical events — reading a slow-changing sensor once every 100 ms in a simple loop, for instance — polling is often simpler to write, easier to debug, and has fully deterministic timing that some applications specifically want. Interrupts are the better tool only when an event is brief, fast, or high-priority enough that missing it or delaying its handling would actually cause a problem.
There is no fixed number, but the guiding principle is: do the minimum work necessary to capture or acknowledge the event (read a register, set a flag, store a byte) and defer any heavier processing to the main loop. A long-running ISR blocks lower-priority interrupts and can delay the main loop enough to cause the very timing problems interrupts were meant to solve.
Try our Mechatronics Studio
More calculators, simulators, and guides for this discipline.