Skip to content
On this page

UART, I2C and SPI — what the three buses are, and how to check a pin before you wire it

Question this page answers: “UART vs I2C vs SPI — what’s actually different, and before I wire a device to a pin, how do I know that pin is legal, free and safe on my board?”

The one-line differences

BusLinesWho talks whenTypical use
UARTTX, RX (async, both directions)both sides whenever (agreed baud)console/serial, modems
I2CSDA, SCL (+shared bus, addresses)controller addresses a peripherallow-speed sensors, config EEPROMs
SPIMOSI, MISO, SCK, CS (+1 per device)controller selects, full duplexfast flash, displays, SD

UART is the typical point-to-point choice (two devices); I2C hangs many devices on two shared wires; SPI is usually the fastest of the three but spends an extra select wire per device.

Where they hide on these boards

  • ESP32-S3-DevKitC-1 — the USB-to-UART bridge talks to the chip over UART0 (U0TXD/U0RXD on GPIO43/44 in the header table). That is why “the serial console” works without any wiring: the bridge is permanently wired to those pins. Several J3 pins also carry FSPI* names — the chip’s flash-SPI function group.
  • ESP32-DevKitC — D0/D1/D2/D3/CMD/CLK are an SPI port in action: the SPI flash wired to the chip. On WROVER variants the same SPI bus carries PSRAM — which is why GPIO16/17 disappear there (see the board page).
  • Pico / Pico 2 — both boards’ SDK headers default UART0 to GP0/1 and I2C0 to GP4/5 (pico.h and pico2.h, commit 079c6f39). What PIO, the programmable state machines, can do is a different question — a software implementation of the protocol, separate from the hardware UART/I2C/SPI blocks.

Before you wire: the three-layer pin check

“Can I use GP_n for my bus?” is three separate questions. Check them in order, because each layer can veto the pin on its own:

  1. The SDK default — a software convention. PICO_DEFAULT_I2C_SDA_PIN 4 means the SDK’s board header chose GP4 for you; you can change it in code. Defaults are per-board files, and they prove nothing about which pins are legal — nor do they configure anything: the macro names a default choice, and initializing the controller and selecting pin functions is your application’s (or framework’s) job.
  2. The chip’s mux table — the hardware fact. A hardware UART/I2C/SPI block exists only on a fixed set of mux pins per chip. For RP2040 this site pins the official io_bank0.h: UART0 TX/RX sits on GP0/1, with GP12/13 and GP16/17 as further UART0 options — never on an arbitrary GP pin. For RP2350 this site has not yet pinned the official mux table to a fixed source, so this page does not list its legal combinations — check the RP2350 datasheet; the Pico 2 board header’s defaults (GP0/1, GP4/5) are layer-1 facts, not proof that other pins are illegal or legal.
  3. The board’s wiring — what actually reaches the header, and what is already occupied. This is the board page’s claim table: physical header position, board-internal functions (LED, VBUS sense…), per revision.

And before current flows: all four boards’ GPIO are 3.3 V logic (see 3.3 V and 5 V), share a common ground with the peripheral, and an I2C bus needs pull-ups to 3.3 V on SDA/SCL (open-drain lines) — many sensor modules carry them on-board; check yours rather than assuming.

Worked example: GP4/GP5 for an I2C sensor

The check, done honestly for both generations:

  1. Layer 1 — pico.h and pico2.h set PICO_DEFAULT_I2C_SDA_PIN 4, PICO_DEFAULT_I2C_SCL_PIN 5: on both boards the SDK’s default pin choice for I2C0 is GP4/5 — the macros name default pins, they do not initialize the controller or mux the pin functions.
  2. Layer 2 — GP4/GP5 are the documented defaults for both generations’ chips. For RP2040 the pinned mux table confirms I2C0 on GP4/5; for RP2350 this site has not verified a second-layer mux source, so the header default is not recycled here as mux proof — the full legal-pin set stays datasheet territory.
  3. Layer 3 — the Pico and Pico 2 records show GP4/GP5 brought out on the J1 header with no board-internal function on them.

Conclusion: on both generations GP4/5 is the documented default pair, and both boards bring it out unoccupied — wiring the module there means following the SDK’s default instead of fighting it. That is a head start, not a guarantee: the controller still needs initializing, pull-ups to 3.3 V, a common ground and the right bus address before the first transaction.

The counter-example: GP25 is not a free pin

The mirror-image mistake: picking a pin because it is near the sensor and skipping layer 3. On both the Pico and the Pico 2, GP25 is wired to the on-board LED and is not brought out on the J1/J2 header (fixed records on both board pages) — the SDK will let you write the code, and layers 1 and 2 never complain, but there is no header pin to wire to, and driving that line as a bus fights the board’s own LED. The same layer vetoes harder on the ESP32-S3-DevKitC-1: GPIO43/44 look like “UART0’s default pins”, and they are — permanently occupied by the USB-to-UART bridge. Use another UART instance for your own link, or you will fight the console for the pins.

The one trap to remember

Bus controllers are cheap; pins are the scarce resource. The flash-SPI pins on the DevKitC are a bus you must not share; the Pico’s “default” pins can move — within each peripheral’s legal mux pins for that chip; the DevKitC-1’s U0TXD/U0RXD are already taken by the bridge.

What this page cannot tell you

  • Electrical/protocol details (pull-up values, clock stretching, SPI modes 0-3) — chip datasheet territory; this page is the orientation layer.
  • Which UART/I2C/SPI hardware instances exist on each chip — see the chip pages’ fixed-source records and vendor datasheets.
  • The RP2350’s full legal mux combinations — not yet pinned to a fixed official source here; until then this page asserts only its documented defaults.

Sources