Microcontroller Electronics
The hardware around a microcontroller: power and reset, crystals, GPIO limits, level shifting, pull-ups and debounce, the ADC, I2C pull-ups, programming headers and battery life.
On this page
- Power, decoupling and reset
- Clocks and crystals
- GPIO: outputs, inputs and limits
- Logic levels and level shifting
- Switches, pull-ups and debounce
- Analog inputs and the ADC
- PWM and timers
- I2C, SPI and UART at the wire level
- Driving loads from a pin
- Programming and debug connections
- Low power and battery life
- Protection and robustness
- Common faults
- FAQ
A microcontroller board runs on code, but it only works if the electronics around the chip are right: a clean supply, a reset, a clock, inputs with defined levels, and outputs that are not asked for more than they can give. This page is the hardware side of building with microcontrollers (Arduino, ESP32, STM32, Raspberry Pi Pico and bare chips alike). For the software and peripherals see Embedded Systems.
Power, decoupling and reset
- Check the supply voltage and current. Most modern chips run at 3.3 V (some 1.8 V or 5 V); a few use two supply rails (core and I/O). Use a regulator with some current to spare (see Batteries and Power Supplies).
- Decouple every supply pin with a 100 nF ceramic capacitor as close as possible to the pin, plus 4.7–10 µF per rail near the regulator. The chip’s switching draws sharp current pulses that the capacitor must supply locally (see Capacitors).
- Analog supply. Many chips have separate AVCC/VDDA pins for the ADC: connect them to the supply through a small ferrite bead or 10 Ω resistor with a decoupling capacitor.
- Reset. A pull-up (10 kΩ) on the reset pin and a 100 nF capacitor to ground hold the chip in reset until the supply is stable; a push button to ground gives a manual reset. Chips with a built-in brown-out detector reset themselves when the supply droops; turn it on for battery projects.
- Boot and strapping pins. Some pins set the start-up mode (for example GPIO0 on the ESP32, BOOT0 on the STM32). Do not load them with circuits that pull them to the wrong level at power-up.
- Power-up order and back-feeding. A signal driven into a pin before the chip is powered can power it through the protection diodes; keep connected devices on the same supply or switch them together.
Clocks and crystals
Most chips have an internal oscillator that is accurate to a percent or two, good enough for blinking and slow serial links. Use a crystal (quartz) when you need accurate timing (USB, a real-time clock at 32.768 kHz, fast UART, CAN) or a precisely known frequency. A crystal oscillator needs two small load capacitors, one from each pin to ground.
Worked example: load capacitors for a crystal
- The crystal’s datasheet gives its load capacitance CL, say 12 pF. The oscillator sees the two capacitors in series plus the stray capacitance of the board and pins (about 5 pF): CL = C1 × C2 ÷ (C1 + C2) + Cstray.
- With C1 = C2 = C: C ÷ 2 + 5 = 12, so C = 2 × (12 − 5) = 14 pF. Use the nearest standard value (15 pF).
- Keep the crystal and its capacitors close to the chip, with short traces, a ground pour under them and no other signals nearby. A wrong capacitor value makes the frequency a little off; a bad layout makes it fail to start.
GPIO: outputs, inputs and limits
| Mode | What the pin does | Notes |
|---|---|---|
| Push-pull output | Drives high and low | Typical source/sink limit 4–25 mA per pin; read the datasheet for the voltage drop at the current you use |
| Open-drain output | Pulls low or releases | Used for I2C, shared lines and level shifting; needs a pull-up |
| Input (floating) | Reads the voltage | Never leave an input floating: it picks up noise |
| Input with pull-up or pull-down | Internal resistor (20–100 kΩ) sets the idle level | Fine for buttons; too weak for long wires or noisy places |
| Analog input | Connected to the ADC | See below; the digital input stage is switched off |
| Alternate function | Connected to a peripheral (UART, SPI, I2C, timer) | The datasheet table says which pins can do what |
Worked example: an LED on a 3.3 V pin
- A red LED has a forward voltage of about 2 V. For 5 mA from a 3.3 V pin: R = (3.3 − 2) ÷ 0.005 = 260 Ω; use 270 Ω.
- Modern LEDs are bright at 2 to 5 mA. The pin’s current is the LED current, so keep the total of all pins within the chip’s limit (often 100–200 mA for the whole package).
- Do not drive more than the pin’s rating: for a motor, a relay or a strip of LEDs, use a transistor (see the next sections and Driving Motors and Actuators).
- Total current. The sum of the currents from all pins, and the current through the supply pins, has its own limit: add up the loads.
- Unused pins: configure them as outputs (left unconnected) or as inputs with a pull-up; never as floating inputs.
- Series resistors (100–470 Ω) on pins that go off the board limit current into a short and reduce noise.
- Pin state at power-up and reset is usually an input: a connected transistor or relay may briefly turn on; use a pull-down on its gate or base.
Logic levels and level shifting
| Term | Meaning | Typical value (3.3 V logic) |
|---|---|---|
| VOH | Output high voltage at the stated load | At least 2.4 V |
| VOL | Output low voltage | No more than 0.4 V |
| VIH | Lowest voltage read as high | About 0.7 × VDD = 2.3 V |
| VIL | Highest voltage read as low | About 0.3 × VDD = 1.0 V |
| 5 V tolerant | The pin accepts 5 V though the chip runs at 3.3 V | Only if the datasheet says so (many ESP32, RP2040 and STM32 pins are not) |
Connecting a 5 V output to a 3.3 V input can damage the input; connecting a 3.3 V output to a 5 V input may not be read as high (a 5 V chip may need 3.5 V). Match the levels.
| Method | Direction | Use for | Notes |
|---|---|---|---|
| Resistor divider | High to low, one way | Slow inputs from a 5 V output | Simple; 1 kΩ and 2 kΩ turn 5 V into 3.33 V; slows fast edges |
| Series resistor and clamp | High to low | Occasional 5 V into a tolerant pin | Relies on the protection diode; limit current to a milliamp |
| MOSFET level shifter (BSS138) | Both ways | I2C and open-drain buses | Bidirectional with a pull-up on each side |
| Level-shifter IC (74LVC, TXS0108, 74HCT) | One or both ways | SPI, UART, parallel; fast signals | Check the speed and the direction control |
| 74HCT or 74AHCT gate | Low to high | 3.3 V into 5 V logic | A 5 V HCT gate reads 3.3 V as high |
| Opto-isolator or digital isolator | Either | Different grounds, noisy or mains-related circuits | See Switches, Connectors and Protection |
Switches, pull-ups and debounce
A button connects the pin to ground when pressed; a pull-up resistor (internal or 10 kΩ external) holds it high otherwise (see Resistors). A real switch bounces: for a few milliseconds the contacts make and break, and the microcontroller sees many presses. Fix it in software (ignore changes for 10–20 ms) or in hardware with an RC filter.
Worked example: a hardware debounce
- A 10 kΩ pull-up with a 1 µF capacitor across the switch gives τ = R × C = 10 ms. The voltage takes about 4.6 τ = 46 ms to settle to within 1 percent, longer than the typical bounce of a few milliseconds.
- The capacitor discharges through the switch when it closes: a brief current spike (V ÷ contact resistance); add a 100 Ω series resistor to limit it.
- A Schmitt-trigger input (or a 74HC14 gate) gives a clean edge from the slow RC; most microcontroller pins have hysteresis, but check the datasheet.
- Long wires pick up noise: use a stronger pull-up (1–4.7 kΩ) and a small capacitor (10–100 nF), and shielded or twisted cable.
Analog inputs and the ADC
An analog-to-digital converter turns a voltage between 0 and its reference (often the supply, 3.3 V or 5 V) into a number. An n-bit ADC has 2n steps; one step (the LSB) is Vref ÷ 2n.
| ADC | Reference | Steps | One LSB |
|---|---|---|---|
| 10-bit (AVR, Arduino Uno) | 5 V | 1 024 | 4.88 mV |
| 12-bit (STM32, RP2040, ESP32 nominal) | 3.3 V | 4 096 | 0.81 mV |
| 16-bit (external ADS1115 and similar) | 3.3 V | 65 536 | 0.050 mV |
Worked example: bringing a 12 V signal into a 3.3 V ADC
- Scale: a divider of 27 kΩ and 10 kΩ gives 12 × 10 ÷ (27 + 10) = 3.24 V at 12 V in, within the 3.3 V range. Use resistors of 1 percent for accuracy; the 37 kΩ total draws only 0.3 mA.
- Source impedance: the ADC’s sampling capacitor needs a source of a few kilohms or less. The divider’s output impedance is 27 kΩ ∥ 10 kΩ = 7.3 kΩ, a little high for some chips: the 100 nF capacitor across the pin supplies the sampling charge and averages it, or use an op-amp buffer.
- Filter: a 1 kΩ resistor and a 100 nF capacitor give a cutoff of 1 ÷ (2π × 1 kΩ × 100 nF) = 1.6 kHz, removing noise above that. For slow signals (a temperature) use a lower cutoff.
- Resolution: a reading of 2048 on a 12-bit, 3.3 V ADC is 2048 ÷ 4096 × 3.3 = 1.65 V at the pin, which is 6.11 V at the input. One step at the pin (0.81 mV) is 2.98 mV at the input.
- Protect it: the clamp diode (or the pin’s internal one with a series resistor) keeps spikes from reaching the chip.
- Averaging and oversampling reduce noise: averaging N samples improves the noise by √N; oversampling 16 samples and shifting adds about 2 bits of resolution for slow signals.
- The reference matters. If Vref is the noisy supply, so is every reading: use a reference chip or a well-filtered supply for accurate work.
- Keep analog wires short, away from switching signals; use a ground plane and the separate analog ground pin.
- Check linearity and offset of cheap on-chip ADCs (some are non-linear near the ends of the range); calibrate against a known voltage.
PWM and timers
A timer counts the clock and can toggle a pin when it reaches set values, giving a PWM output with no CPU effort. The frequency is the clock divided by the timer period; the duty cycle is the compare value divided by the period. Resolution and frequency trade off: a 16 MHz timer with 8-bit resolution runs at 62.5 kHz at most (16 MHz ÷ 256), while 16 bits gives only 244 Hz. PWM drives LEDs (dimming), motors (see Driving Motors and Actuators) and servos, and with a filter it makes a crude analog output: an RC low-pass turns the pulses into a voltage proportional to the duty cycle.
I2C, SPI and UART at the wire level
| Bus | Wires | Speed | Electrical notes |
|---|---|---|---|
| I2C | SDA, SCL (+ ground) | 100 kHz, 400 kHz, 1 MHz | Open-drain with a pull-up on each line; many devices on one bus; each has an address |
| SPI | MOSI, MISO, SCK, CS per device | Up to tens of MHz | Push-pull, point to point; short wires; keep the clock clean |
| UART | TX, RX (+ ground) | 9 600 to 3 Mbaud | Cross TX to RX; common ground; 3.3 V and 5 V levels differ; RS-232 and RS-485 need transceivers (see Serial Communication) |
| 1-Wire | One data wire and ground | Slow | Pull-up of 4.7 kΩ; Dallas temperature sensors |
| CAN | CANH, CANL | Up to 1 Mbit/s | Needs a transceiver and 120 Ω terminators (see Fieldbuses) |
Worked example: choosing the I2C pull-up
- Minimum value: a device must pull the line below 0.4 V while sinking 3 mA: Rmin = (3.3 − 0.4) ÷ 3 mA = 967 Ω.
- Maximum value: the rise time (30 to 70 percent) is 0.8473 × R × Cbus. With 100 pF of wiring and device capacitance, standard mode (100 kHz, 1 000 ns allowed) allows R up to 1 000 ns ÷ (0.8473 × 100 pF) = 11.8 kΩ, and fast mode (400 kHz, 300 ns) up to 3.5 kΩ.
- 4.7 kΩ sits between the limits and is the usual choice for 100 kHz: its rise time is 0.8473 × 4.7 kΩ × 100 pF = 398 ns, too slow for 400 kHz, where 2.2 kΩ (186 ns) is needed.
- Many breakout boards already have 4.7 kΩ or 10 kΩ pull-ups: several in parallel lower the value. If an I2C bus is unreliable, measure the edge with a scope.
- Keep I2C short (tens of centimeters); a longer bus needs lower pull-ups, a buffer chip or differential drivers.
- Address clashes: two devices with the same address cannot share a bus: use an address pin, an I2C multiplexer, or another bus.
- SPI chip selects idle high; unused slaves must be deselected, and the clock should be kept clean (a series resistor of 22–47 Ω helps).
- UART: a common ground, crossed TX/RX, and the same baud rate, data bits, parity and stop bits at both ends.
Driving loads from a pin
| Load | Circuit | Notes |
|---|---|---|
| LED, up to ~10 mA | Pin, series resistor, LED to ground | See above; set the current with the resistor |
| LED strip, buzzer, relay, solenoid | Pin, 1 kΩ to the gate of a logic-level N-MOSFET (or the base of an NPN through 1 kΩ), load to the supply, a 10 kΩ pull-down, flyback diode for coils | See Transistors and Driving Motors and Actuators |
| Mains load | A relay module or an SSR with opto-isolation | Mains is lethal: enclose and follow the rules |
| High-side switching | P-channel MOSFET or a load switch IC | The load keeps a ground reference; the gate must swing to the supply |
| 5 V logic from a 3.3 V pin | See level shifting | A 74HCT gate does it for one way |
Programming and debug connections
| Interface | Pins | Used by | Notes |
|---|---|---|---|
| USB-serial bootloader | TX, RX, DTR/RTS for auto-reset | Arduino, ESP32, many STM32 | Needs the right boot pin state and a USB-serial adapter at 3.3 V logic |
| SWD | SWDIO, SWCLK, GND, Vref, reset | ARM Cortex-M (STM32, RP2040, nRF) | Two wires; breakpoints and live debugging; 10-pin or 6-pin headers |
| JTAG | TCK, TMS, TDI, TDO, reset | Many chips; FPGAs | More pins than SWD |
| ISP / UPDI | MOSI, MISO, SCK, reset; or UPDI single wire | AVR chips | 6-pin ICSP header; UPDI on newer parts |
| USB native | D+, D− (+ 5 V and ground) | RP2040 (UF2), ESP32-S, STM32 DFU | Series resistors of about 22 Ω on D+ and D− if required by the datasheet |
- Always put a programming header on a custom board. It is cheap and it saves a board that arrived with the wrong firmware.
- Break out ground, supply, reset and the debug pins, and a UART for log messages.
- Protect the header from backwards connection with a keyed connector.
Low power and battery life
Battery life depends on the average current, and a microcontroller that sleeps most of the time needs a tiny fraction of the current it uses when it is running. The power budget has three parts: the chip in active and sleep modes, the sensors and radios you switch on, and the always-on circuits (the regulator’s quiescent current, pull-up resistors, LEDs).
Worked example: how long on a 1 000 mAh cell?
- The board draws 40 mA while awake and 0.010 mA (10 µA) asleep, and is awake 1 percent of the time.
- The average current is 40 × 0.01 + 0.010 × 0.99 = 0.410 mA.
- With 80 percent of the 1 000 mAh usable, the life is 800 ÷ 0.410 = 1 952 hours (81 days), against 20 hours (0.8 days) if it never slept.
- The always-on parts matter: an LDO with 100 µA of quiescent current alone would dominate a 10 µA sleep current. Choose a regulator with a quiescent current of a few microamperes, switch off sensors with a MOSFET, and measure the real sleep current with a meter or a current-profiler.
- Use sleep modes and wake on an interrupt or a timer instead of polling.
- Slow down the clock when full speed is not needed; lower the supply voltage.
- Turn off the radio and the sensors between readings.
- Remove power LEDs on cheap boards for battery projects (they draw milliamperes), and note that USB-serial chips and regulators on dev boards waste power.
Protection and robustness
| Risk | Measure |
|---|---|
| Reversed supply | A series Schottky diode or a P-MOSFET reverse-polarity circuit (see Switches, Connectors and Protection) |
| Overvoltage and spikes on the supply | A TVS diode, a fuse or a polyfuse, a regulator rated for the input range |
| ESD and spikes on I/O pins | Series resistors, TVS arrays on connectors, clamp diodes |
| Noise and glitches | Decoupling, a ground plane, ferrites; watchdog timer in software |
| Brown-out | Brown-out detector enabled; a supervisor chip; enough bulk capacitance |
| Hot-plugging | Connect grounds first; use connectors with long ground pins; add series resistors |
| Long cables | Buffer or isolate the signals; use RS-485 or CAN for distance; see Cabling, Grounding and Noise |
Common faults
| Symptom | Likely cause | Try |
|---|---|---|
| The board does not start or keeps resetting | Supply droop, missing decoupling, a boot pin held in the wrong state, a floating reset | Scope the supply and reset; add 100 nF per supply pin; check the boot strapping |
| Programmer cannot connect | Wrong voltage, no reset or boot control, an SWD pin used by the program, a damaged chip | Check the supply, the header wiring and the boot mode; try slower speed |
| Random pin states or inputs that flicker | Floating inputs, no pull-up, noise | Add pull-ups; shorten wires; filter |
| Analog readings noisy or wrong | Noisy reference, high source impedance, switching close by | Add the RC filter; average; separate the analog supply |
| I2C works on the bench and fails on a cable | Too much capacitance, pull-ups wrong, noise | Shorten; reduce the pull-up value; lower the speed; use a buffer |
| A pin is damaged or stuck | Overcurrent, 5 V on a 3.3 V pin, a spike | Test the pin with nothing connected; use another pin; add protection |
| Serial garbage | Wrong baud rate, wrong voltage level, TX and RX not crossed | Match the settings; cross the lines; check levels |
| The board is hot | Linear regulator dropping a high voltage, a short, a driven pin fighting another | Measure supply current; fit a switching regulator; check for contention |
| Works on USB, fails on battery | Battery voltage too low or sagging, a regulator that needs more input voltage | Measure the supply under load; use a low-dropout regulator or a boost converter |
Related
- Digital Electronics and Microcontrollers: the overview of this guide.
- Driving Motors and Actuators: the drivers for motors, solenoids and relays.
- Transistors and Op-amps and Integrated Circuits: switching and analog front ends.
- Batteries and Power Supplies: regulators and batteries.
- Embedded Systems and the MCU Pinout & Peripheral Multiplexer.
- PCB Design and Layout.
- RC Time Constant and Filter Calculator.
FAQ
Do I need a crystal?
Only for accurate timing: USB, a real-time clock, fast UART or CAN. The internal oscillator is fine for most hobby work.
Can I connect a 5 V sensor to a 3.3 V board?
Only if its output is not above the pin’s limit. A 5 V digital output needs a divider or a level shifter; a 5 V analog output needs a divider. Many modules have a regulator and level shifting built in: check the module.
What pull-up value should I use?
For a button, 10 kΩ (or the internal pull-up). For I2C, 2.2 kΩ at 400 kHz and 4.7 kΩ at 100 kHz, adjusted for the bus capacitance. For a long wire or a noisy place, a smaller value (1–4.7 kΩ).
Why do my analog readings jump around?
Noise on the input or the reference, a high source impedance, or a floating pin. Add the RC filter, buffer high-impedance sources, average several samples and keep wires short.
How do I make a board last a year on a battery?
Sleep nearly all the time, wake on a timer or an interrupt, switch off sensors and radios between readings, choose a regulator with a microampere quiescent current, and measure the real average current.
References
- NXP Semiconductors, UM10204 I2C-bus specification and user manual (rise-time and pull-up limits).
- Microchip AVR, STMicroelectronics STM32, Espressif ESP32 and Raspberry Pi RP2040 datasheets and hardware design guides (decoupling, boot pins, ADC, GPIO limits).
- Horowitz, P. and Hill, W., The Art of Electronics, 3rd ed., Cambridge University Press: chapters on digital logic and microcontrollers.
- Crystal manufacturers’ application notes on load capacitance (Epson, Abracon, NDK).
Last reviewed: October 2026. Values are typical: check the datasheets of the parts you use.
