Embedded SystemUnit 89 min read

UART, SPI, I2C: Serial Protocols for Embedded Communication

Unit 8 of Embedded System explores UART (asynchronous), SPI (synchronous master-slave), and I2C (multi-master, multi-slave) protocols—how they transmit data, their hardware/software layers, wiring, speed trade-offs, and real-world uses in sensors, displays, and microcontroller networks.

Core Concepts: What Are UART, SPI, and I2C?

Embedded systems rarely work alone—they communicate with sensors, displays, memory chips, and other MCUs. Three dominant serial communication protocols handle this:

  • UART (Universal Asynchronous Receiver/Transmitter): No clock line, data sent asynchronously.
  • SPI (Serial Peripheral Interface): Synchronous, full-duplex, requires 4+ wires.
  • I2C (Inter-Integrated Circuit): Multi-device, half-duplex, minimal wiring (2 wires).
classDiagram
    class Protocol {
        <<abstract>>
        +transmitData()
        +wiringComplexity
        +speed
    }
    class UART {
        +asynchronous
        +2 wires (TX/RX)
        +no clock
    }
    class SPI {
        +synchronous
        +4+ wires (SCLK, MOSI, MISO, SS)
        +master-slave
    }
    class I2C {
        +synchronous
        +2 wires (SDA, SCL)
        +multi-master/slave
    }
    Protocol <|-- UART
    Protocol <|-- SPI
    Protocol <|-- I2C

1. UART: Asynchronous, Simple, and Slow

How it works:

  • No shared clock line; sender/receiver must agree on baud rate (bits per second).
  • Data framed by start bit (0), 8/9 data bits, parity bit (optional), stop bit (1).
  • No handshaking: Risk of data loss if baud rates mismatch.

Real-world use:

  • Ncell SIM cards: UART connects the SIM module to the MCU for AT commands (e.g., AT+CMGF=1 to enable SMS).
  • Debugging: Most MCUs (Arduino, ESP32) use UART for serial monitors (e.g., Serial.begin(9600)).

Worked Example: Problem: Send "HELLO" from an Arduino to a PC at 9600 baud. Draw the UART frame for 'H' (ASCII 72, no parity). Solution:

Start | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | Stop
      |---|---|---|---|---|---|---|---|
      | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 1 |

Why? 'H' in binary is 01001000 (MSB first). UART transmits LSB first, so the frame above is correct.

Advantages/Disadvantages: | UART | ✅ Simple wiring (2 wires) | ❌ No error checking (unless parity used) | | | ✅ Low cost | ❌ Baud rate must match exactly | | | ✅ Long-distance capable | ❌ Slower than SPI/I2C |


In the Real World

  1. Khalti’s Payment Terminals

    • Uses UART to communicate between the MCU (e.g., STM32) and the card reader. The MCU sends AT commands via UART to authenticate transactions.
    • Why UART? Low cost, simple wiring for point-of-sale devices.
  2. Pathao Rider App’s GPS Module

    • The ESP32 MCU talks to the GPS module (e.g., NEO-6M) via UART to fetch latitude/longitude. The module sends NMEA sentences like $GPGGA asynchronously.
    • Worked Example: If the GPS sends $GPGGA,123519,4236.1234,N,..., the MCU parses this string to update the rider’s location.
  3. Daraz’s Warehouse Inventory Sensors

    • SPI connects RFID readers to the central MCU for fast, full-duplex data transfer. Each shelf’s RFID tag reader (slave) sends inventory updates to the master MCU without collisions.
    • Why SPI? Speed (up to 10 Mbps) and direct wiring reduce latency in high-throughput warehouses.

2. SPI: Synchronous, Fast, and Complex

How it works:

  • 4+ wires:
    • SCLK (Serial Clock): Master-generated clock.
    • MOSI (Master Out Slave In): Master → Slave.
    • MISO (Master In Slave Out): Slave → Master.
    • SS/CS (Slave Select): Chip select (1 slave per line).
  • Full-duplex: Send/receive simultaneously.
  • No addressing: Each slave needs a dedicated SS line.

Real-world use:

  • NTC’s Smart Meters
    • SPI connects the MCU to the energy measurement IC (e.g., ADE7758). The meter sends voltage/current data at high speed (1 Mbps) for billing accuracy.
  • eSewa’s QR Code Scanners
    • The scanner’s camera module (e.g., OV7670) uses SPI to stream pixel data to the MCU for real-time QR decoding.

Worked Example: Problem: Design SPI communication between an Arduino (master) and an SD card module (slave) to read a file. Steps:

  1. Pull SS low to select the SD card.
  2. Send clock pulses on SCLK while shifting data MSB-first on MOSI.
  3. Read response on MISO.
  4. Pull SS high to deselect.
sequenceDiagram
    participant Master as Arduino (Master)
    participant Slave as SD Card (Slave)
    Master->>Slave: SS = LOW (Select)
    loop Data Transfer
        Master->>Slave: SCLK pulse + MOSI (MSB first)
        Slave-->>Master: MISO (data)
    end
    Master->>Slave: SS = HIGH (Deselect)

Advantages/Disadvantages: | SPI | ✅ Fastest (up to 10+ Mbps) | ❌ Dedicated wiring per slave | | | ✅ Full-duplex | ❌ No built-in addressing | | | ✅ No clock synchronization issues | ❌ More pins used |


3. I2C: Multi-Device, Minimal Wiring

How it works:

  • 2 wires:
    • SDA (Serial Data): Bidirectional.
    • SCL (Serial Clock): Shared clock line.
  • 7-bit or 10-bit addressing: Up to 128 devices (7-bit) or 1024 (10-bit).
  • Half-duplex: Only one device transmits at a time.
  • Start/Stop conditions: SDA transition while SCL is high.

Real-world use:

  • NEPSE Stock Terminals
    • I2C connects the real-time clock (RTC) module (e.g., DS3231) to the MCU. The RTC keeps time even when power is off, critical for stock market data timestamps.
  • Bank ATMs
    • I2C links the keypad, display, and card reader to the main MCU. The keypad (slave 0x20) sends key presses, while the display (slave 0x38) receives commands.

Worked Example: Problem: Write I2C code to read a temperature from an LM75 sensor (address 0x48). Steps:

  1. Send start condition.
  2. Send device address + write (0x48 << 1 | 0).
  3. Send register address (0x00 for temp).
  4. Send repeated start.
  5. Send device address + read (0x49).
  6. Read 2 bytes (temp data).
  7. Send stop condition.
stateDiagram-v2
    [*] --> Start
    Start --> SendDeviceAddrWrite
    SendDeviceAddrWrite --> SendRegAddr
    SendRegAddr --> RepeatedStart
    RepeatedStart --> SendDeviceAddrRead
    SendDeviceAddrRead --> ReadData
    ReadData --> Stop
    Stop --> [*]

Advantages/Disadvantages: | I2C | ✅ Minimal wiring (2 wires) | ❌ Limited speed (~400 kbps standard) | | | ✅ Multi-master/slave support | ❌ Collision risk (arbitration needed) | | | ✅ Addressable devices | ❌ Complex protocol (ACK/NACK) |


Protocol Comparison Table

Feature UART SPI I2C
Wiring 2 wires (TX/RX) 4+ wires 2 wires (SDA/SCL)
Duplex Half/Full* Full Half
Speed Slow (115 kbps) Fast (10+ Mbps) Medium (400 kbps)
Devices 1:1 1:many (dedicated) 1:many (addressed)
Clock No (asynchronous) Master-provided Shared
Error Handling Parity/None None ACK/NACK
Cost Low Medium Low

*UART can be full-duplex with separate TX/RX pairs.


Hardware Wiring: How to Connect Them

UART

MCU TX ────┬─────► Sensor RX
           │
MCU RX ────┬─────◄ Sensor TX

SPI

MCU SCLK ────┬─────► Slave SCLK
MCU MOSI ────┬─────► Slave MOSI
MCU MISO ────┬─────◄ Slave MISO
MCU SS    ────┬─────► Slave SS

I2C

MCU SDA ────┬─────►► Slave1 SDA
            │       │
MCU SCL ────┴─────►► Slave2 SCL

Exam Tip

  1. Protocol Selection:

    • Asked: "Which protocol would you use for a weather station with 5 sensors and a display?"
    • Answer: I2C (minimal wiring for multiple devices) or SPI (if speed is critical for the display).
  2. Frame/Byte Calculation:

    • Asked: "Draw the UART frame for ASCII 'A' (65) at 115200 baud with even parity."
    • Solution: Show start bit, 8 data bits (01000001), parity bit (1 for even), stop bit.
  3. Wiring Diagrams:

    • Asked: "Connect an Arduino to an OLED display using SPI. Label all pins."
    • Must include: SCLK, MOSI, MISO, SS, and GND/VCC.
  4. Speed vs. Complexity:

    • Asked: "Why does SPI use more pins than I2C?"
    • Answer: SPI requires dedicated SS lines per slave; I2C uses addressing on 2 wires.
  5. Real-world Scenarios:

    • Asked: "How does a bank ATM use I2C?"
    • Answer: Connects keypad, display, and card reader to the MCU via I2C for minimal wiring and multi-device support.

Key Formula to Remember:

  • UART Baud Rate Calculation: Example: For 9600 baud, each bit takes .

Common Pitfalls:

  • Forgetting to pull SS high in SPI after communication (slave stays selected).
  • Not enabling internal pull-ups on I2C lines (SDA/SCL must be high when idle).
  • Mismatched baud rates in UART causing garbled data.

Based on the PU BE Computer (PU) syllabus for Embedded System (ELX320), unit 8.

Discussion

Loading…