UART vs SPI vs I²C: the decision
You now know all three protocols. The real skill isn't reciting them — it's picking the right one for a given job, quickly and correctly. This slide turns the three lessons into a clean decision you can make in seconds.
The four questions that decide it
For any peripheral, ask:
- How many devices? One/two, or many?
- How fast must it be? Modest (sensor readings, text) or high (displays, bulk data)?
- How many pins can I spare? Plenty, or am I pin-limited?
- Is it a ready-made module with a fixed interface? (Often the module decides for you — a GPS speaks UART, an OLED might speak I²C or SPI.)
The decision, distilled
Two devices, simple link → UART. Especially if the module already speaks UART (GPS, some modems, serial debug).
Few devices, need SPEED, pins to spare → SPI. Displays, SD cards, fast memory, high-rate sensors.
Many devices, slow is fine, pins are scarce → I²C. Clusters of small sensors, RTCs, EEPROMs, small displays.
Worked mini-examples
- "Read six tiny environmental sensors on a small board." → Many, slow, pin-limited → I²C. (Six on two wires; SPI would need six CS pins; UART can't bus them.)
- "Drive a fast colour graphical display." → One, fast, pins available → SPI. (Throughput matters; one CS pin is cheap.)
- "Connect a GPS module." → Two-device, module speaks serial → UART. (TX↔RX, set the baud.)
- "Add a real-time clock and a temperature sensor to a board already using I²C." → Slow, few pins → I²C, sharing the existing two wires (just different addresses).
Real designs mix protocols
A crucial point: you don't pick one protocol for the whole board. A single microcontroller routinely runs all three at once — UART to a GPS, SPI to a display, I²C to a cluster of sensors. Each peripheral gets the protocol that fits it. Good interfacing is matching each device to its best bus, not forcing everything onto one.
Don't forget: some sensors speak no protocol at all
UART, SPI, and I²C are all digital — they're for chips that already output digital data. But many of the simplest, cheapest sensors output a raw analog voltage with no protocol whatsoever (a basic light sensor, a simple temperature element, a potentiometer). These don't connect to any of the three buses — they connect to an ADC, which is the next slide. The full interfacing picture is digital protocols + analog conversion.
The next slide covers that analog path — ADC and DAC — completing how a microcontroller reaches every kind of device in the real world.
You need to read six small sensors with as few microcontroller pins as possible, and speed doesn't matter. Best fit:
Analog interfacing: ADC and DAC
Not every sensor speaks a digital protocol. The simplest, cheapest ones just output a voltage that varies with what they measure — and the real world itself (light, heat, sound, position) is analog. To bridge that analog world and the microcontroller's digital one, you need two converters: the ADC and the DAC. You met them briefly in L4; here's how they complete the interfacing picture.
The world is analog; the microcontroller is digital
A microcontroller thinks in numbers — discrete digital values. But temperature, light, sound, and a knob's position are continuous, analog quantities. Many simple sensors reflect this directly: a basic light sensor's output voltage rises smoothly with brightness; a simple thermistor's voltage changes smoothly with temperature. There's no protocol, no bits — just a voltage.
To use such a sensor, the microcontroller must turn that varying voltage into a number. That's the ADC's job.
ADC: analog voltage → numbers (input)
An ADC (Analog-to-Digital Converter) measures a voltage on an input pin and converts it into a number the code can read. Feed an ADC input 0–3.3V and it returns, say, 0 at 0V up to its maximum value at 3.3V, proportionally in between.
This is how a microcontroller senses analog quantities:
- A simple light sensor → ADC → a number for "how bright."
- A potentiometer (knob) → ADC → a number for "how far turned."
- A basic temperature element → ADC → a number for "how hot."
Most microcontrollers (the ESP32 included) have built-in ADC inputs — it's a standard peripheral, the "ADC" block from L4's MCU diagram. Resolution matters: a higher-resolution ADC distinguishes finer voltage steps (more numbers between 0 and full-scale), giving more precise readings.
DAC: numbers → analog voltage (output)
A DAC (Digital-to-Analog Converter) does the exact reverse: it takes a number from the code and produces a corresponding output voltage. This lets a microcontroller generate a smoothly varying signal rather than just on/off:
- Produce an audio tone or waveform.
- Output an analog control voltage for some other circuit.
- Dim or fade an analog output smoothly.
DACs are less universal than ADCs (some microcontrollers have them, some don't — and PWM is often used as a cheaper stand-in for analog output), but the concept is the clean mirror of the ADC: numbers out, voltage out.
ADC and DAC as the analog bridge
Put together:
- ADC = ears for analog — read the real world's voltages as numbers (input).
- DAC = voice for analog — turn numbers back into voltages (output).
They bridge the digital microcontroller and the analog world that the digital protocols can't touch directly.
The complete interfacing toolkit
You now have the full picture of how a microcontroller reaches everything around it:
- Digital chips/modules → UART, SPI, or I²C (pick per the decision rules).
- Raw analog sensors → ADC (read voltages as numbers).
- Analog outputs → DAC (or PWM) (numbers as voltages).
Note that many modern sensor modules put a tiny ADC on board and then speak I²C or SPI — so you get the convenience of a digital protocol over an inherently analog measurement. But understanding the ADC underneath is what lets you reason about accuracy, and handle the cheap raw-analog sensors directly.
The final slide ties all of L5 together in a realistic build — every interface type in one design.
A purely analog sensor (e.g., a simple light or temperature sensor outputting a voltage) connects to the microcontroller via:
Putting it together: a real build
Let's put every piece of L5 together in one realistic build — the kind of system engineers actually produce. We'll use an ESP32 monitoring a solar power setup (tying L5 straight into L6), and show how each interface type earns its place.
As always: this is a teaching example to consolidate the concepts, not a product spec. Real designs are owned by the engineering team and reviewed properly.
The build: a solar monitor
An ESP32 (L4) watches a solar generator (L6) and shows its status. It needs to:
- Measure battery voltage and solar/charge current — to compute state of charge and power flow.
- Read temperature — batteries care about heat (L6).
- Show the data on a graphical display.
- Keep accurate time — to log daily energy.
- Report status to a phone or server — wireless.
Each need → the right interface
Battery voltage / current → ADC (analog). The raw electrical measurements come in as voltages (often via a divider — L1 — for the high battery voltage, and a current-sense element). The ESP32's built-in ADC turns these into numbers. Pure analog interfacing — no protocol involved. (Lesson 5.2)
Temperature sensor → I²C. A small digital temperature sensor sits on the I²C bus (SDA/SCL with pull-ups — L1). It's slow and tiny — exactly I²C's sweet spot. (Lesson 4)
Real-time clock → I²C, same two wires. The RTC for daily energy logging joins the same I²C bus at a different address. No new wires — the whole point of I²C. Now two devices share two wires. (Lesson 4)
Graphical display → SPI. The colour status screen needs throughput to refresh smoothly, so it goes on SPI (SCK/MOSI/MISO + its own CS). Fast, one pin for CS — a fair trade. (Lesson 3)
Wireless reporting → (the ESP32's radio). The ESP32's built-in Wi-Fi/Bluetooth handles the phone/server link — beyond L5's wired protocols, but worth noting the ESP32 was chosen partly for this. (A GPS or external modem, if added, would be UART — Lesson 2.)
The whole picture on one microcontroller
┌── ADC pins ◄── battery voltage / current (analog)
ESP32 (L4) ───┼── I²C (SDA/SCL, pull-ups) ◄── temp sensor + RTC (2 devices, 2 wires)
├── SPI (SCK/MOSI/MISO/CS) ──► graphical display (fast)
└── Wi-Fi ──► phone / server
All three answers at once: analog via ADC, many slow devices via I²C, one fast device via SPI. That's real interfacing — matching each device to its best path, exactly the instinct L5 set out to build.
What this competence is for
With L5, a technical person can:
- Read a build and understand how everything connects — not just that a sensor is wired, but why it's on I²C and the display is on SPI.
- Diagnose interfacing faults — "garbled UART" → check baud; "dead I²C bus" → check the pull-ups; "SPI device silent" → check its CS.
- Reason about the products you design and support, from the sensor up to the cloud.
The ladder so far
L5 is the bridge between L4 (the microcontroller) and L6 (the power systems it monitors). You now understand the chip, how it talks to the world, and the power domain it so often controls.
Next: the K-Check tests all three protocols + ADC/DAC, and the P-Check asks you to design the interfacing for a real multi-peripheral build — choosing and justifying a protocol for each device. Bring the decision rules; that's the whole job.