Module 7 - Displays, Buses & Signals

21. Buses on the Oscilloscope: UART, I2C & SPI

Compare UART, I2C and SPI by wiring and device selection, find their Uno pins, capture UART and I2C traffic on the oscilloscope and choose a bus for a module.

Estimated time 1 session + optional extrasIn class Week 7 · Session 32

Learning outcomes

  • Compare UART, I2C and SPI by wiring, speed and how devices are selected
  • Identify Uno hardware pins for UART, I2C and SPI
  • Explain I2C addresses and SPI chip-select
  • Choose a suitable bus for GPS, RTC and SD-style modules
  • Capture UART and I2C traffic on the oscilloscope and label start, address and ACK

Parts and preparation

Arduino Uno, the I2C LCD from Lesson 20, two-channel oscilloscope, jumpers. Any other I2C module (such as an RTC) is optional for a second scan.

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.
SPI.hSPIArduinoBuilt into the Arduino core. Used later with SD / RFID modules; not required for this lesson's sketch.
Buses on the Oscilloscope: UART, I2C & SPI instructional connection diagram

Three buses at a glance

UART, I2C and SPI are the three buses you will meet most often in this course. They all need a common GND and matching logic voltage. They differ in how many devices share the wires, whether a clock line is shared, and how a device is selected.

This lesson is a reference: use it when wiring an unfamiliar module or when a project needs more than one device on the Uno.

Three cards: UART links the Uno to one GPS with TX and RX crossed plus GND on D0/D1; I2C puts an LCD at 0x27 and an RTC at 0x68 on shared SDA and SCL on A4/A5; SPI joins an SD card by SCK, MOSI, MISO and CS on D13, D11, D12 and D10; all three share GND
UART for one partner, I2C for several low-speed modules, SPI when speed and chip-select fit.
BusSignal wires (typical)How devices are chosen
UARTTX, RX (+ GND)Usually one partner per UART
I2CSDA, SCL (+ GND)7-bit address on the shared bus
SPISCK, MOSI, MISO, CS (+ GND)Chip-select pin per device

UART

UART is asynchronous: both ends agree a baud rate (for example 9600) and send bytes without a shared clock wire. Wire TX of one device to RX of the other, RX to TX, and share GND. That crossover is easy to get wrong once.

On the Uno, hardware UART is D0 (RX) and D1 (TX). The USB Serial Monitor uses the same UART through the board USB bridge, so a GPS or other module on D0/D1 can block uploads or garble Serial output. SoftwareSerial on other pins is possible later; start by knowing D0/D1 are special.

Uno TX connected to device RX and Uno RX connected to device TX with shared GND
Cross TX to RX. Match baud. Unplug D0/D1 modules if uploads fail.

I2C

I2C is a two-wire shared bus: SDA carries data and SCL carries the clock. Several devices can share those wires because each has an address (for example LCD 0x27, RTC 0x68). Pull-up resistors hold idle lines HIGH; most modules include them (Lesson 20).

On the Uno, SDA is A4 and SCL is A5. Use Wire.h. If a device stays silent, run the I2C scanner sketch from Lesson 20 before rewriting application code.

Uno master on shared SDA and SCL lines with LCD, RTC and sensor at different I2C addresses
One SDA and one SCL for every device. Addresses keep them separate.

SPI

SPI is clocked and usually faster than I2C for bulk data. SCK is the clock, MOSI carries controller-to-device data, MISO returns device-to-controller data. Each device normally needs its own CS (chip select) pin. Only one CS is active (usually LOW) at a time; idle CS lines stay HIGH.

On the Uno, hardware SPI is D13 (SCK), D11 (MOSI), D12 (MISO). D10 is often used as SS / CS for the first device and also appears on the ICSP header. SD cards and RFID modules in later lessons use this pattern.

Uno sharing SCK MOSI MISO with an SD card on CS D10 and an RFID module on CS D7
Shared data lines; separate CS per chip. Idle CS stays HIGH.

Uno pin map

Memorize the hardware pins for this course. They are fixed on the Uno R3 - swapping them casually usually means you are no longer using the hardware peripheral.

Uno R3 drawing with the bus pins coloured: I2C on SDA/SCL next to AREF and on A4/A5, SPI on D13 SCK, D12 MISO, D11 MOSI and D10 CS, and UART on D1 TX and D0 RX
UART D0/D1, I2C A4/A5, SPI D11/D12/D13 (+ CS, often D10).
BusUno R3 pins
UARTD0 RX, D1 TX
I2CA4 SDA, A5 SCL
SPID13 SCK, D11 MOSI, D12 MISO, CS as chosen (often D10)
SPI altSame SPI signals on the ICSP header

Choosing a bus

Match the module datasheet first - you rarely get to invent the bus. When you do choose: UART for one serial partner (GPS, PC text), I2C when several sensors/displays must share two wires, SPI when you need speed or the part is SPI-only (SD, many RFID readers).

Voltage matters: a 3.3 V SPI flash or sensor may not tolerate 5 V Uno pins. Always check logic levels before connecting.

Module pin labels tell you the bus: TX and RX mean UART (GPS, D0/D1), SDA and SCL mean I2C (LCD backpack, RTC, A4/A5), SCK, MOSI, MISO and CS mean SPI (SD card, RFID, D13-D10)
Challenge anchor: GPS UART, RTC I2C, SD SPI.

Scanning the I2C bus

To list every address on the bus, use the I2C scanner sketch in Lesson 20. Run it again after adding a second device: each module should appear once (for example LCD 0x27 and RTC 0x68).

Capture it

Upload the worked sketch below with your I2C LCD wired as in Lesson 20. It sends the letter U on the UART and a short I2C 'are you there?' to the LCD every 10 ms, so the scope always has something to trigger on. Clip every probe ground to Uno GND.

UART: the line idles HIGH (5 V). A start bit pulls it LOW for one bit time (about 104 µs at 9600 baud), then eight data bits follow, least significant first, then a HIGH stop bit. U is 01010101 in binary, so it shows as an even row of alternating bits - easy to measure one bit width.

I2C: both lines idle HIGH. The start condition is SDA falling while SCL is still HIGH. Then nine SCL clocks: seven address bits plus a read/write bit (0x27 + write = 0x4E), then the ACK - on the ninth clock the LCD pulls SDA LOW to say 'I am here'. SDA rising while SCL is HIGH is the stop condition. Label start, address, ACK and stop on your capture for the logbook.

CaptureProbeSuggested settingsLook for
UART TXCH1 on D1 (TX)2 V/div, 200 µs/div, trigger CH1 falling edge at about 2.5 V, Normal or Single modeIdle HIGH, start bit LOW, ten bits per character
I2CCH1 on SCL (A5), CH2 on SDA (A4)2 V/div both, 20 µs/div, trigger CH2 (SDA) falling edgeStart (SDA falls, SCL HIGH), address byte, ACK LOW on 9th clock, stop

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
  5. Capture demo: I2C LCD VCC/GND/SDA/SCL to Uno 5 V, GND, A4, A5 (as in Lesson 20)
  6. Scope: probe grounds to Uno GND; probe tips on D1, A4 and A5 as in the Capture it table
Power rule: switch off before moving wires. Arduino I/O pins are control signals; high-current loads require a driver and suitable external supply.

Worked sketch

Download .ino

What this sketch is for: Makes steady bus traffic for the oscilloscope: one UART character and one short I2C transfer every 10 ms.

#include <Wire.h>

const byte lcdAddress = 0x27;   // your LCD address from the I2C scanner

void setup() {
  Serial.begin(9600);
  Wire.begin();
}

void loop() {
  Serial.print('U');                   // one UART character on D1 (TX)
  Wire.beginTransmission(lcdAddress);  // I2C start + address byte on A4/A5
  Wire.endTransmission();              // LCD answers with ACK, then stop
  delay(10);
}

How the code works

  1. Serial.print('U') sends one character out of D1; U (01010101) gives an even pattern of bits.
  2. beginTransmission() plus endTransmission() with no data sends only the start, address byte and stop - the same check the I2C scanner uses.
  3. delay(10) repeats the traffic often, so a Normal-mode trigger shows a steady picture.
  4. The Serial Monitor fills with UUUU - that is expected.

Test and record evidence

Expected result: The scope shows a U character on D1 (start bit then alternating bits) and an I2C transfer on A4/A5 with start, address 0x27 and an ACK.

Practical evidence checklist

Common faults and checks
  • Scanner finds no addresses: check power, GND, SDA/SCL swapped, and pull-ups.
  • Several unexpected addresses may indicate noise or voltage problems.
  • Scope trace will not hold still: use Normal (not Auto) trigger, set the level to about 2.5 V, and check you trigger on the right channel.
  • I2C has no ACK (SDA stays HIGH on the 9th clock): wrong address in the sketch - run the scanner.
  • UART upload fails: disconnect anything wired to D0/D1, then try again.
  • SPI device silent: confirm CS pin, idle HIGH on unused CS lines, and shared GND.
  • Confirm 5 V vs 3.3 V module ratings before powering.
Challenge (extension - optional): Create a comparison table selecting a bus for a GPS module, an RTC and an 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.

Q3. Which Uno pins are hardware UART?

Show answer

D0 (RX) and D1 (TX).

Q4. Why cross TX to RX on UART?

Show answer

Each side transmits on TX and listens on RX - they must meet.