Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

RC522 RFID with Arduino Leonardo — ICSP SPI and a card-to-keyboard reader

Wire an RC522 to an Arduino Leonardo through the ICSP header’s SPI pins with a level shifter, and type each card’s UID into a spreadsheet as a USB keyboard.

Arduino C++Verified — core avr 1.8.8, MFRC522 1.4.12, 3 Nov 2026Compile-only

Community draft — report a mistake

On the Leonardo, the RC522 wiring is the main difference from an Uno: hardware SPI is only on the ICSP header in the middle of the board’s edge. MISO, SCK and MOSI come from there; chip-select (D10) and reset (D9) can be any pins.

The Leonardo’s native USB adds something an Uno can’t do: the sketch types each card’s UID into whatever window is active, followed by Enter, just like a commercial USB RFID reader.

Wiring

Arduino LeonardoOnly the pins used are shown · 5 V logicRC522 RFID reader (MFRC522, 13.56 MHz)LV⇄HVLV⇄HVLV⇄HVLV⇄HV3.3VGNDD9D10MISO · 14SCK · 15MOSI · 16SDASCKMOSIMISOIRQ (not connected)GNDRST3.3V
Also needed: 4-channel BSS138 level shifter, Female–female jumpers for the ICSP header.
Every connection
Arduino LeonardoRC522 RFID reader (MFRC522, 13.56 MHz)WireNotes
3.3V3.3VredAbout 50 mA available; the RC522 needs ~26 mA. Also feeds the shifter’s LV side.
GNDGNDblack
MISOMISOblueICSP pin 1. RC522 output (3.3 V) — direct.
SCKSCKyellowVia level shifter — ICSP pin 3.
MOSIMOSIgreenVia level shifter — ICSP pin 4.
D10SDApurpleVia level shifter — SDA = chip select.
D9RSTorangeVia level shifter — Shifter LV = 3.3V, HV = 5V, GND shared.

3.3 V only part, 5 V board. Power the RC522 from 3.3 V — never 5 V. The MFRC522 chip’s pins are not rated for 5 V either: many people wire it straight to an Uno and it works for a while, but for a build that lasts, drop the Uno’s SCK, MOSI, SDA (SS) and RST signals to 3.3 V with a level shifter or dividers. ESP32 and Pico connect directly.

Board quirks

  • SPI is only on the 2×3 ICSP header on the Leonardo. D11/D12/D13 are ordinary pins here, so Uno RFID wiring does nothing.
  • ICSP pinout (pin 1 has the dot): 1 MISO, 2 5V, 3 SCK, 4 MOSI, 5 RESET, 6 GND.
  • The card UID is typed like a USB barcode scanner (“keyboard wedge”): click a spreadsheet cell, tap a card, and the UID plus Enter appears. Good for attendance or stock lists.
  • A card UID is an identifier, not a password — don’t use it to type logins. Copying a UID to a cloned card is easy.

Code

rc522-leonardo.inoArduino C++Open in PlaygroundOpen in Playground
// RC522 RFID on an Arduino Leonardo as a USB "keyboard wedge": each card's UID is typed into
// whatever has focus (a spreadsheet for attendance), followed by Enter.
// SPI is only on the ICSP header: MISO → ICSP MISO, and through a level shifter
// SCK → ICSP SCK, MOSI → ICSP MOSI, SDA(SS) → D10, RST → D9. 3.3V → 3.3V, GND → GND.
#include <SPI.h>
#include <MFRC522.h>
#include <Keyboard.h>

const uint8_t SS_PIN = 10;
const uint8_t RST_PIN = 9;
MFRC522 rfid(SS_PIN, RST_PIN);

void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 3000) {}
  SPI.begin();
  rfid.PCD_Init();
  byte v = rfid.PCD_ReadRegister(MFRC522::VersionReg);
  Serial.print(F("RC522 version: 0x"));
  Serial.println(v, HEX);
  Keyboard.begin();
}

void loop() {
  if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) return;
  char uid[3 * 10 + 1];
  uint8_t n = 0;
  for (byte i = 0; i < rfid.uid.size && i < 10; i++) {
    const char *hex = "0123456789ABCDEF";
    uid[n++] = hex[rfid.uid.uidByte[i] >> 4];
    uid[n++] = hex[rfid.uid.uidByte[i] & 0x0F];
  }
  uid[n] = '\0';
  Serial.print(F("Card "));
  Serial.println(uid);
  Keyboard.print(uid);
  Keyboard.write(KEY_RETURN);
  rfid.PICC_HaltA();
  rfid.PCD_StopCrypto1();
  delay(1000);  // one entry per tap
}

Library: MFRC522 (GithubCommunity) — compiled with MFRC522 1.4.12.

Expected serial output

Serial Monitor · 115200Output
RC522 version: 0x92
Card 7A3C912B
Card 04A1B2C3D4E5F6

Common errors

Version 0x00 or 0xFF

SPI wired to D11–D13 instead of ICSP. Full fix.

UID typed with wrong characters

Non-US keyboard layout on the PC. Hex digits A–F and numbers are the same on most layouts; check the PC’s input language.

↑↓ to move · Enter to open