概述
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卡做兼容处理*/
}
读取操作的指令和M1卡片是一样的,因此在取得卡片的全部UID后可以采用同一个函数对Ultralight卡片进行读取
应注意, PcdAnticoll_type2是我自己写的函数,实际内容和 PcdAnticoll内容是一样的,只是将查询的指令由0x93变更为0x95,即ucComMF522Buf[0]的值需要修改
/
//Mifare Ultralight 卡二次防冲撞
/
char PcdAnticoll_type2(unsigned char *pSnr)
{
char status;
unsigned char i,snr_check=0;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x00);
ClearBitMask(CollReg,0x80);
ucComMF522Buf[0] = PICC_ANTICOLL2;//0x95,Ultralight二次选择需要的指令
ucComMF522Buf[1] = 0x20;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
if (status == MI_OK)
{
for (i=0; i<4; i++)
{
*(pSnr+i) = ucComMF522Buf[i];
snr_check ^= ucComMF522Buf[i];
}
if (snr_check != ucComMF522Buf[i])
{ status = MI_ERR; }
}
SetBitMask(CollReg,0x80);
return status;
}
在移植到PHY6212平台时,只需要重新对几个引脚操作进行重定义即可
#define MF522_RST_PIN GPIO_P20
#define MF522_MOSI_PIN GPIO_P03
#define MF522_SCK_PIN GPIO_P01
#define MF522_NSS_PIN GPIO_P02
#define MF522_MISO_PIN GPIO_P31
#define LED_WHITE GPIO_P34
#define LED_WARM GPIO_P00//我自己加的错误指示灯,可以不用
#define LED_ON hal_gpio_write(LED_WHITE, 1)
#define LED_OFF hal_gpio_write(LED_WHITE, 0)
#define ERR_ON hal_gpio_write(LED_WARM, 1)//我自己加的错误指示灯,可以不用
#define ERR_OFF hal_gpio_write(LED_WARM, 0)//我自己加的错误指示灯,可以不用
#define RST_H hal_gpio_fast_write(MF522_RST_PIN, 1)
#define RST_L hal_gpio_fast_write(MF522_RST_PIN, 0)
#define MOSI_H hal_gpio_fast_write(MF522_MOSI_PIN, 1)
#define MOSI_L hal_gpio_fast_write(MF522_MOSI_PIN, 0)
#define SCK_H hal_gpio_fast_write(MF522_SCK_PIN, 1)
#define SCK_L hal_gpio_fast_write(MF522_SCK_PIN, 0)
#define NSS_H hal_gpio_fast_write(MF522_NSS_PIN, 1)
#define NSS_L hal_gpio_fast_write(MF522_NSS_PIN, 0)
#define READ_MISO hal_gpio_read(MF522_MISO_PIN)//hal_gpio_read(MF522_MISO_PIN)
移植到其他平台也是一样,重新定义这些GPIO操作和引脚即可,我将完整代码上传到CSDN了,有需要可以下载,不闲麻烦的话可以自己根据这个流程改一下RC522的例程代码,有问题大家随时沟通,一起学习
下载地址:https://download.csdn.net/download/weixin_47047654/16817998
最后
以上就是畅快画板为你收集整理的RC522读取NFC Forum Type2 Tag流程及代码解析——Mifare Ultralight卡片读取(采用PHY6212平台,可移植)的全部内容,希望文章能够帮你解决RC522读取NFC Forum Type2 Tag流程及代码解析——Mifare Ultralight卡片读取(采用PHY6212平台,可移植)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复