ESP32)

知识库
知识库文档
/firmware/通信模块/RC522/RC522 RFID模块代码例程 (Arduino/STM32/ESP32).md

文档

RC522 RFID模块代码例程


例程1:Arduino (MFRC522 库)

依赖:安装 MFRC522 库(作者 miguelbalboa)

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

#define SS_PIN   10   // 片选
#define RST_PIN  9    // 复位

MFRC522 mfrc522(SS_PIN, RST_PIN);

void setup() {
    Serial.begin(9600);
    SPI.begin();
    mfrc522.PCD_Init();
    Serial.println("RC522 Ready. 请刷卡...");
}

void loop() {
    // 检测新卡
    if (!mfrc522.PICC_IsNewCardPresent())
        return;
    if (!mfrc522.PICC_ReadCardSerial())
        return;

    // 打印 UID
    Serial.print("UID: ");
    for (byte i = 0; i < mfrc522.uid.size; i++) {
        Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
        Serial.print(mfrc522.uid.uidByte[i], HEX);
    }
    Serial.println();

    // 读取 MIFARE Classic 1K 扇区0块0
    byte sector = 0;
    byte blockAddr = 0;
    byte trailerBlock = 3;
    MFRC522::MIFARE_Key key;
    for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF; // 默认密钥

    MFRC522::StatusCode status;
    status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A,
                                       trailerBlock, &key, &(mfrc522.uid));
    if (status == MFRC522::STATUS_OK) {
        byte buffer[18];
        byte size = sizeof(buffer);
        status = mfrc522.MIFARE_Read(blockAddr, buffer, &size);
        if (status == MFRC522::STATUS_OK) {
            Serial.print("Block 0 data: ");
            for (byte i = 0; i < 16; i++) {
                Serial.print(buffer[i] < 0x10 ? " 0" : " ");
                Serial.print(buffer[i], HEX);
            }
            Serial.println();
        }
    }

    mfrc522.PICC_HaltA();
    mfrc522.PCD_StopCrypto1();
}

例程2:STM32 HAL (SPI 裸驱动)

#include "stm32f1xx_hal.h"

/* ========== RC522 寄存器定义 ========== */
#define RC522_REG_COMMAND       0x01
#define RC522_REG_COM_IEN       0x02
#define RC522_REG_FIFO_DATA     0x09
#define RC522_REG_FIFO_LEVEL    0x0A
#define RC522_REG_TX_CONTROL    0x14
#define RC522_REG_BIT_FRAMING   0x0D
#define RC522_REG_MODE          0x11
#define RC522_REG_T_MODE        0x2A
#define RC522_REG_T_PRESCALER   0x2B
#define RC522_REG_T_RELOAD_H    0x2C
#define RC522_REG_T_RELOAD_L    0x2D
#define RC522_REG_ERROR         0x06
#define RC522_REG_COLL          0x0E
#define RC522_REG_VERSION       0x37

/* ========== 引脚宏(按实际接线修改) ========== */
#define RC522_CS_PORT      GPIOA
#define RC522_CS_PIN       GPIO_PIN_4
#define RC522_RST_PORT     GPIOA
#define RC522_RST_PIN      GPIO_PIN_3
#define RC522_SPI          hspi1

/* ========== 基础SPI读写 ========== */
static void rc522_cs_low(void)  { HAL_GPIO_WritePin(RC522_CS_PORT, RC522_CS_PIN, GPIO_PIN_RESET); }
static void rc522_cs_high(void) { HAL_GPIO_WritePin(RC522_CS_PORT, RC522_CS_PIN, GPIO_PIN_SET); }

static uint8_t rc522_spi_transfer(uint8_t data) {
    uint8_t rx;
    HAL_SPI_TransmitReceive(&RC522_SPI, &data, &rx, 1, 100);
    return rx;
}

static uint8_t rc522_read_reg(uint8_t reg) {
    uint8_t addr = ((reg << 1) & 0x7E) | 0x80;
    rc522_cs_low();
    rc522_spi_transfer(addr);
    uint8_t val = rc522_spi_transfer(0x00);
    rc522_cs_high();
    return val;
}

static void rc522_write_reg(uint8_t reg, uint8_t val) {
    uint8_t addr = ((reg << 1) & 0x7E);
    rc522_cs_low();
    rc522_spi_transfer(addr);
    rc522_spi_transfer(val);
    rc522_cs_high();
}

/* ========== 复位与初始化 ========== */
void rc522_init(void) {
    // 硬件复位
    HAL_GPIO_WritePin(RC522_RST_PORT, RC522_RST_PIN, GPIO_PIN_RESET);
    HAL_Delay(10);
    HAL_GPIO_WritePin(RC522_RST_PORT, RC522_RST_PIN, GPIO_PIN_SET);
    HAL_Delay(50);

    // 软复位
    rc522_write_reg(RC522_REG_COMMAND, 0x0F); // Soft reset
    HAL_Delay(50);

    // 定时器设置:TPrescaler=0x18, TReload=0x3B => ~13.56MHz载波
    rc522_write_reg(RC522_REG_T_MODE, 0x80);
    rc522_write_reg(RC522_REG_T_PRESCALER, 0x18);
    rc522_write_reg(RC522_REG_T_RELOAD_H, 0x00);
    rc522_write_reg(RC522_REG_T_RELOAD_L, 0x3B);

    // ASK 调制,CRC 初始值 0x6363
    rc522_write_reg(RC522_REG_TX_CONTROL, 0x03);
    rc522_write_reg(RC522_REG_MODE, 0x3D);

    // 开启天线
    uint8_t tx = rc522_read_reg(RC522_REG_TX_CONTROL);
    rc522_write_reg(RC522_REG_TX_CONTROL, tx | 0x03);
}

/* ========== 寻卡 ========== */
uint8_t rc522_request(uint8_t req_mode, uint8_t *tag_type) {
    rc522_write_reg(RC522_REG_BIT_FRAMING, 0x07); // LSB first, 7 bits
    rc522_write_reg(RC522_REG_FIFO_DATA, req_mode);

    rc522_write_reg(RC522_REG_COMMAND, 0x0C);     // Transceive
    rc522_write_reg(RC522_REG_COM_IEN, 0x20);     // 使能完成中断

    HAL_Delay(30);

    uint8_t err = rc522_read_reg(RC522_REG_ERROR);
    uint8_t fifo_len = rc522_read_reg(RC522_REG_FIFO_LEVEL);

    if (err != 0 || fifo_len < 2) return 0xFF;

    *tag_type = rc522_read_reg(RC522_REG_FIFO_DATA);
    return 0;
}

/* ========== 完整演示 ========== */
void rc522_demo(void) {
    rc522_init();

    uint8_t ver = rc522_read_reg(RC522_REG_VERSION);
    printf("RC522 Version: 0x%02X (expected 0x92 or 0x91)\r\n", ver);

    while (1) {
        uint8_t tag_type = 0;
        if (rc522_request(0x26, &tag_type) == 0) {
            printf("Card detected! Type: 0x%02X\r\n", tag_type);
        }
        HAL_Delay(500);
    }
}

例程3:ESP32 (直接寄存器操作)

#include <SPI.h>

#define RC522_SS   5
#define RC522_RST  4

SPIClass rc522_spi(HSPI);

// --- 寄存器读写函数同 STM32 例程,略 ---

void setup() {
    Serial.begin(115200);
    pinMode(RC522_SS, OUTPUT);
    pinMode(RC522_RST, OUTPUT);
    digitalWrite(RC522_SS, HIGH);

    rc522_spi.begin(14, 12, 13, RC522_SS); // SCK=14, MISO=12, MOSI=13
    rc522_spi.setFrequency(8000000);
    rc522_spi.setDataMode(SPI_MODE0);

    // 初始化(同 STM32 例程)
    rc522_init();
    Serial.println("RC522 on ESP32 ready.");
}

void loop() {
    uint8_t tag_type;
    if (rc522_request(0x26, &tag_type) == 0) {
        Serial.printf("Tag type: 0x%02X\n", tag_type);
    }
    delay(500);
}

常见问题排查

现象 可能原因 解决方法
无法检测到卡 供电不足/天线问题 确保 3.3V 供电稳定,远离金属
读卡距离短 天线匹配差 更换模块或优化天线布局
通信超时 SPI引脚错误 检查MISO/MOSI/SCK/NSS连接
认证失败 密钥错误 确认卡片密钥,尝试默认密钥
Version寄存器读0x00 SPI不通 检查接线和片选时序

信息

路径
/firmware/通信模块/RC522/RC522 RFID模块代码例程 (Arduino/STM32/ESP32).md
更新时间
2026/5/26