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 Leonardo | RC522 RFID reader (MFRC522, 13.56 MHz) | Wire | Notes |
|---|---|---|---|
| 3.3V | 3.3V | red | About 50 mA available; the RC522 needs ~26 mA. Also feeds the shifter’s LV side. |
| GND | GND | black | |
| MISO | MISO | blue | ICSP pin 1. RC522 output (3.3 V) — direct. |
| SCK | SCK | yellow | Via level shifter — ICSP pin 3. |
| MOSI | MOSI | green | Via level shifter — ICSP pin 4. |
| D10 | SDA | purple | Via level shifter — SDA = chip select. |
| D9 | RST | orange | Via 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 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
}// 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
RC522 version: 0x92
Card 7A3C912B
Card 04A1B2C3D4E5F6RC522 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.