资讯详情

资讯详情

RFID模块实战指南:从选型到读写M1卡的完整流程

想做门禁、储物柜、校园卡模拟器或者只是想把手里的IC卡数据读出来看看大概率都会走到同一个选型路口RFID模块。这玩意儿在嵌入式项目里太常见了说它是物联网入门必备也不夸张。市面上最普及的是13.56MHz频段的高频读写模块配合常见的IC卡和钥匙扣能实现读卡号、写数据块、模拟门禁逻辑等一整套操作。这篇文章把我自己从零开始摸RFID模块的过程完整复盘一遍覆盖硬件选型、接线、底层指令、读写实战和排错经验适合刚接触射频卡读写、正准备把它塞进自己项目里的开发者。内容不涉及任何商业套件用的都是最常见的芯片方案和通用工具照着操作就能跑起来。1. 选型先看这几项频段、协议芯片和模块形态1.1 频段决定了你能读什么卡RFID不是一个统一标准而是按工作频段分成好几大类不同频段对应完全不同的应用场景。做项目第一步不是挑模块而是搞清楚你要读的卡属于哪个频段。低频段125kHz常见于宠物芯片、老式门禁卡穿透性好但对金属敏感读取距离通常只有几厘米而且存储结构非常简单基本只能读一个ID号。高频段13.56MHz是目前最活跃的领域公交卡、校园卡、身份证、银行卡大多是这一频段协议成熟、防碰撞能力强卡片内部有扇区、数据块的概念可以真正读写数据。超高频段915MHz左右用于仓储物流读取距离可以到几米甚至更远但对环境干扰很敏感模块价格也明显更高。新手做门禁、考勤、会员积分这类项目几乎都在13.56MHz高频段里做文章。这个频段最常见的卡片协议是ISO 14443A市面上绝大多数的M1卡、钥匙扣都跑这个协议对应的读写芯片方案也很成熟。选模块之前先确认手头的测试卡是哪个协议否则买回来读不出数据白折腾一圈。1.2 模块形态与接口差异同样是13.56MHz读写器市面上形态差异挺大。有的做成独立读卡器带外壳和天线通过串口发指令就能工作适合快速验证。有的做成裸板模块天线和射频电路都在一块小PCB上通过排针引出接口适合嵌入到自己的电路里。还有一种连射频芯片都省了直接用PN类芯片搭外围电路灵活性最高但工作量也大。接口方面常见的有四类UART串口、SPI、I2C以及直接用射频芯片寄存器操作的底层接口。串口模块最省心发几个字节命令就能读卡号适合不关心底层实现的项目。SPI和I2C模块需要自己写初始化逻辑但能精确控制读写流程自由度更高。我自己的经验是调试排错时优先用串口模块逻辑简单逻辑分析仪一挂就能看到完整交互。等流程跑通了再根据量产需求换成底层芯片方案这样可以避免一上来就被SPI时序折腾得失去耐心。1.3 避坑别把125kHz低频卡和13.56MHz高频卡混为一谈很多人第一次买模块看到“RFID模块”就下单结果手里拿着13.56MHz的M1卡去读125kHz的低频模块怎么都读不出来还以为模块坏了。这两个频段完全不兼容模块芯片和天线线圈都不一样软件层面更是毫无共同语言。另外一个常见的坑是协议标签ISO 14443A和ISO 14443B虽然都是13.56MHz高频标准但底层通信方式不同绝大多数通用模块支持A类遇到B类卡比如部分二代身份证读卡需求就需要专门的模块。买模块前看清楚支持的协议列表比看频率参数更重要。还有一个容易忽略的点模块天线尺寸决定了读取范围。同样一个芯片方案天线面积大一圈读取距离可能从4厘米涨到8厘米。如果项目要求隔着一块亚克力板刷卡选模块时就要留意天线面积和外壳装配方式不能只看芯片型号。2. 接线和初始化电平、电源和复位这三个坑2.1 标准接线方式和供电要求以最常见的13.56MHz高频模块为例接口一般有电源、地、复位、串口收发或者SPI总线的几根线。电源部分是第一个容易翻车的地方这类模块射频发射时需要瞬时电流通常需要3.3V供电电流峰值可能到几百毫安。如果从开发板的3.3V引脚取电而开发板本身电源余量不足会导致模块发射功率上不去读卡距离特别短。我遇到过一种典型情况用USB转串口直接给模块供电读卡距离只有1厘米左右换成一节干净的稳压电源供电后立刻恢复到4厘米以上。排查步骤很简单用示波器看模块供电引脚在寻卡瞬间有没有明显跌落跌了就是电源问题。没有示波器的话在电源引脚并联一个100微法的电容再试经验上能改善不少。接线时注意地线要粗而短射频电路对地线阻抗很敏感。模块和单片机共用电源时尽量让电源先到模块再到单片机避免模块的大电流在PCB走线上产生压降反过来干扰单片机的ADC或者复位电路。2.2 3.3V与5V系统的电平转换很多老式开发板逻辑电平是5V而射频模块通常按3.3V设计。直接用5V的TX去接模块的RX多数模块的IO有钳位保护短时间不烧但长期跑有风险。更稳妥的做法是把单片机侧的IO配置成开漏模式外加3.3V上拉电阻或者用简单的两个MOS管做双向电平转换。如果模块本身支持5V供电但IO参考电压是3.3V同样存在电平不匹配。我处理过一个项目主板给模块供5V电模块的TX输出是3.3V电平主板串口识别不出高电平导致收不到任何数据。最后是给模块单独供3.3V电源同时串口走电平转换芯片才解决。判断电平是否匹配最简单的办法是用万用表量空闲状态下的TX引脚电压能测到稳定的3.3V左右才算正常。空闲时测得接近0V大概率是模块没有初始化成功或者被拉低在复位状态。2.3 复位时序与初始化代码要点大部分射频芯片上电后需要一次完整的复位脉冲然后等待内部振荡器稳定才能继续操作。很多人跳过这一步直接发寻卡命令结果一直接收超时。复位的推荐时序是上电后先把复位引脚拉低保持至少10毫秒然后拉高再延时等待约50毫秒。等待的目的不是CPU而是让芯片内部的晶振从起振到幅度稳定。某些低成本模块用的晶振启动很慢这里多等一会儿能明显提高首次寻卡的成功率。初始化代码里还有一个容易忽略的寄存器天线控制寄存器。芯片默认天线可能是关闭的需要显示配置为开启状态才能发射射频场。判断天线有没有打开可以用一个简单方法拿一张卡贴近天线区域看模块的电流指示是否在寻卡时跳动。完全没变化基本可以断定发射链路没起来。3. 读懂读写器的指令体系从寻卡到写数据3.1 指令概览与寄存器工作方式高频RFID芯片内部本质是一个射频收发器对外提供一组寄存器通过SPI或者I2C读取和写入。模块固件把底层的寄存器操作封装成几个高层命令最常用的是下面这几个指令名称功能输入参数返回结果寻卡请求检测天线场内是否有卡请求类型如寻所有卡卡的ATQA信息防碰撞当多卡同时在场时获取单卡序列号级联级别4字节或7字节卡号选卡选中某一张卡准备后续操作卡号卡的SAK信息认证验证扇区密钥扇区号、密钥类型、卡号认证通过状态读块读取指定数据块的16字节块地址16字节数据写块写入指定数据块块地址、16字节数据写操作状态以M1卡为例卡片内部存储分为16个扇区每个扇区有4个数据块其中块3是控制块存储密钥和访问控制位。读写数据主要操作的是前3个数据块每个块可以放16字节。这个结构决定了读写前必须先认证密钥不对直接报错。3.2 寻卡与防碰撞的处理逻辑“寻卡”这一步容易被初学者忽略细节。ISO 14443A协议的寻卡请求有一种类型是ALL模式只要有一张卡在感应区就返回。还有一种是WUP模式专门用于唤醒处于休眠状态的卡片。区别很实际一张卡连续读了几次后会被要求进入睡眠以省电此时用ALL模式找不到它必须用WUP模式唤醒。防碰撞则是多个卡片同时进场时的处理机制。原理并不复杂每张卡有全局唯一的序列号读卡器发一个防碰撞命令每张卡同时应答自己的序列号如果发现多张卡应答冲突就通过逐个比特仲裁的方式最终把每一张卡号都拿到。实际做门禁项目时这个逻辑是“读卡循环”的核心先WUP然后防碰撞拿卡号选卡再读数据。防碰撞后拿到卡号只是第一步如果项目里不需要读卡内数据走到选卡就可以结束一轮。但注意防碰撞命令执行后卡片处于选中状态下次循环最好先发HALT让卡片休眠避免卡一直占着通道。3.3 认证与读写块操作的参数细节认证命令需要三个参数扇区号、密钥类型A密钥或B密钥、卡序列号。这里最容易搞错的是扇区号和块地址的关系M1卡有16个扇区每个扇区4个块总体块地址从0排到63。读第5扇区的第1个数据块实际块地址等于5乘以4加1也就是21而不是直接写5。密钥类型也经常被忽略。很多卡出厂时A密钥和B密钥都是全F六个字节都是0xFF但不是所有卡都这样。有的卡只允许用A密钥认证用B密钥会直接返回认证失败。我在项目里调试一张定制的会员卡时就是因为厂商把B密钥改掉了却没说导致认证一直失败最后用读卡器盲扫B密钥才找到问题。读写块操作还有一个隐藏细节写块命令必须一次性写入16字节不能只写4个字节。如果业务数据不满16字节需要用固定填充位补齐。很多人以为读卡号就等于RFID的全部实际做数据存储时一个数据块能放什么信息、放完后怎么校验才是真正考验设计的地方。4. 一个完整实例读卡号、读写数据块、写新卡4.1 读卡号流程与代码骨架下面是一个完整读卡号的流程骨架我用最常见的SPI接口模块做示例函数名是通用的拿到任何基于此芯片方案的模块都能对上。首先初始化SPI和复位引脚void rfid_init(void) { gpio_pin_low(RST_PIN); delay_ms(10); gpio_pin_high(RST_PIN); delay_ms(50); spi_init(SPI_FREQ_1MHZ, SPI_MODE_0); rfid_write_reg(TX_ANTENNA_REG, 0x0F); // 开天线 rfid_write_reg(INTERRUPT_REG, 0x7F); rfid_write_reg(INTERRUPT_REG, 0x80); delay_ms(10); }然后是寻卡加防碰撞的代码段uint8_t card_number[5]; uint8_t atqa[2]; rfid_transceive(CMD_TRANSMIT_ANTICOLLISION, 0x93, card_number, 5); if (card_number[0] ! 0x00) { uint8_t sak; rfid_transceive(CMD_SELECT_CARD, 0x93, card_number, sak); printf(Card UID: %02X %02X %02X %02X\n, card_number[0], card_number[1], card_number[2], card_number[3]); }这段逻辑看起来简单但实际执行时要注意防碰撞命令返回的是5字节数据第一个字节是校验位后四位才是卡号。很多新手直接打印5个字节把校验位当成卡号的一部分到写认证逻辑时怎么都对不上就是这个原因。4.2 数据块读写示例读数据块前必须先认证。认证函数的参数需要当前卡号所以我们把上一步获取的卡号保存成全局变量。以读取第4扇区的块0为例uint8_t block_addr 4 * 4 0; // 第4扇区的第0个块地址是16 uint8_t key[6] {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint8_t data[16]; rfid_authen(AUTH_KEY_A, block_addr, key, card_number); rfid_read_block(block_addr, data, 16);如果返回错误先检查当前卡是否仍在感应区。常见问题是认证前误发了HALT命令卡片已经休眠认证命令根本没人应答。此时需要先发WUP唤醒再重新走防碰撞流程。写入数据块的流程类似但有一个额外要求写入的数据长度必须是16字节。比如要存一个四字节的卡号和八字节的用户编号剩下四个字节用0x00补齐。uint8_t new_data[16]; memset(new_data, 0x00, 16); new_data[0] 0x12; new_data[1] 0x34; new_data[2] 0x56; new_data[3] 0x78; rfid_authen(AUTH_KEY_A, block_addr, key, card_number); rfid_write_block(block_addr, new_data, 16);4.3 实测数据演示与结果判断我用一块全新的M1卡跑了一次完整流程时序上有个直观结果复位后第一次发WUP命令正常情况下应该在20毫秒内收到应答。如果等了100毫秒以上还没反应先不要怀疑代码把卡靠近模块天线中心很多模块的感应场并不是均匀的边缘区域时好时坏。读到的原始数据里块0通常存放卡片的厂商信息和序列号部分字段块1和块2默认是全零块3存放密钥。很多人拿到一把空白卡直接读块0发现能读出数据就以为卡片被写过了其实那是厂商出厂时烧录的信息不占业务存储空间。写数据后的验证方式不要依赖读卡器直接显示建议写完后立刻读回来比对。有一种情况是写命令返回成功但读回来发现全是0说明写入过程中卡被移出了感应区数据根本没落进去。比对这一步能避免把这种脏数据带入业务流程。5. 故障排查与经验总结信号弱、读卡慢、卡写坏怎么办5.1 读卡距离短与天线摆放读卡距离是RFID项目里最常被吐槽的指标。13.56MHz模块理论距离一般是3到8厘米但实际使用中经常缩水到1厘米主要原因有四个。第一个是电源问题前面说过射频发射瞬间功耗大电源不稳距离就短。第二个是天线周围有金属金属会吸收射频能量形成涡流损耗距离直接砍半。第三个是卡片本身的质量有些卡片的芯片天线线圈面积小或者封装塑料太厚读卡器再好也白搭。第四个是天线和谐振匹配的问题裸板模块的天线线圈和调谐电容在出厂时已匹配好擅自改天线尺寸会造成失谐。项目里安装读卡器时背后尽量不要贴铁板如果结构上必须用金属底板至少要保持2厘米以上的间距。前面板如果是一块几毫米厚的亚克力影响不大但如果是金属面板基本就别想正常刷卡了。5.2 读卡不稳定的干扰排查读卡不稳定表现为10次里有两三次读不出或者读卡号时好时坏。排查思路建议按这个顺序走确认供电确认电平确认协议最后才怀疑模块硬件。供电和电平用万用表就能排查。协议层的排查稍微麻烦如果寻卡命令返回超时大概率是卡片类型不匹配如果返回了ATQA但卡号校验不对往往是防碰撞过程受到干扰周围有大功率高频设备或者变频器。还有一种隐蔽干扰来自模块自己的SPI线路。SPI信号线如果和天线区域靠得太近高速翻转的数字信号会耦合进模拟前端降低接收灵敏度。我自己遇到过一块模块只要把它靠近单片机读卡成功率先从95%掉到60%把模块挪开几厘米立刻就恢复。所以布板时SPI走线务必和天线保持距离优先级不要低于电源设计。5.3 写卡失败的常见原因写卡失败比读卡失败更让人头大因为可能把卡弄成半残状态。最常见的原因有三个。第一个是认证没过密钥错误。厂商定制的卡往往改了默认密钥直接用全F密钥认证必然失败。第二个是访问控制位限制某些卡的块被配置成只读即使认证通过写块命令也会被拒绝。这类卡想改写数据得先修改控制块但控制块一旦改错整张卡可能彻底变砖改之前要把原始值完整备份。第三个是写入过程中卡被移走数据块可能处于部分写入状态读回来的数据既不新也不旧属于最糟糕的结果。我给定制卡做批量初始化时额外写了一层校验每张卡写完后把所有关键块读回来和原始数据比对不一致就直接标记为异常卡单独处理避免坏卡流到用户手上。5.4 日常使用中的维护经验最后分享几条实操中摸出来的经验不算什么高深理论但很实用。读卡模块的天线区域如果长期裸露灰尘和金属碎屑容易积累导致灵敏度下降。工业现场用的话最好定期用气吹清洁天线表面。模块固件里的看门狗超时设置要留意有些模块在一段时间没检测到卡之后会自动关闭天线需要在寻卡前重新打开否则表现为“越用越没反应”。关于卡片的保存也有讲究M1卡怕弯折和高温弯折会折断内部天线线圈卡片直接报废。批量发卡时不要用订书机把卡和纸质说明钉在一起很容易伤到芯片位置。另外所有涉及密钥的项目建议把密钥管理流程单独拎出来设计。很多项目读卡部分写得顺手密钥却写死在固件里后面要升级才知道有多痛苦。先把密钥放在一个独立配置区量产时再写入比后期改固件省太多事情。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →