如何设置两台Arduino UNO连接的RFID RC522为主从机实现通信?
如何配置两个RFID RC522模块实现Arduino UNO主从通信?
嘿,这个需求我之前帮朋友折腾过好几次,RC522本身支持ISO14443A协议,要实现两台Arduino之间的主从通信,核心是让其中一个模块主动发起读写请求(主机),另一个模拟成被动响应的“虚拟PICC卡片”(从机)。下面我一步步给你拆解实现步骤:
第一步:硬件连接要点
- 两个RC522模块分别和各自的Arduino UNO连接,接线都是标准SPI引脚,别接错了:
- SDA → D10
- SCK → D13
- MOSI → D11
- MISO → D12
- GND → GND
- 3.3V → 3.3V(敲黑板:RC522绝对不能接5V,一接就烧!)
- 额外小技巧:如果两个模块离得近,给每个模块的3.3V和GND之间接个100nF的陶瓷电容,能减少电源干扰,通信更稳定。
第二步:软件配置与代码实现
首先要用到MFRC522库,这个库默认支持主机模式,而从机模式需要我们手动配置寄存器来模拟PICC卡片。下面是主机和从机的完整代码:
主机代码(主动发起通信)
主机负责主动扫描、识别从机,并发送/接收数据:
#include <SPI.h> #include <MFRC522.h> #define SS_PIN 10 #define RST_PIN 9 MFRC522 mfrc522(SS_PIN, RST_PIN); // 创建RC522实例 void setup() { Serial.begin(9600); SPI.begin(); mfrc522.PCD_Init(); // 初始化模块,默认就是主机模式 Serial.println("主机已启动,等待连接从机..."); } void loop() { // 检测是否有"卡片"(这里就是我们的从机模块) if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) { 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(); // 示例:给从机发送"HELLO" byte sendData[] = {'H', 'E', 'L', 'L', 'O'}; MFRC522::StatusCode status = mfrc522.PCD_TransceiveData(sendData, sizeof(sendData), NULL, 0, NULL, NULL); if (status == MFRC522::STATUS_OK) { Serial.println("数据发送成功!"); } else { Serial.print("发送失败,错误码: "); Serial.println(mfrc522.GetStatusCodeName(status)); } // 结束当前通信 mfrc522.PICC_HaltA(); mfrc522.PCD_StopCrypto1(); } delay(100); }
从机代码(被动响应)
从机需要配置成模拟PICC卡片的模式,等待主机的请求并回复:
#include <SPI.h> #include <MFRC522.h> #define SS_PIN 10 #define RST_PIN 9 MFRC522 mfrc522(SS_PIN, RST_PIN); // 自定义从机的UID,主机就是通过这个识别它的 byte slaveUID[] = {0x12, 0x34, 0x56, 0x78}; void setup() { Serial.begin(9600); SPI.begin(); mfrc522.PCD_Init(); // 配置RC522为从机模式,模拟PICC卡片 mfrc522.PCD_WriteRegister(MFRC522::CommandReg, MFRC522::PCD_IDLE); mfrc522.PCD_WriteRegister(MFRC522::TxControlReg, 0x00); mfrc522.PCD_WriteRegister(MFRC522::ModeReg, 0x3D); // 设置为模拟PICC模式,CRC初始值0x6363 // 写入我们自定义的UID mfrc522.PCD_WriteRegister(MFRC522::TxDataReg, slaveUID[0]); mfrc522.PCD_WriteRegister(MFRC522::TxDataReg+1, slaveUID[1]); mfrc522.PCD_WriteRegister(MFRC522::TxDataReg+2, slaveUID[2]); mfrc522.PCD_WriteRegister(MFRC522::TxDataReg+3, slaveUID[3]); Serial.println("从机已启动,等待主机连接..."); } void loop() { // 监听主机发来的数据 byte buffer[18]; byte bufferSize = sizeof(buffer); MFRC522::StatusCode status = mfrc522.PCD_ReceiveData(buffer, &bufferSize, NULL); if (status == MFRC522::STATUS_OK && bufferSize > 0) { Serial.print("收到主机数据: "); for (byte i = 0; i < bufferSize; i++) { Serial.print((char)buffer[i]); } Serial.println(); // 示例:回复主机"HI" byte response[] = {'H', 'I'}; mfrc522.PCD_TransceiveData(response, sizeof(response), NULL, 0, NULL, NULL); } delay(50); }
关键注意事项
- 模块一致性:尽量用同一品牌同一批次的RC522模块,不同厂商的模块寄存器可能有细微差异,容易出问题。
- 通信距离:RC522的有效通信距离大概在1-5cm,两个模块要尽量靠近,别隔太远。
- 库版本:上面的代码基于最新版的MFRC522库,如果你的库版本比较老,可能需要调整寄存器的配置值。
- 电源问题:Arduino的3.3V引脚输出电流有限,如果模块工作不稳定,建议给RC522外接一个3.3V/500mA的电源。
内容的提问来源于stack exchange,提问作者Osama Lazim




