NFC,全称是Near Field Communication,即“近场通信”,也叫“近距离无线通信”。NFC诞生于2004年,是基于RFID非接触式射频识别技术演变而来,由当时的龙头企业NXP(原飞利浦半导体)、诺基亚以及索尼联合发起。NFC采用13.56MHz频段,设计运行于20厘米距离之间,传输速度分为13.25KB/s、26.5KB/s、53KB/s三种。
NFC虽然具有只需要靠近就能快速完成配对和传输全过程的优势,但是所谓成也萧何败也萧何,其短距离才能建立连接,以及低带宽的特点在面对手机与其他电子设备无线连接需求时劣势尽显,再加上跟蓝牙相比,其需要单独的天线(蓝牙可以wifi公用),所以其在刚诞生之际鲜有移动设备搭载此项功能,倒是在门禁等安防系统中有所应用。后来随着移动支付的需求增加,NFC功能又迎来了新的机遇。
本篇文章从NFC的技术诞生背景将起,从最常见的应用入手,由上到下讲述了整个NFC技术从理论到实现的过程,NFC读卡器使用的是复旦微电子的FM17XX系列芯片,NFC卡片为M1。
目录
NFC技术概述
防止冲突机制
卡片认证
实现原理
嵌入式软件
卡片触发
INITVAL VALUE
读卡
写卡
在讲NFC之前,先讲讲它的前辈:RFID,其英文全称是radio-frequency identification,即射频识别技术。RFID系统使用标签(Tag)来识别物体。除了标签,RFID系统还有一个双向无线收发机,被称为读写器(Interrogator/Reader),向标签发送信号,并读取标签的反馈。RFID属于自动识别(AIDC:Automatic Identification and Data Capture)技术中的一种。这个识别过程如下:
NFC作为RFID技术的后辈,在设计之初旨在智能设备的近场双向通信,但是其诞生之后,应用最为广泛还是门禁的功能。
ISO14443协议是Contactless card standards(非接触式IC卡标准)协议,它定义了以下两个主体:
根据信号发送和接收方式的不同,ISO/IEC14443-3定义了TYPEA、TYPEB两种卡型。 以飞利浦,西门子公司为代表的TYPEA。 以摩托罗拉,意法半导体公司为代表的TYPEB。今天我们讲到的为M1卡,指的是菲利浦下属子公司恩智浦出品的芯片缩写,全称为NXP Mifare1系列,常用的有S50及S70两种型号,属于TYPEA类型。
读卡机我们文章涉及到的FM17XX系列芯片,可分别支持13.56MHz频率下的typeA、 typeB、15693三种非接触通信协议,支持MIFARE和SH标准的加密算法。
标准不仅定义了射频卡和读写器的物理特性,例如频率和天线设计,还描述了射频卡与读写器之间的初始化和防冲突机制以及数据传输协议和指令集。下图是文章涉及的读卡机与卡片的通信流程。
读卡器正常情况下一个时间点只能对磁场中的一张卡进行读或写操作,但是实际应用中经常有当多张卡片同时进入读写器的射频场,读写器怎么处理呢?读写器需要选出特定的一张卡片进行读或写操作,这就是标签防碰撞。常见的防冲突机制主要有以下几种:
三重加密算法被用于执行标准认证。在密钥缓冲器中必须存储准确的密钥以便能够进行成功的认证操作。
使用任意型号的MCU(一般需要具有低功耗模式)作为微处理器(下图中的uProcessor),MCU与FM17XX系列芯片采用SPI接口进行通信,天线直接连接FM17XX,具体如下图。
嵌入式软件从下到上主要分为以下三层:
下面主要将应用功能的部分函数贴上来供各位深入理解读卡器对卡片的操作功能。
/*************************************
/*名称: HL Active
/*功能: 该函数实现高级 MIFARE 卡激活命今
/*输入: Secnr: 扇区号
/* Block Adr: 块地址
/*输出:操作状态码
/* 读出数据存于 buffer 中
*************************************/
uchar HL_Active(uchar Block_Adr,uchar Mode)
{
uchar temp;
Secnr = Block_Adr/4;
MIF_Halt(); //Halt
temp = Request(RF_CMD_REQUEST+STD);//Request
if(temp != FM1715_OK)
{
return(FM1715_REQERR);
}
temp = AntiColl(); //AntiCol
if(temp != FM1715_OK)
{
return(FM1715_ANTICOLLERR);
}
temp = Select_Card(); ///Select
if(temp != FM1715_OK)
{
return(FM1715_SELERR);
}
Load_keyE2_CPY((Secnr%16),Wode);//LoadKey
temp = Authentication(UID, Secnr, Mode);//Authentication
if(temp != FM1715_OK)
{
return(FM1715 AUTHERR)
}
return FM1715_OK;
}
/**************************************
/*名称:MIF_Initival
/*功能: 该函数实现 MIFARE 卡初始化值操作
/*输入: buff: 四个字节初始化数值起始地加
/* Block Adr: 块地址
/*输出: FM1715 NOTAGERR:无卡
/* FM1715 BYTECOUNTERR: 接收字节错误
/* FM1715 NOTAUTHERR: 未经权威认证
/* FM1715 EMPTY:数据溢出错误
/* FM1715 CRCERR: CRC 校验错
/* FM1715 PARITYERR: 奇偶校验错
/* FM1715 WRITEERR: 写卡块数据出错
/* FM1715 0K: 应答正确
/**************************************
uchar MIF_Initival(uchar idata *buff,uchar Block_Adr)
{
uchar idata temp;
uchar i;
for (i = 0; i < 4: i++)
{
*(buff + 4 + i)=~(*(buff + i));
}
for (i = 0;i < 4: i++)
{
*(buff + 8 + i)=*(buff + i);
}
*(buff + 12) = Block Adr;
*(buff + 13) =Block Adr;
*(buff + 14) = Block Adr;
*(buff + 15) =Block Adr;
temp = MIF_Write(buff, Block_Adr);
return temp;
}
/***************************
/*名称: HL Read
/*功能:该函数实现高级读命令
/*输入:Secnr: 扇区号
/* Block Adr: 块地址
/*输出:操作状态码
/*读出数据存于 buffer 中
/***************************
uchar HL_Read(uchar idata *buff,uchar Block_Adr,uchar Mode)
{
uchar temp;
temp = HL Active(Block_Adr, Mode);
if(temp != FM1715_OK)
{
return temp;
}
//Read
temp = MIF_READ (buff,Block_Adr);
if(temp != FM1715_OK)
{
return temp;
}
return FM1715_OK
}
/*******************************
/*名称: HL Write
/*功能:该函数实现高级写命令
/*输入: buff: 待写入数据的首地址
/* Secnr: 刷区号
/* Block Adr: 块地址
/*输出:操作状态码
/*******************************
uchar HL_Write(uchar idata *buff,uchar Block_Adr,uchar Mode)
{
uchar temp;
temp = HL_Active(Block_Adr, Mode);
if(temp != FM1715_OK)
{
return temp;
}
//Write
temp = MIF_Write(buff, Block_Adr);
if(temp != FM1715_OK)
{
return FM1715_WRITEERR;
}
return FM1715_OK;
}
十六宿舍 原创作品,转载必须标注原文链接。
©2023 Yang Li. All rights reserved.
欢迎关注 『十六宿舍』,大家喜欢的话,给个,更多关于嵌入式相关技术的内容持续更新中。