An RFID attendance register or door lock often grows into a Mega project — a keypad, a display, a relay, a buzzer and a reader need a lot of pins. The thing that trips people is that the Mega’s SPI pins moved to 50–53.
Wire the RC522 there, through a level shifter for the four signals going into it. The sketch enrols each new card on its first tap and greets it on later taps — a starting point for an attendance list.
Wiring
| Arduino Mega 2560 | RC522 RFID reader (MFRC522, 13.56 MHz) | Wire | Notes |
|---|---|---|---|
| 3.3V | 3.3V | red | The Mega’s 3.3 V regulator gives about 50 mA; the RC522 needs about 26 mA. It also feeds the shifter’s LV side. |
| GND | GND | black | |
| D50 | MISO | blue | 3.3 V output — read directly. |
| D51 | MOSI | green | Via level shifter |
| D52 | SCK | yellow | Via level shifter |
| D53 | SDA | purple | Via level shifter — SDA = chip select (SS). |
| D49 | 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 on the Mega is 50 (MISO), 51 (MOSI), 52 (SCK), 53 (SS) — not 11/12/13 as on the Uno. Uno RFID tutorials wired to 11–13 do nothing on a Mega.
- The same SPI signals are on the 6-pin ICSP header, which is how Uno-style shields reach them.
- Pin 53 must stay an OUTPUT while the Mega is SPI master; using it as the RC522’s chip-select takes care of that.
- Unlike the Nano, the Mega has a proper 3.3 V regulator, so the RC522 can run from the 3.3V pin.
- The enrolled list lives in RAM and is lost at reset. For a real lock, store the UIDs in EEPROM (the Mega has 4 KB).
Code
// RC522 RFID reader on an Arduino Mega 2560's SPI pins (50-53).
// 3.3V → 3.3V, GND → GND, MISO → D50, and through a level shifter: MOSI ← D51, SCK ← D52,
// SDA(SS) ← D53, RST ← D49. Keeps a list of up to 20 known cards in RAM.
#include <SPI.h>
#include <MFRC522.h>
const uint8_t SS_PIN = 53;
const uint8_t RST_PIN = 49;
MFRC522 rfid(SS_PIN, RST_PIN);
const uint8_t MAX_CARDS = 20;
uint32_t known[MAX_CARDS];
uint8_t knownCount = 0;
uint32_t uidToLong(const MFRC522::Uid &u) {
uint32_t v = 0;
for (uint8_t i = 0; i < 4 && i < u.size; i++) v = (v << 8) | u.uidByte[i];
return v;
}
void setup() {
Serial.begin(115200);
SPI.begin();
rfid.PCD_Init();
byte v = rfid.PCD_ReadRegister(MFRC522::VersionReg);
Serial.print(F("RC522 version: 0x"));
Serial.println(v, HEX);
Serial.println(F("Tap a card: first tap enrols it, later taps say 'welcome back'"));
}
void loop() {
if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) return;
uint32_t id = uidToLong(rfid.uid);
Serial.print(F("UID 0x"));
Serial.print(id, HEX);
bool found = false;
for (uint8_t i = 0; i < knownCount; i++) found |= known[i] == id;
if (found) {
Serial.println(F(" welcome back"));
} else if (knownCount < MAX_CARDS) {
known[knownCount++] = id;
Serial.print(F(" enrolled as card #"));
Serial.println(knownCount);
} else {
Serial.println(F(" list full"));
}
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
}// RC522 RFID reader on an Arduino Mega 2560's SPI pins (50-53).
// 3.3V → 3.3V, GND → GND, MISO → D50, and through a level shifter: MOSI ← D51, SCK ← D52,
// SDA(SS) ← D53, RST ← D49. Keeps a list of up to 20 known cards in RAM.
#include <SPI.h>
#include <MFRC522.h>
const uint8_t SS_PIN = 53;
const uint8_t RST_PIN = 49;
MFRC522 rfid(SS_PIN, RST_PIN);
const uint8_t MAX_CARDS = 20;
uint32_t known[MAX_CARDS];
uint8_t knownCount = 0;
uint32_t uidToLong(const MFRC522::Uid &u) {
uint32_t v = 0;
for (uint8_t i = 0; i < 4 && i < u.size; i++) v = (v << 8) | u.uidByte[i];
return v;
}
void setup() {
Serial.begin(115200);
SPI.begin();
rfid.PCD_Init();
byte v = rfid.PCD_ReadRegister(MFRC522::VersionReg);
Serial.print(F("RC522 version: 0x"));
Serial.println(v, HEX);
Serial.println(F("Tap a card: first tap enrols it, later taps say 'welcome back'"));
}
void loop() {
if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) return;
uint32_t id = uidToLong(rfid.uid);
Serial.print(F("UID 0x"));
Serial.print(id, HEX);
bool found = false;
for (uint8_t i = 0; i < knownCount; i++) found |= known[i] == id;
if (found) {
Serial.println(F(" welcome back"));
} else if (knownCount < MAX_CARDS) {
known[knownCount++] = id;
Serial.print(F(" enrolled as card #"));
Serial.println(knownCount);
} else {
Serial.println(F(" list full"));
}
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
}Library: MFRC522 (GithubCommunity) — compiled with MFRC522 1.4.12.
Expected serial output
RC522 version: 0x92
Tap a card: first tap enrols it, later taps say 'welcome back'
UID 0x7A3C912B enrolled as card #1
UID 0x7A3C912B welcome backRC522 version: 0x92 Tap a card: first tap enrols it, later taps say 'welcome back' UID 0x7A3C912B enrolled as card #1 UID 0x7A3C912B welcome back
Common errors
Version 0x00 or 0xFF
SPI on 11–13 instead of 50–52, or the shifter not powered on both sides. Full fix.
Reads the first card, then nothing
Missing PICC_HaltA(), or a weak 3.3 V supply. Keep other loads off the 3.3V pin.