RC522作为一款NFC读写芯片,性价比还是很高的,因为在项目里需要采用NFC OOB配对,所以需要读取配对方模拟的NFC卡片信息
读取对象采用NRF52832,使用其NFC功能模拟type2 tag,但是读取方式和M1卡不一样,踩了不少坑,网上的资料都是调取现有接口没啥用处,也没有什么资料可以参考,只能自己看技术规范来实现了。
NFC Forum Type2 Tag属于Mifare Ultralight卡,和M1卡一样都遵循IEC14443-3/A规范,但是Mifare Ultralight有7位UID,这点需要额外注意;
查阅IEC14443-3/A规范得知卡片读取流程如下:
开始读取流程后,先需要发送查询指令得到卡片的ATQA值,对于Mifare Ultralight卡来说ATQA值为0x4400,识别到这个ATQA值即可进入Mifare Ultralight卡的UID读取流程
如何得到ATQA值呢?有两种方式,可以通过发送REQA或者WUPA都可以得到:
在RC522的例程中,采用WUPA进行查询,代码如下:
ClearBitMask(Status2Reg,0x08);//清除Status2Reg寄存器
WriteRawRC(BitFramingReg,0x07);//停止当前RC522的指令
SetBitMask(TxControlReg,0x03);//准备发送数据
ucComMF522Buf[0] = 0x52;//查询指令
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);//和RC522通讯,若有卡片存在则会将卡片的ATQA值保存在ucComMF522Buf中
if ((status == MI_OK) && (unLen == 0x10)){ *pTagType = ucComMF522Buf[0];*(pTagType+1) = ucComMF522Buf[1];}
得到的返回值pTagType即为卡片的ATQA值;
若有Mifare Ultralight卡位于RF场内,则进行第一次选择卡片操作,即流程图中的“Select cascade level 1”
这里有个大坑,对于Mifare Ultralight卡来说,需要先进行一次防冲撞操作得到前三位UID值后才能继续往下进行选择卡片操作,否则不会得到任何返回值,当时在这里卡了好久
PcdRequest(0x52,TagType);//第一步,查询卡片
if(TagType[0]==0x44 && TagType[1]==0x00)//确认卡片为Ultralight
{PcdAnticoll(SelectedSnr);//第一次防冲撞,得到卡片的第一组UID值,保存在SelectedSnr内,长度为4位//假设返回值为88:5F:D1:6E,5F:D1:6E才是卡片UID的一部分88只是卡片代码,在后续的获取UID的操作中应当忽略掉这个值UID[0]=SelectedSnr[1];UID[1]=SelectedSnr[2];UID[2]=SelectedSnr[3];//得到前三位UID值PcdSelect(SelectedSnr);//第一次选择卡片,这里的卡号参数需要连着0x88一起发送出去PcdAnticoll_type2(SelectedSnr+4);//第二次防冲撞,将后四位UID号储存在SelectedSnr[4]之后的数组内UID[3]=SelectedSnr[4];UID[4]=SelectedSnr[5];UID[5]=SelectedSnr[6];UID[6]=SelectedSnr[7];//得到后四位UID卡号PcdSelect2(SelectedSnr+4);//第二次选择卡片,这样才可以得到卡片的访问权限/*从此处之后即可正常读取卡片信息,应注意Ultralight卡片不需要密钥访问,因此无需调用 PcdAuthState写入访问密钥,直接调用PcdRead函数即可例如Pcd_Read(0x00, buf),会直接返回卡片0,1,2,3扇区的16位内容,虽然Ultralight的每个区块只有四位,但是返回值和M1卡是一样的,都是16位,即范围所选区块后四块的内容,可以与M1卡做兼容处理*/}