`MFRC522`(Contactless Reader IC for 13.56 MHz with SPI Interface)是一款高度集成的13.56MHz射频识别读卡器芯片,由NXP Semiconductors公司设计和生产。该芯片支持ISO/IEC 14443A和MIFARE通信协议,可以读写、加密和解密多种传统射频卡和接触式智能卡。MFRC522芯片集成了调制解调器、解密器、发射天线、接收天线等基础电路,同时还具有SPI接口、中断输出和定时器等功能,方便与微处理器或其他外围设备集成。由于其功能强大、易于使用和应用广泛,MFRC522芯片被广泛应用于物联网、门禁控制、智能家居、物流管理、人员考勤等领域。
数据手册
在学习该模块之前,需要准备arduino Uno开发板+MFRC522模块。
fork github源码:https://github.com/461911662/rfid
描述:如何在可更改 UID 的 MIFARE
卡上设置 UID。
主要流程:
1.初始化arduino uno串口、MFRC522实例、提供新的UID
2.找卡
3.读当前卡的UID
4.设置新的UID
5.挂起PICC设备为IDLE和HALT状态
6.再次重复2-3步骤(重新激活卡),读取卡UID检验是否写成功
关键函数:
MFRC522 mfrc522(SS_PIN, RST_PIN)
// SS_PIN: 用于arduino在使用spi发送数据时,通知MFRC522的片选信号
// RST_PIN:用于arduino检测MFRC522是否上电
mfrc522.PCD_Init();
// 硬复位MFRC522模块,并设置对应的通信参数
// 设置TxControlReg打开天线
mfrc522.PICC_IsNewCardPresent()
// 初始化MFRC522 TXRX寄存器为默认值(与NFC论坛规定速率一直106KBps)
// 以及设置默认的调制宽度。
// 通过SPI发送寻卡命令,寻卡命令格式:
// req: PICC_CMD_REQA = 0x26
// resp: byte1、byte2
// byte1:bit7保留
// bit6表示SAK[1],防冲撞0:不支持,1:支持
// bit5表示SAK[0],应答0:已经应答,1:需要选卡
// bit0-4表示UID size,卡片UID支持的长度
// byte2:用于区分不同的卡片类型,M卡为0x0。
mfrc522.PICC_ReadCardSerial()
// 读卡过程分为寻卡和选卡两个步骤
// 通讯协议如下:
// Byte 0: SEL 可选的命令:PICC_CMD_SEL_CL1, PICC_CMD_SEL_CL2 or PICC_CMD_SEL_CL3
// Byte 1: NVB 表示当前有效的bits位
// Byte 2: UID-data or CT 表示UID<=4:UID,否则是级联PICC_CMD_CT = 0x88
// Byte 3: UID-data 表示UID
// Byte 4: UID-data 表示UID
// Byte 5: UID-data 表示UID
// Byte 6: BCC 表示2-5的异或值
// Byte 7: CRC_A 表示CRC低地址
// Byte 8: CRC_A 表示CRC高地址
// 通讯示例:
// UID size Cascade level Byte2 Byte3 Byte4 Byte5
// ======== ============= ===== ===== ===== =====
// 4 bytes 1 uid0 uid1 uid2 uid3
// 7 bytes 1 CT uid0 uid1 uid2
// 2 uid3 uid4 uid5 uid6
// 10 bytes 1 CT uid0 uid1 uid2
// 2 CT uid3 uid4 uid5
// 3 uid6 uid7 uid8 uid9
// 1.寻卡命令格式:
// req:
// byte1:PICC_CMD_SEL_CL1 = 0x93
// byte2:0x20 表示有32位有效的bit
// resp:
// byte1: UID1
// byte2: UID2
// byte3: UID3
// byte4: UID4 可能返回更多字符这个与所读的卡片有关
// 2.选卡命令格式(假设UID长度为4):
// req:
// byte1:PICC_CMD_SEL_CL1 = 0x93
// byte2:0x70 表示有0x70位有效的bit
// byte3:UID1
// byte4:UID2
// byte5:UID3
// byte6: UID4
// byte7:UID1^UID2^UID3^UID4
// byte8:Low CRC
// byte9: High CRC
// resp:
// byte1:SAK(Select Acknowledge)
// byte2: Low CRCA
// byte3:High CRCA
// SAK格式如下:
// Bit 0(LSB):表示标签是否支持 ISO/IEC 14443-4 协议,如果支持则为 1,否则为 0。
// Bit 1:保留,未使用。
// Bit 2:Cascade 标志位,表示 UID 是否完整。
// Bit 3-7:表示标签的类型和版本信息,具体取值由不同的标签类型定义。
// 例如 MIFARE Classic 标签的 Bit 3-4 表示标签容量,Bit 5 表示加密类型等等。
mfrc522.MIFARE_SetUid(newUid, (byte)4, true)
// 设置UID的步骤大致有:
// 1.对block0进行鉴权
// 2.读取block0的内容
// 3.将旧的UID替换成新的UID,并更新BCC(Block Character Check)
// 4.关闭鉴权。
// 5.激活卡的后门功能,将新的block内容写到block0中去。
// 鉴权PICC卡片的命令格式:
// req:
// byte1:PICC_CMD_MF_AUTH_KEY_A = 0x60
// byte2:blockAddr,M1有64个block
// byte3:keyA1/keyB1
// byte4:keyA2/keyB2
// byte5:keyA3/keyB3
// byte6:keyA4/keyB4
// byte7:keyA5/keyB5
// byte8:keyA6/keyB6
// byte9-byte12:UID1-UID4
// resp:NA
// 读取PICC卡片的命令格式:
// req:
// byte1:PICC_CMD_MF_READ = 0x30
// byte2:blockAddr,M1有64个block
// byte3:Low CRCA
// byte4:High CRCA
// resp:
// byte1-byte16:1block为16字节
// byte17-byte18:CRCA
// 写PICC卡片的命令分两部分:写命令+写数据
// 格式如下:
// 1.写命令
// req:
// byte1:PICC_CMD_MF_WRITE = 0xA0
// byte2:blockAddr,M1有64个block
// byte3-byte4:CRCA
// resp:
// byte1:MF_ACK = 0xA bit0-3
// 2.写数据
// req:
// byte1-byte16:需要写的数据
PCD_StopCrypto1()
// 清除当前的鉴权状态
mfrc522.PICC_DumpToSerial(&(mfrc522.uid))
// 打印的内容如下:
// 1.卡片UID
// 2.卡片SAK码
// 3.卡片类型
// 4.卡片扇区内容
描述:展示使用MFRC522读取PICC里面的数据内容。
主要流程:
1.初始化arduino uno串口、MFRC522实例
2.初始化MFRC522的PCD模块
3.读取PCD模块的版本信息
4.寻卡+选卡
5.打印选择的卡片数据信息
关键函数:
mfrc522.PCD_DumpVersionToSerial()
//1.打印PCD的版本信息
mfrc522.PICC_DumpToSerial(&(mfrc522.uid))
//1.打印PICC的数据内容
描述:这个例子测试你的 MFRC522 读卡器模块的固件,只有已知版本才能被检查。如果测试通过,并不意味着你的模块是完美无缺的!某些模块可能存在损坏的天线或者损坏的 PICC(Proximity Integrated Circuit Card)。
主要流程:
1.查看PCD估计版本呢
2.对MFRC522的PCD进行自测试
描述:这个示例展示了如何修改一个损坏了的可更改 UID 的 MIFARE 卡片,针对可修改的卡片来说可以修改0扇区。
主要流程:
1.激活卡的后门功能
2.通过写命令直接清除0扇区的block
描述:这个示例展示了如何在 MIFARE Classic PICC(=卡片/标签)上设置数据块在处于“值块”模式:在这种模式下可以使用增量/减量、存储和传输等操作。
主要流程:
1.初始化arduino uno串口、MFRC522实例
2.初始化MFRC522的PCD模块
3.找卡、选卡
4.使用keyA(0xFF、0xFF、0xFF、0xFF、0xFF、0xFF),认证操作的block。
5.设置M卡的控制位,将对应的block设置为value block。
6.对指定的value block进行增量加、增量减、存储、传输等操作。
7.打印对应block,检查value block是否被修改。
8.挂起PICC、并清除PCD的鉴权信息。
关键函数:
mfrc522.MIFARE_SetAccessBits(&trailerBuffer[6], 0, 6, 6, 3)
// 通过4个block的权限转换成字节流。
// 这些字节流主要是用来构成控制块(block3)的关键字节
status = mfrc522.MIFARE_Increment(valueBlockA, 1)
// 增量加:对指定的block加1
// 增量加操作分为2个命令
// 发送增量命令
// req:
// byte1:PICC_CMD_MF_INCREMENT = 0xC1
// byte2:value blockAddr,M1有64个block
// byte3-byte4:CRCA
// resp:NA
// 发送增量值命令
// req:
// byte1:value&0xFF
// byte2:(value>>8)&&0xFF
// byte3:(value>>16)&&0xFF
// byte4:(value>>24)&&0xFF
// byte5-byte6:CRCA
// resp:NA
status = mfrc522.MIFARE_Transfer(valueBlockA)
// 传输:将PICC内部bufer中的数据保存到value block中
// 发送传输命令
// req:
// byte1:PICC_CMD_MF_TRANSFER = 0xB0
// byte2:value blockAddr,M1有64个block
// byte3-byte4:CRCA
// resp:NA
status = mfrc522.MIFARE_GetValue(valueBlockA, &value)
// 获取value block的值
// 与读取PICC卡片的命令格式相同,前4个字节位value值
// *value = (int32_t(buffer[3])<<24)
// | (int32_t(buffer[2])<<16)
// | (int32_t(buffer[1])<<8)
// | int32_t(buffer[0])
status = mfrc522.MIFARE_SetValue(valueBlockB, 255)
// 设置value block的值,方法同写PICC卡片的命令
// 如下是value block的协议规则:
// Translate the int32_t into 4 bytes; repeated 2x in value block
// buffer[0] = buffer[ 8] = (value & 0xFF);
// buffer[1] = buffer[ 9] = (value & 0xFF00) >> 8;
// buffer[2] = buffer[10] = (value & 0xFF0000) >> 16;
// buffer[3] = buffer[11] = (value & 0xFF000000) >> 24;
// Inverse 4 bytes also found in value block
// buffer[4] = ~buffer[0];
// buffer[5] = ~buffer[1];
// buffer[6] = ~buffer[2];
// buffer[7] = ~buffer[3];
// Address 2x with inverse address 2x
// buffer[12] = buffer[14] = blockAddr;
// buffer[13] = buffer[15] = ~blockAddr;
status = mfrc522.MIFARE_Decrement(valueBlockB, 10);
// 增量减:对指定的block加10
// 增量减操作分为2个命令
// 发送增量命令
// req:
// byte1:PICC_CMD_MF_DECREMENT = 0xC0
// byte2:value blockAddr,M1有64个block
// byte3-byte4:CRCA
// resp:NA
// 发送增量值命令
// req:
// byte1:value&0xFF
// byte2:(value>>8)&&0xFF
// byte3:(value>>16)&&0xFF
// byte4:(value>>24)&&0xFF
// byte5-byte6:CRCA
// resp:NA
描述:使用中断读取 MIFARE Classic PICC 的 UID。
主要流程:
1.初始化arduino uno串口、MFRC522实例
2.初始化MFRC522的PCD模块
3.获取PCD固件版本
4.设置MFRC522的IRQ pin脚为输入上拉模式
5.使能PCD的rx中断
6.注册终端处理函数
7.清除1次终端状态
8.循环中寻找卡,触发中断进入中断处理函数,去选择卡片,读卡信息
描述:展示如何读写PICC模块。
主要流程:
1.初始化arduino uno串口、MFRC522实例
2.初始化MFRC522的PCD模块
3.寻卡
4.读卡
5.使用KeyA鉴权卡的指定block
6.读取该block
7.使用KeyB鉴权卡的指定block
8.读写取该block
9.挂起PICC、并清除PCD的鉴权信息。
描述:循环读取PICC模块UID。
主要流程:
1.初始化arduino uno串口、MFRC522实例
2.初始化MFRC522的PCD模块
3.寻卡
4.读卡,将卡保存在内存中
5.循环检测新卡
描述:连续多次从PICC 中读取UID。
主要流程:
与ReadNUID类似
描述:从默认的工厂key中找到对应的key。
主要流程:
循环使用默认key,进行鉴权,鉴权成功即找到了对应的key
描述:对第1和第2个扇区进行鉴权,然后获取扇区block的内容。
主要流程:NA
描述:对第1和第2个扇区进行鉴权,然后重写扇区block的内容。
主要流程:NA
描述:复制RFID卡。
主要流程:
1.初始化arduino uno串口、MFRC522实例
2.初始化MFRC522的PCD模块
3.寻卡
4.读卡
5.循环鉴权block,并将block值保存在内存中
6.寻新卡、读卡,鉴权新卡,将内存内容保存在新卡block中,跳过控制块。