STM8S 系列单片机 + RC522(MFRC522)读写 IC 卡(MIFARE Classic)
一、适用芯片说明
- MCU:STM8S003 / STM8S103 / STM8S105(推荐 103F3P6,性价比最高)
- RFID:RC522(13.56MHz,ISO/IEC 14443 Type A)
- IC 卡:MIFARE Classic 1K(S50)
二、硬件连接(SPI 方式)
| RC522 | STM8S | 说明 |
|---|---|---|
| VCC | 3.3V | 禁止 5V |
| GND | GND | |
| RST | PC4 | 复位 |
| NSS | PA3 | 片选 |
| SCK | PC5 | SPI 时钟 |
| MOSI | PC6 | 主发从收 |
| MISO | PC7 | 主收从发 |
| IRQ | 悬空 | 可选 |
STM8S 使用 SPI 主模式,CPOL=0,CPHA=0
三、RC522 工作原理简述
寻卡 → 防冲撞 → 选卡 → 认证 → 读/写扇区
MIFARE 1K:
- 16 个扇区(0~15)
- 每扇区 4 块(0~3)
- 块 3 = 密钥区(KeyA + Access Bits + KeyB)
四、SPI 基础读写
c
uint8_t SPI_ReadWrite(uint8_t data)
{
while (!(SPI->SR & SPI_SR_TXE));
SPI->DR = data;
while (!(SPI->SR & SPI_SR_RXNE));
return SPI->DR;
}
uint8_t RC522_ReadReg(uint8_t addr)
{
uint8_t val;
NSS_LOW();
SPI_ReadWrite((addr << 1) | 0x80);
val = SPI_ReadWrite(0x00);
NSS_HIGH();
return val;
}
void RC522_WriteReg(uint8_t addr, uint8_t val)
{
NSS_LOW();
SPI_ReadWrite((addr << 1) & 0x7E);
SPI_ReadWrite(val);
NSS_HIGH();
}
五、RC522 初始化
c
void RC522_Init(void)
{
RC522_Reset();
RC522_WriteReg(TModeReg, 0x8D);
RC522_WriteReg(TPrescalerReg, 0x3E);
RC522_WriteReg(TReloadRegL, 30);
RC522_WriteReg(TReloadRegH, 0);
RC522_WriteReg(TxAutoReg, 0x40);
RC522_WriteReg(ModeReg, 0x3D);
RC522_AntennaOn();
}
六、寻卡 & 防冲撞
1、寻卡
c
uint8_t RC522_Request(uint8_t *cardType)
{
uint8_t status;
RC522_WriteReg(BitFramingReg, 0x07);
status = RC522_ToCard(PICC_REQALL, cardType);
return status;
}
2、防冲撞(获取 UID)
c
uint8_t RC522_Anticoll(uint8_t *uid)
{
uint8_t status;
RC522_WriteReg(BitFramingReg, 0x00);
status = RC522_ToCard(PICC_ANTICOLL, uid);
return status;
}
七、扇区认证(关键)
c
uint8_t keyA[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
uint8_t RC522_Auth(uint8_t blockAddr)
{
uint8_t buff[12];
buff[0] = PICC_AUTHENT1A;
buff[1] = blockAddr;
memcpy(&buff[2], keyA, 6);
memcpy(&buff[8], uid, 4);
return RC522_ToCard(PCD_AUTHENT, buff);
}
八、读数据(16 字节)
c
uint8_t RC522_ReadBlock(uint8_t block, uint8_t *data)
{
uint8_t buff[18];
buff[0] = PICC_READ;
buff[1] = block;
RC522_ToCard(PCD_TRANSCEIVE, buff);
memcpy(data, buff, 16);
}
九、写数据(必须 16 字节对齐)
c
uint8_t RC522_WriteBlock(uint8_t block, uint8_t *data)
{
uint8_t buff[18];
buff[0] = PICC_WRITE;
buff[1] = block;
RC522_ToCard(PCD_TRANSCEIVE, buff);
memcpy(buff, data, 16);
return RC522_ToCard(PCD_TRANSCEIVE, buff);
}
参考代码 STM8S系列单片机通过RC522电路向IC卡中读取、写入数据 www.youwenfan.com/contentcsv/72536.html
十、典型主流程
c
int main(void)
{
SPI_Init();
RC522_Init();
while(1)
{
if(RC522_Request(cardType) == MI_OK)
{
if(RC522_Anticoll(uid) == MI_OK)
{
RC522_Auth(8);
RC522_ReadBlock(8, data);
RC522_WriteBlock(8, "1234567890123456");
}
}
delay_ms(200);
}
}
十一、常见问题 & 避坑指南
| 问题 | 原因 | 解决 |
|---|---|---|
| 读不到卡 | 电压不稳 | 加 100nF 电容 |
| 写卡失败 | 未认证 | 先 Auth |
| 偶尔死机 | SPI 时序 | 降低 SPI 频率 |
| 距离短 | 天线 | 优化 PCB / 线圈 |