
深入RFID从读卡到写卡我用RC522踩过的那些坑说起RFID大家肯定不陌生——门禁卡、公交卡、校园卡、银行卡……每天都在用。但你有没有好奇过那张小小的卡片里到底存了什么读卡器是怎么跟它通信的数据是怎么读出来、写进去的最近做了两个RFID实验一个读、一个写用的是经典的MFRC522模块和STM32L4xx。从SPI通信到寻卡防冲撞从密码验证到扇区读写一路踩了不少坑。今天把整个过程整理出来带你从原理到代码彻底搞懂RFID。一、RFID到底是怎么工作的先从最基础的说起。RFIDRadio Frequency Identification射频识别是一种非接触式的自动识别技术通过射频信号来识别目标对象并获取数据。我们常用的Mifare卡也就是S50卡、M1卡工作在13.56MHz频率下属于近场通信的一种。它的原理说穿了就三步第一步读卡器给卡片供电。卡片本身是没有电池的完全靠无线充电。读卡器的天线发出13.56MHz的电磁波卡片里的线圈感应出电流给卡片上的芯片供电。这也是为什么要把卡靠近读卡器才能用——远了感应不到足够的能量。第二步读卡器和卡片通过调制信号通信。读卡器要发数据给卡片时就对载波进行ASK幅移键控调制卡片要回数据时通过改变自身负载阻抗来影响读卡器天线的电压这种方式叫负载调制。所以通信是半双工的你一句我一句。第三步数据交互遵循ISO14443A协议。这是一套国际标准规定了寻卡、防冲撞、选卡、认证、读写等操作的具体命令格式和时序。RC522芯片就是专门用来处理这套协议的把底层的射频调制解调都封装好了MCU通过SPI跟RC522打交道就行。二、硬件连接SPI就够了RC522模块跟STM32的连接很简单核心就是SPI接口加两个控制脚RC522引脚STM32引脚功能SDA/CSPA15SPI片选低电平有效SCKSPI3_SCKSPI时钟MOSISPI3_MOSISPI主机发从机收MISOSPI3_MISOSPI主机收从机发RSTPD0复位/休眠控制RST脚的用法挺有意思的——拉低就是休眠拉高就是唤醒。初始化的时候先拉低再拉高相当于硬件复位一下。SPI的配置也没什么特殊的速率不用太高实验里用了64分频。读写寄存器的格式有讲究读寄存器先发送一个字节最高位是1表示读中间6位是寄存器地址左移一位最低位不用管。然后再发一个空字节同时接收回来的就是寄存器值。写寄存器最高位是0表示写后面跟寄存器地址再后面跟要写的数据。// 读寄存器 ucAddr ((address1)0x7E)|0x80; // bit71表示读 RF_SPI_WriteByte(ucAddr); ucResult RF_SPI_WriteByte(0); // 发空字节收数据 // 写寄存器 ucAddr ((address1)0x7E); // bit70表示写 RF_SPI_WriteByte(ucAddr); RF_SPI_WriteByte(dat);就这么简单的SPI读写是所有上层功能的基础。三、读卡的完整流程寻卡→防冲撞→选卡→读数据很多人以为读RFID卡就是滴一下读出ID其实中间经过了好几个步骤一步都不能少。第一步寻卡Request读卡器先发一个寻卡命令0x26或0x52问附近有没有卡啊。0x26只寻没休眠的卡0x52寻所有卡。如果有卡在场卡片会返回自己的类型码2字节。比如S50卡返回0x0400Ultralight返回0x4400。这样读卡器就知道哦附近有一张S50卡。第二步防冲撞Anticollision如果有好几张卡同时在场怎么办总不能一起回答吧那不就乱了。这就需要防冲撞机制。简单说防冲撞就是按位筛选。读卡器说我要ID第N位是0的卡回答如果有多张就继续往下分直到只剩一张。整个过程是协议里规定好的不用自己实现调用RC522_Anticoll函数就行。防冲撞成功后你就能拿到卡片的4字节唯一IDUID了。每张卡的UID都是唯一的这就是我们常说的卡号。第三步选卡Select拿到UID之后还要发选卡命令告诉那张卡就你了准备好跟我通信吧。卡片返回一个字节的ATS应答选择确认选卡成功。第四步验证密码AuthenticationMifare卡不是谁想读就能读的每个扇区都有密码保护。读之前必须先验证密码——用A密钥0x60命令或者B密钥0x61命令。出厂默认密码一般是6个0xFF也就是{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}。如果密码不对后面的读写操作都会失败。第五步读/写数据密码验证通过之后就可以读写数据了。一次读或写都是16个字节一个块的大小。整个流程串起来就是这样status RC522_Search_Cards(PICC_REQALL, card_type); // 寻卡 if(status MI_OK) { status RC522_Anticoll(card_id); // 防冲撞拿ID } if (status MI_OK) { status RC522_Select_Cards(card_id); // 选卡 } if(status MI_OK) { status RC522_Verification_Password( // 验证密码 PICC_AUTHENT1A, block_addr, key, card_id); } if(status MI_OK) { status RC522_Read_Date(block_addr, data); // 读数据 // 或者 RC522_Write_Date(block_addr, data); // 写数据 }一步一步来缺了任何一步都不行。四、Mifare卡的存储结构扇区、块、密码区要往卡里写数据必须先搞清楚卡的存储空间是怎么组织的。S50卡也就是Mifare 1K总共有1KB的EEPROM存储空间分成了16个扇区Sector 0~15每个扇区又分成4个块Block 0~3每个块16字节。加起来就是16×4×16 1024字节。这64个块按绝对地址编号就是0~63。每个扇区的4个块分工不同块0、块1、块2数据块随便读随便写存你自己的数据块3控制块/尾块存的是密码和访问控制千万不要乱写控制块的16个字节是有固定格式的字节0-5: 密钥A (Key A) 字节6-9: 访问控制位 (Access Bits) 字节10-15: 密钥B (Key B)如果你不小心往控制块里写了乱七八糟的数据密钥就变了这个扇区可能就再也打不开了——俗称扇区锁死或者把卡写废了。实验代码里反复强调不要往块3写数据就是这个原因。还有一个特殊的地方第0扇区的块0绝对地址0是厂商代码区出厂时就固化了UID和厂商信息是只读的改不了。这也是每张卡UID唯一的原因。实验里用的是第1扇区RC522_SECTOR 1对应绝对地址块4、5、6、7。其中块4、5、6是数据块可以放心写块7是控制块别碰。五、写入实验按键选择刷卡写入写入实验比读取实验多了一个交互——用4个按键来选择要做什么操作KEY1往数据块0写123456KEY2往数据块1写this is a testKEY3往数据块2写十六进制数据{0x30,0x31,0x32,0x33}KEY4清除数据块0、1、2的数据全写0操作流程是先按键选择功能然后把卡放到感应区程序检测到卡后就执行对应的写入操作最后再把三个数据块的内容读出来显示验证。这里有个细节每次写完之后都会再读回来验证。这是个好习惯——因为RFID是非接触通信受距离、干扰、卡片位置等因素影响写入有可能失败。写了再读一遍确认心里才踏实。还有个容易踩的坑写入操作其实是分两步的。先发写命令块地址卡片返回ACK之后再发16字节数据CRC。不是一次就能写完的。RC522_Write_Date函数内部已经把这两步封装好了但你得知道有这么回事。六、那些年我踩过的坑做这两个实验的过程中踩了不少坑说几个印象最深的坑1SPI通信死活不通。一开始怎么都读不到RC522的寄存器值查了半天才发现是SPI的CPOL和CPHA没配对。RC522要求SPI模式是CPOL0、CPHA0也就是模式0上升沿采样。配错了读出来全是0xFF或者0x00。坑2寻卡成功但防冲撞失败。有时候能寻到卡但防冲撞那步老是返回错误。后来发现是天线的问题——RC522_Init之后一定要记得开天线RC522_AntennaOn而且开关天线之间至少要有1ms的间隔。天线没调好信号强度不够防冲撞就容易失败。坑3密码验证通不过。一开始以为是代码问题查了半天结果是那张卡的密码被之前的实验改过了不是默认的6个0xFF了。换了张新卡就好了。所以玩RFID卡的时候最好在卡上贴个标签记一下密码不然哪天忘了就只能当一次性卡用了。坑4往控制块写了数据扇区废了。这个是真的坑……刚开始不了解存储结构随手往块3写了点测试数据结果那个扇区就再也打不开了。后来才知道控制块不能乱写数据只能往块0、1、2里存。坑5卡片放的位置不对。RFID读卡对位置还挺敏感的不是随便一放就能行。有时候卡稍微偏一点或者离远一点寻卡就失败。实验里做了个感应区的标记把卡放在标记正上方成功率就高多了。七、从实验到应用RFID能做什么搞懂了原理和读写操作能玩的东西就多了。说几个我觉得比较有意思的方向门禁系统这是最经典的应用。把授权的卡号存在数据库里刷卡的时候比对一下合法就开门。再加点功能比如记录刷卡时间、支持临时卡、黑名单管理等等。消费系统校园卡、公交卡其实就是把余额存在卡里的某个扇区值块刷卡的时候扣钱。值块有专门的格式还支持增减操作和备份RC522_Deduction_Recharge函数就是干这个的。资产管理给设备贴个RFID标签盘点的时候一扫就知道哪些设备在、哪些不在。比人工扫码快多了。NFC手机交互现在的手机基本都支持NFC可以跟RFID卡交互。比如把网址、文本存在卡里手机一靠就打开网页或者显示内容。往深了做还能研究安全——Mifare卡的加密其实早就被破解了有很多关于嗅探、克隆、破解的技术。当然这个得在合法合规的范围内玩。八、写在最后两个实验做下来最大的感受是RFID这东西看似简单不就是滴一下嘛但里面的门道真不少。从射频通信到协议栈从存储结构到安全机制每一层都值得深入研究。RC522是个很好的入门芯片资料多、价格便宜、社区活跃。把它搞懂了再去接触其他RFID芯片甚至NFC控制器就容易多了。如果你也对RFID感兴趣我的建议是买个RC522模块和几张白卡跟着代码一步步调从读ID开始到读数据、写数据、改密码慢慢往上加。动手调过几个bug很多原理自然就懂了。好了这篇就写到这里。后面打算再研究一下值块操作和Mifare的安全机制到时候再来分享。