HW protocol basics UART SPI I2C MDIO CAN - MarekBykowski/readme GitHub Wiki

Hardware Protocols Cheat Sheet


Quick Comparison

Property UART SPI I2C MDIO CAN
Wires 2 minimal (TX/RX), 4 with flow control (TX/RX/RTS/CTS) 4 (MOSI/MISO/CLK/CS) 2 (SDA/SCL) 2 (MDC/MDIO) 2 (CANH/CANL)
Total wire count 2 min, 3 with GND, 5 with GND+RTS/CTS 4 + GND + 1 CS per extra device 2 + GND 2 + GND 2 + GND
Topology point-to-point point-to-point (1 master, N slaves via CS) multi-master bus point-to-point multi-master bus
Speed up to 921600 baud up to 100MHz 100kHz / 400kHz / 3.4MHz 2.5MHz 1Mbps
Max Distance ~15m (RS232), ~1200m (RS485) <1m (PCB traces) ~1m typical, 5m max <1m (PCB only) ~40m @1Mbps
Clock none (async) master provides master provides master provides none (async)
Addressing none CS pin per device 7-bit address 5-bit PHY addr 11/29-bit message ID
Duplex full duplex full duplex half duplex half duplex half duplex
Use in drones FC↔companion, telemetry IMU, flash, radio sensors, EEPROM, PMU Ethernet PHY config automotive, some UAVs

UART β€” Universal Asynchronous Receiver Transmitter

Key Facts

  • Asynchronous β€” no clock wire, both sides agree on baud rate beforehand
  • Point-to-point β€” TX of one connects to RX of other
  • Full duplex β€” can send and receive simultaneously
  • Frame format β€” configurable: data bits, parity, stop bits

Frame Format

idle  [start][d0][d1][d2][d3][d4][d5][d6][d7][parity][stop]  idle
  1      0    ←────────── 8 data bits ──────────►              1

start bit = always 0  (marks beginning)
stop bit  = always 1  (marks end, returns to idle)
parity    = optional error check (even/odd/none)

Configuration (must match both sides)

115200 8N1   ← most common
  |    β”‚β”‚---- 1 stop bit
  |    β”‚----- N = no parity
  |    ------ 8 data bits
  ----------- boud rate

921600 8N1   ← high speed MAVLink over UART
57600  8N1   ← SiK telemetry radio

Baud Rate β€” how timing works

baud = symbols per second
115200 baud β†’ 1 bit = 1/115200 = 8.68 Β΅s

Both sides must agree β€” no clock to synchronise on
Tolerance: typically Β±2% β€” beyond that bits are misread

Use in Drones

RPi                         Flight Controller
─────────────────────────   ─────────────────
TX  (GPIO14) ─────────────► RX
RX  (GPIO15) ◄───────────── TX
RTS (GPIO17) ─────────────► CTS   (optional flow control)
CTS (GPIO16) ◄───────────── RTS   (optional flow control)
GND          ─────────────── GND  ← always connect!

Common Bugs

1. Crossed TX/RX  — TX must go to RX, not TX→TX
2. Voltage mismatch β€” RPi is 3.3V, some devices 5V β†’ level shifter needed
3. Missing GND     β€” floating reference β†’ garbage data
4. Baud mismatch   β€” framing errors, garbage characters
5. No flow control β€” buffer overflow at high rates

SPI β€” Serial Peripheral Interface

Key Facts

  • Synchronous β€” master provides clock (SCLK)
  • Full duplex β€” MOSI and MISO simultaneously
  • Point-to-point β€” one CS pin per slave
  • Fast β€” up to 100MHz, fastest of the three

Wires

Master          Slave
  MOSI ────────► MOSI   (Master Out Slave In  β€” data to slave)
  MISO ◄──────── MISO   (Master In Slave Out  β€” data from master)
  SCLK ────────► SCLK   (clock β€” always from master)
  CS   ────────► CS     (Chip Select β€” active low, selects slave)
  GND  ────────── GND

Multiple Slaves

Master ──MOSI──┬──────┬──────┐
               β”‚      β”‚      β”‚
         Slave1β”‚ Slave2β”‚ Slave3β”‚
               β”‚      β”‚      β”‚
Master ──CS0β”€β”€β”€β”˜      β”‚      β”‚   CS0 selects Slave1
Master ──CS1β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚   CS1 selects Slave2
Master ──CS2β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   CS2 selects Slave3

MOSI, MISO, SCLK shared β€” CS selects which slave is active

Transfer β€” full duplex

CS goes LOW  (select slave)
    ↓
Master drives MOSI bit by bit on each clock edge
Slave  drives MISO bit by bit simultaneously
    ↓
CS goes HIGH (deselect)

Both sides send AND receive at the same time
If you only want to write β†’ ignore MISO
If you only want to read  β†’ send dummy bytes on MOSI

Clock Modes (CPOL / CPHA)

CPOL = clock polarity (idle state of clock)
CPHA = clock phase (when data is sampled)

Mode 0 (CPOL=0, CPHA=0) β€” most common
Mode 1 (CPOL=0, CPHA=1)
Mode 2 (CPOL=1, CPHA=0)
Mode 3 (CPOL=1, CPHA=1)

Must match between master and slave β€” check datasheet!

Use in Drones

IMU (MPU-6000, ICM-42688)  β†’ SPI up to 20MHz
SPI flash (W25Q128)        β†’ store logs, parameters
Radio modules (nRF24, CC2500)
SD card                    β†’ SPI mode

I2C β€” Inter-Integrated Circuit

Key Facts

  • Synchronous β€” master provides clock (SCL)
  • Half duplex β€” one wire (SDA) for data both directions
  • Multi-master bus β€” multiple masters possible
  • Addressed β€” 7-bit address (128 devices) or 10-bit (1024)
  • Slower β€” 100kHz standard, 400kHz fast, 3.4MHz high-speed
  • Open drain β€” needs pull-up resistors on SDA and SCL

Wires

Master          Slave(s)
  SDA ◄────────► SDA   (data β€” bidirectional, open drain)
  SCL ────────► SCL   (clock β€” from master)
  GND ────────── GND

Pull-up resistors to VCC on both SDA and SCL
Typical: 4.7kΞ© for 100kHz, 2.2kΞ© for 400kHz

Transaction β€” Write

START  [ADDR 7-bit][W=0]  ACK  [DATA byte]  ACK  [DATA byte]  ACK  STOP
  ↑                         ↑                ↑
master generates          slave ACKs       slave ACKs

START = SDA falls while SCL high  (unique condition)
STOP  = SDA rises while SCL high  (unique condition)
ACK   = slave pulls SDA low on 9th clock pulse
NACK  = slave leaves SDA high (error or done)

Transaction β€” Read

START  [ADDR 7-bit][R=1]  ACK  [DATA byte]  ACK  [DATA byte]  NACK  STOP
                            ↑    ↑
                         slave  slave drives SDA
                         ACKs   master ACKs each byte
                                master NACK on last byte β†’ STOP

Repeated Start β€” write then read without releasing bus

START [ADDR][W] ACK [REG_ADDR] ACK  Sr  [ADDR][R] ACK [DATA] NACK STOP
                                     ↑
                               Repeated START β€” no STOP in between
                               used to set register address then read it

Use in Drones

Barometer (MS5611, BMP280)     β†’ I2C
Magnetometer (HMC5883, QMC5883)β†’ I2C
OLED display                   β†’ I2C
EEPROM (AT24C256)              β†’ I2C
Power management (INA226)      β†’ I2C
GPS (some modules)             β†’ I2C or UART

I2C vs SPI β€” when to use which

Situation Choose
Many devices, few pins I2C
High speed needed SPI
Long distances SPI (more noise immune)
Simple sensors I2C
Flash memory SPI
Already have SPI bus SPI (add CS pin)

MDIO β€” Management Data Input/Output

Key Facts

  • Ethernet PHY management β€” configures and monitors Ethernet PHY chips
  • 2 wires only β€” MDC (clock) and MDIO (bidirectional data)
  • Slow β€” 2.5MHz max
  • Addressed β€” 5-bit PHY address (32 PHYs max), 5-bit register address
  • Used in your Tieto work β€” Ethernet PHY bring-up

Wires

MAC / CPU       Ethernet PHY
  MDC  ────────► MDC    (Management Data Clock β€” from MAC)
  MDIO ◄────────►MDIO   (Management Data β€” bidirectional)

Frame Format

Read:
  PRE(32 ones) ST(01) OP(10) PHYAD(5) REGAD(5) TA(Z0) DATA(16) IDLE

Write:
  PRE(32 ones) ST(01) OP(01) PHYAD(5) REGAD(5) TA(10) DATA(16) IDLE

PRE   = preamble β€” 32 ones (synchronise PHY)
ST    = start of frame (01)
OP    = operation (10=read, 01=write)
PHYAD = PHY address (which PHY chip)
REGAD = register address (which register)
TA    = turnaround (bus direction change)
DATA  = 16-bit register value

Common PHY Registers

Reg 0  = Basic Control    (reset, speed, duplex, autoneg)
Reg 1  = Basic Status     (link up/down, autoneg complete)
Reg 2  = PHY ID 1         (OUI upper 16 bits)
Reg 3  = PHY ID 2         (OUI lower 6 bits + model + revision)
Reg 4  = Autoneg Advertise (what speeds this PHY supports)
Reg 5  = Autoneg Partner   (what link partner advertises)

Use

// Linux kernel β€” read PHY register
int val = mdiobus_read(bus, phy_addr, MII_BMSR);  // Basic Status
if (val & BMSR_LSTATUS) {
    printk("link is up\n");
}

CAN β€” Controller Area Network

Key Facts

  • Differential bus β€” CANH and CANL (noise immune)
  • Multi-master β€” any node can transmit
  • Message-based β€” no addresses, nodes filter by message ID
  • Priority β€” lower ID = higher priority (wins bus arbitration)
  • Error detection β€” CRC, bit stuffing, acknowledgement
  • Speed β€” up to 1Mbps (classic), 8Mbps (CAN FD)

Wires

Node A    Node B    Node C
  CANH ────────────────────── 120Ξ© terminator
  CANL ────────────────────── 120Ξ© terminator
  GND  ────────────────────── (common ground)

Differential: CANH - CANL
  dominant  (0): CANH=3.5V, CANL=1.5V β†’ difference = 2V
  recessive (1): CANH=CANL=2.5V       β†’ difference = 0V

Bus Arbitration β€” non-destructive

Two nodes transmit simultaneously:
  Node A sends ID: 0b00000001010  (lower = higher priority)
  Node B sends ID: 0b00000001100

Bit by bit comparison:
  bit 3: A sends 0, B sends 1
  β†’ A wins (dominant 0 overrides recessive 1)
  β†’ B detects mismatch, backs off, retries later
  β†’ A's message transmitted without corruption

Frame Format

SOFβ”‚ ID(11bit) β”‚RTRβ”‚IDEβ”‚r0β”‚DLC(4)β”‚ DATA(0-8B) β”‚ CRC(15) β”‚ACKβ”‚EOF
 1    11         1   1   1    4      0-64 bits     15       2   7

Use in Drones

Less common than UART/SPI/I2C in small drones
Used in:
  - larger UAVs with distributed avionics
  - automotive-grade components
  - UAVCAN / DroneCAN protocol (CAN-based drone protocol)
    β†’ ESC control, GPS, airspeed sensors
    β†’ replaces PWM for ESC control

Protocol Selection Guide

Need to...                          Use
──────────────────────────────────────────────────────
Connect FC to companion computer  β†’ UART (MAVLink)
Connect FC to telemetry radio     β†’ UART
Read IMU at high speed            β†’ SPI
Read barometer / magnetometer     β†’ I2C
Configure Ethernet PHY            β†’ MDIO
Many sensors, few GPIO pins       β†’ I2C
Long cable runs, noise immunity   β†’ CAN or RS-485
ESC control (modern)              β†’ DroneCAN (CAN)
ESC control (traditional)         β†’ PWM
Debug / console                   β†’ UART
SPI flash / SD card               β†’ SPI

Signal Levels

Protocol Voltage Notes
UART (RPi) 3.3V NOT 5V tolerant β€” use level shifter for 5V devices
UART (Arduino) 5V level shifter needed for 3.3V devices
SPI 3.3V or 5V match to device
I2C 3.3V or 5V open drain β€” pull-ups set voltage
CAN differential 120Ξ© termination at each end of bus
MDIO 3.3V

Oscilloscope / Logic Analyser Tips

UART: set baud rate in analyser β†’ it decodes bytes automatically
SPI:  set CPOL/CPHA, identify CS/CLK/MOSI/MISO
I2C:  analyser auto-detects start/stop, shows address + data
CAN:  set bit rate, analyser shows ID + DLC + data

Common debug: Saleae Logic, sigrok/PulseView (open source)
On Cortex-M: ITM trace, SWO pin for printf without UART

Generated during prep session Β· Swarmer Integration Engineer Β· 2026