Unit D - Sensors & Buses

23. UART, I2C & SPI Reference

Choose and troubleshoot common embedded communication buses.

Estimated time 3 hours

Learning outcomes

  • Compare UART, I2C and SPI
  • Identify Uno bus pins
  • Explain addressing and chip select
  • Choose a bus for a practical requirement

Parts and preparation

Arduino Uno and any I2C/SPI modules available in the kit.

Before power: inspect wiring, confirm supply voltage and ensure all connected circuits share GND.

Libraries for this lesson

In Arduino IDE 2 open Tools → Manage Libraries…. Search by the Library Manager name and install the package by the exact author below. Similar names from other authors can use different APIs and will break the example.

IncludeLibrary Manager nameAuthorInstall note
Wire.hWireArduinoBuilt into the Arduino core. No Library Manager install required.
UART, I2C & SPI Reference instructional connection diagram
Open the diagram for a larger view. Trace every connection before building.

UART

Point-to-point asynchronous communication uses TX and RX plus common GND. It is simple and full-duplex but normally connects one partner per hardware UART.

I2C

A controller shares SDA/SCL with addressed devices. It uses two signal wires and pull-ups, making it convenient for several low-speed modules.

SPI

SCK clocks data, MOSI carries controller-to-device data, MISO returns data, and each device usually needs a CS pin. SPI is fast but uses more wires.

Uno pins

UART: D0/D1. I2C: A4/A5. SPI: D10 SS, D11 MOSI, D12 MISO, D13 SCK (also available on the ICSP header).

Wiring and safe build sequence

  1. Always connect common GND
  2. Check module logic voltage before connection
  3. Keep bus wires short in breadboard prototypes
  4. Do not assume every module is 5 V tolerant
Power rule: switch off before moving wires. Arduino I/O pins are control signals; high-current loads require a driver and suitable external supply.
#include <Wire.h>

void setup() {
  Serial.begin(9600);
  Wire.begin();
  Serial.println("I2C addresses:");
  for (byte address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    if (Wire.endTransmission() == 0) {
      Serial.print("0x");
      if (address < 16) Serial.print('0');
      Serial.println(address, HEX);
    }
  }
}

void loop() {}

How the code works

  1. The scanner attempts every valid 7-bit address.
  2. A zero return indicates an acknowledged address.

Test and record evidence

Expected result: Connected I2C devices appear as hexadecimal addresses.

Practical evidence checklist

Common faults and checks
  • No addresses: check power, GND, SDA/SCL order and pull-ups.
  • Several unexpected addresses may indicate noise or voltage problems.
Extension challenge: Create a comparison table selecting a bus for a GPS module, RTC and SD card.

Check your understanding

Q1. Which bus uses a chip-select line per device?

Show answer

SPI.

Q2. Which bus uses device addresses on two shared wires?

Show answer

I2C.