GPIO, Timers & Interrupts
The first peripherals every embedded engineer masters. Learn GPIO modes (push-pull, open-drain, pull-ups, alternate function), drive strength and input thresholds, button debouncing, external interrupts (EXTI) with edge selection, timers for delays, periodic ticks, input capture (frequency/pulse measurement) and output compare.
Blinking an LED, reading a button and measuring a sensor's pulse are the 'hello world' of embedded systems — but doing them robustly teaches electrical limits, interrupts and timer hardware used in every serious design.
An analogy
A GPIO pin is a door that can be set to open outward (output) or inward (input); timers are the building's clocks and stopwatches that time everything precisely.
GPIO modes
Output push-pull (drives high and low), open-drain (only pulls low — for I²C and wired-OR, needs pull-up), input floating/pull-up/pull-down, analog, and alternate function (peripheral controls the pin). Respect per-pin current limits (≈ 8–25 mA).
Buttons and EXTI
Mechanical contacts bounce for 1–10 ms. Debounce with RC + Schmitt input, or in software (time filter or state sampling). External interrupt lines trigger on rising, falling or both edges.
Timer functions
Time base (periodic interrupts), input capture (measure frequency, pulse width, encoder speed), output compare (precise edges), PWM, one-pulse mode, encoder interface mode for quadrature encoders.
Robustness
ESD and over-voltage protection on external pins, 5 V-tolerant pins, slew-rate settings to reduce EMI, glitch filters on inputs, and handling timer overflow when measuring long periods.
Formulas
- Input capture frequency:
f_signal = f_tim / N_cap - Pulse width:
t = N / f_tim - Timer overflow period:
T_ovf = 2^bits / f_tim - Pull-up current:
I = V_DD / R_pu
Worked example: Frequency by input capture
Given: Timer at 1 MHz; Captured difference 2500 counts
Find: Frequency.
- f = 10⁶/2500 = 400 Hz
Answer: 400 Hz (resolution ±1 count = ±0.04 %)
Worked example: Pull-up current
Given: 3.3 V, 40 kΩ internal pull-up, button pressed
Find: Current.
- I = 3.3/40 000 = 82.5 µA
Answer: 82.5 µA while pressed
Button interrupt with debounce + input capture (STM32 HAL)
#include "main.h"
volatile uint32_t last_press_ms = 0;
volatile uint32_t period_counts = 0, last_capture = 0;
void HAL_GPIO_EXTI_Callback(uint16_t pin) { /* falling edge on button */
uint32_t now = HAL_GetTick();
if (pin == BUTTON_Pin && (now - last_press_ms) > 30) { /* 30 ms debounce */
last_press_ms = now;
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { /* timer at 1 MHz */
uint32_t cap = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
period_counts = (cap - last_capture) & 0xFFFF; /* handles wrap-around */
last_capture = cap;
}
float signal_hz(void) { return period_counts ? 1e6f / period_counts : 0.0f; }EXTI gives an interrupt on the button edge; time-based debounce ignores bounces within 30 ms. Input capture latches the timer count on each signal edge, so the difference gives the period with hardware precision.
Common mistakes
- Wrong: Driving loads beyond pin current limits. — Right: Use transistors/MOSFETs for heavier loads.
- Wrong: No debounce on buttons. — Right: Filter in hardware or software.
Applications
- User interfaces: Buttons, LEDs, rotary encoders.
- Speed measurement: Hall sensors and encoders via input capture.
- Scheduling: Periodic timer ticks.
Key takeaways
- Push-pull vs open-drain; pull-ups.
- Debounce buttons.
- Input capture: f = f_tim/N.
- Watch overflow and pin limits.
Going further
- Quadrature encoder mode: Hardware position counting.
- Timer chaining: Master/slave timers for long counts.
- Glitch filters: Digital input filtering.