Arduino library · Core

The Arduino SPI library: fast four-wire talk with chips

SPI.h is the Arduino library for the Serial Peripheral Interface, the bus SD cards, RFID readers, TFT screens, radios and many ADCs use. It has a clock line (SCK), a line out of the Arduino (MOSI, or COPI), a line back in (MISO, or CIPO), and one chip-select line per device that the sketch pulls LOW to talk to that device and HIGH when it is done.

Built in on Mokxi: #include <SPI.h> and it builds, with nothing to install. Free, and no account needed.

What SPI does

Every SPI byte is an exchange: transfer() clocks one byte out and returns the byte that came back at the same time. Devices differ in the clock speed they accept, which edge they sample on (the four SPI modes) and whether the most or least significant bit goes first, so modern sketches wrap each conversation in beginTransaction(SPISettings(...)) and endTransaction().

The bus pins are fixed by the chip: 13, 12 and 11 on an Uno or Nano, 52, 50 and 51 on a Mega, and only the ICSP header on a Leonardo. Chip select can be any pin, but on AVR boards pin 10 (53 on the Mega) must stay an output or the chip can drop out of controller mode.

Library Manager nameSPI
AuthorArduino
Include#include <SPI.h>
Boardsevery board Mokxi compiles for
In the simulatorSimulated: it runs against the part the way it does on the bench.
Parts it drivesRFID reader, MFRC522, microSD card module

Install it

It builds on every board Mokxi compiles for.

In Mokxi it is built in: #include <SPI.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board it comes with the board package (Arduino), so the Arduino IDE has it as soon as the board is installed: there is nothing to add from the Library Manager.

ESP32-C3 · Arduino Uno · Arduino Nano · Arduino Mega 2560 · Arduino Leonardo · SparkFun Pro Micro · Arduino Micro · ESP32-C6 · ATtiny85 · Raspberry Pi Pico · Raspberry Pi Pico W · Seeed XIAO SAMD21 · STM32 · STM32 Nucleo-F411RE · STM32 Blue Pill · micro:bit V2 · Arduino Uno R4 · ESP32 DevKit · ESP32-S3-DevKitC-1 · ESP8266 NodeMCU · Arduino Pro Mini 3.3 V · Seeed XIAO ESP32-C3 · ESP32-C3 SuperMini · Seeed XIAO ESP32-C6 · ESP32-DevKitC V4 · LOLIN32 Lite · Wemos D1 R32 · Cheap Yellow Display · TTGO T-Display · Seeed XIAO ESP32-S3 · Arduino Nano ESP32 · Arduino Nano RP2040 Connect · Seeed XIAO RP2040 · Waveshare RP2040-Zero · Arduino Uno R4 WiFi

The calls you will use

In the order a sketch meets them.

SPI.begin()

Sets SCK, MOSI and SS up as outputs and starts the bus. Call it once in setup() before any transfer.

SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0))

Claims the bus with one device’s settings: clock speed in hertz, bit order and SPI mode 0 to 3.

SPI.transfer(0x9F)

Sends one byte and returns the byte received at the same time. Send a dummy byte, often 0x00 or 0xFF, to read.

digitalWrite(CS, LOW);
SPI.transfer(0x9F);            // command
byte id = SPI.transfer(0x00);  // reply
digitalWrite(CS, HIGH);

SPI.transfer16(0x1234)

Sends and receives sixteen bits in one call, most significant byte first by default.

SPI.endTransaction()

Releases the bus so another library (an SD card on the same pins, say) can use its own settings.

SPI.end()

Turns the bus off and leaves the pins as they are.

Example: RC522 RFID reader (SS 10, RST 9)

On the Arduino Uno R3. It runs in the browser exactly as printed.

sketch.ino · Arduino Uno R3
// RC522 RFID reader: hold a card to it and see its ID.
//
//   RC522 SDA (SS) -> pin 10    RC522 SCK  -> pin 13
//   RC522 MOSI     -> pin 11    RC522 MISO -> pin 12
//   RC522 RST      -> pin 9     RC522 3.3V -> 3.3V   GND -> GND
//
// The reader talks SPI, the bus on pins 11, 12 and 13 that every SPI part on
// an Uno shares. SDA is the chip-select line that picks this reader. Every
// card carries a serial number, its UID, which the reader can read without
// knowing anything else about the card.
//
// The RC522 runs on 3.3 V. Never wire its supply to 5 V.
//
// Click the reader and pick a card to hold to it.

#include <SPI.h>
#include <MFRC522.h>

const int SS_PIN = 10;
const int RST_PIN = 9;

MFRC522 reader(SS_PIN, RST_PIN);

void setup() {
  Serial.begin(9600);
  SPI.begin();
  reader.PCD_Init();
  Serial.println("Mokxi Uno: RC522 on SS 10 and RST 9. Hold a card to the reader.");
}

void loop() {
  if (!reader.PICC_IsNewCardPresent()) return;
  if (!reader.PICC_ReadCardSerial()) return;
  Serial.print("Card UID:");
  for (byte i = 0; i < reader.uid.size; i++) {
    Serial.print(reader.uid.uidByte[i] < 0x10 ? " 0" : " ");
    Serial.print(reader.uid.uidByte[i], HEX);
  }
  Serial.println();
  reader.PICC_HaltA();
}

Open it in the editor, wired and ready to run · RC522 RFID reader (SS 10, RST 9): the project page

Common errors and how to fix them

Every byte read back is 0xFF or 0x00

The device is not answering: its chip-select pin is not going LOW, MISO is not connected, or the device has no power. Check that the sketch drives CS LOW before transfer() and HIGH after.

Garbage data, but some bytes look almost right

The SPI mode or bit order does not match the device’s data sheet, or the clock is too fast for long jumper wires. Set the right mode in SPISettings and try a slower clock such as 1 MHz.

Two SPI devices work alone but not together

Each needs its own chip-select pin, held HIGH when it is not in use. A device whose CS floats LOW answers along with the other one and corrupts MISO. Use beginTransaction() for each so their settings do not leak.

An SPI module works on an Uno but not on a Leonardo with the same wiring

Pins 11, 12 and 13 are not SPI on a Leonardo. Its SCK, MISO and MOSI are only on the 6-pin ICSP header, so wire the module there and keep chip select on any free pin.

Try SPI without installing anything

Open the example, change the sketch, and keep your version in a free account.