概述
因为工作上有用到让板子与NFC标签进行通讯,所以研究了一下NFC技术中的ISO15693协议.
首先,我的使用场景是板子上有一个PN5180的NFC前端芯片,用做读卡器.与另一个设备做NFC通讯,这个设备使用ST25DV系列NFC标签芯片.
因为NFC技术本身有很多种协议,比如说ISO 14443,Felica也算是NFC技术.但是因为我的使用场景只需要支持这个设备上的ST25DV系列NFC标签芯片,所以下文中我提到NFC就代指ISO15693协议.
从底层来说
ISO15693的底层通讯的还是靠射频场,其编码使用脉冲位置调制(pulse position modulation,PPM).调制的数据包主要有两种,一种是请求命令包,一种是命令响应包.
请求命令包常见的格式如下:
SOF(1byte) | Flags(1byte) | Command Code | Parameters | Data | CRC | EOF(1byte) |
帧开始 | 标识 | 命令代码 | 参数 | 数据 | CRC | 帧结束 |
其中SOF(帧开始)作为包头,会决定通讯过程中的一些底层参数,比如说调制过程中的数据传送速率.这部分一般不需要固件的参与.
然后是请求命令包的Flags(标识),它的8bit各自的含义如下:
位(Bit) | 标志名称 | 描述 |
Bit0 | 副载波标志 | 0=VICC应使用单个副载波频率.1=VICC应使用两个副载波 |
Bit1 | 数据速率标志 | 0=使用低数据速率.1=使用高数据速率 |
Bit2 | 目录标志 | 0=Bit4到Bit7的含义按下方的表3解读.1=Bit4到Bit7的含义按下方的表4解读 |
Bit3 | 协议扩展标志 | 0=无协议格式扩展.1=协议格式已扩展,保留供以后使用 |
位(Bit) | 标志名称 | 描述 |
Bit4 | 选择标志 | 0=根据寻址标志设置,请求将由任何VICC执行.1=请求只由处于选择状态的VICC执行.寻址标志应设为0,UID域不应包含在请求中 |
Bit5 | 寻址标志 | 0=请求没有寻址,不包括UID域,可以由任何VICC执行.1=请求有寻址,`包括UID域,仅由那些自身UID与请求中规定的UID匹配的VICC才能执行 |
Bit6 | 选项标志 | 0=含义由命令描述定义,如果没有被命令定义,此Bit应设置为0.1:含义由命令描述定义. |
Bit7 | RFU |
位(Bit) | 标志名称 | 描述 |
Bit4 | AFI标志 | 0=AFI域没有出现.1=AFI域有出现. |
Bit5 | Nb_slots标志 | 0=16 slots.1=1 slot |
Bit6 | 选择权标志 | 0=含义由命令描述定义,如果没有被命令定义,此Bit应设置为0.1:含义由命令描述定义. |
Bit7 | RFU |
Command Code(命令代码)根据ISO15693的命令代码分成强制的、可选的、自定义以及私有的四种类型。它们的定义如下:
- 强制命令:命令代码(command code)取值范围为0x01~0x1F,所有标签(VICC)必须支持在该命令代码范围内的命令.
- 可选命令:命令代码取值范围为0x20~0x9F.在该命令代码范围的命令,标签可能支持.如果标签支持可选命令,它的命令格式在后续会介绍.如果标签不支持可选命令,并且寻址标识(Address_flag)或者选择标识(Select_flag)都设置了,它可能会返回错误码或者不响应,保持沉默.如果标签不支持可选命令,并且寻址标识(Address_flag)或者选择标识(Select_flag)未设置,那么标签就不会响应,会保持沉默.
- 自定义命令:命令代码取值范围为0xA0~0xDF,标签可以选择去支持它,自定义命令可以实现制造商的特殊功能.所有的自定义命令必须包含IC制作商编码.如果标签不支持自定义命令,那么给它发送自定义命令时,它应该返回错误码或者保持沉默.
- 私有命令:命令代码取值范围是0xE0~0xFF,在该命令代码的范围内的命令可以用于制造商测试,系统信息编码等.私有命令要求必须包含IC制造商代码以及IC版本号.
其中一些常用的命令如下:
命令代码 | 命令类型 | 命令作用 |
0x01 | 强制命令 | 清查命令(查找所有在射频场中的VICC) |
0x02 | 强制命令 | 保持按键命令(指定某个标签不再响应清查命令) |
0x03-0x1F | 强制命令 | 预留 |
0x20 | 可选命令 | 读取标签中指定单个块的内容 |
0x21 | 可选命令 | 将数据写入标签中指定的单个块中 |
0x22 | 可选命令 | 锁定标签中的指定块 |
0x23 | 可选命令 | 读取标签中指定多个块的内容 |
0x24 | 可选命令 | 将数据写入标签中指定多个块中 |
0x25 | 可选命令 | 选择某一标签(选中被发送了保持安静命令的标签) |
0x26 | 可选命令 | 重新准备(重置被发送了保持按键命令的标签) |
0x27 | 可选命令 | 写入AFI(Application Family Identifier) |
0x28 | 可选命令 | 锁定AFI |
0x29 | 可选命令 | 写入DSFID(Data Storage Format Identifier) |
0x2A | 可选命令 | 锁定DSFID |
0x2B | 可选命令 | 获取标签系统信息 |
0x2C | 可选命令 | 获取多个块的安全状态 |
0x2D-0x9F | 可选命令 | 预留 |
0xA0-0xDF | 自定义命令 | 由IC制造商决定 |
0xE0-0xFF | 私有命令 | 由IC制造商决定 |
命令响应包的常见的格式如下:
SOF | Flags | Parameters | Data | CRC | EOF |
帧开始 | 标识 | 参数 | 数据 | CRC | 帧结束 |
其中Flags的内容定义相对于请求命令包中的有所不同.定义如下:
位(Bit) | 标志名称 | 描述 |
Bit0 | 错误标志位 | 0=没有错误.1=出现错误 |
Bit1 | RFU | 应设置为0 |
Bit2 | RFU | 应设置为0 |
Bit3 | 协议扩展标志 | 0=无协议格式扩展.1=协议格式已扩展,保留供以后使用 |
Bit4 | RFU | 应设置为0 |
Bit5 | RFU | 应设置为0 |
Bit6 | RFU | 应设置为0 |
Bit7 | RFU | 应设置为0 |
如果Flags中的错误标志位为1,则一般情况下Flags后面跟着的就是具体的1byte长度的错误码(Error Code).其不同值的含义如下:
错误码(Error Code) | 含义 |
0x01 | 不支持该命令,即无法识别请求代码 |
0x02 | 命令无法识别,例如:出现格式错误 |
0x03 | 不支持该选项 |
0x0F | 未知错误 |
0x10 | 指定的块不可用(不存在) |
0x11 | 指定的块已经被锁定,因此不能再次锁定 |
0x12 | 指定的块被锁定,其内容不能更改 |
0x13 | 指定的块未成功编程 |
0x14 | 指定的块未成功锁定 |
0xA0-0xDF | 自定义命令错误码 |
其他值 | RFU |
往上爬爬
举例一个读单个块的命令(Read single block):
读卡器需要向标签发送请求命令包:
SOF | Flags | Read single block(0x20) | UID | Block number | CRC16 | EOF |
1byte | 1byte | 8byte | 1byte | 2byte |
然后标签发送命令响应包:
- 当命令执行出错时:
SOF | Flags | Error Code | CRC16 | EOF |
1byte | 1byte | 2byte |
- 当命令执行成功时:
SOF | Flags | Block security status | Data | CRC16 | EOF |
1byte | 1byte | N byte | 2byte |
再举例一个写单个块的命令(Write single block):
读卡器需要向标签发送请求命令包:
SOF | Flags | Write single block(0x21) | UID | Block number | Data | CRC16 | EOF |
1byte | 1byte | 8byte | 1byte | 块大小 | 2byte |
然后标签发送命令响应包:
- 当命令执行出错时:
SOF | Flags | Error Code | CRC16 | EOF |
1byte | 1byte | 2byte |
- 当命令执行成功时:
SOF | Flags | CRC16 | EOF |
1byte | 2byte |
下期再会
至此.基础的通讯就到此为止了.下一篇博文再讲讲更上一层的数据封装.
Comments | NOTHING