STM32与PN532构建NFC近场通信指南(四):PN532握手数据流详解

目录

  1. STM32与PN532构建NFC近场通信指南(一):NFC及相关知识准备
  2. STM32与PN532构建NFC近场通信指南(二):PN532及恩智浦PN系列产品简介
  3. STM32与PN532构建NFC近场通信指南(三):PN532通信协议分析
  4. STM32与PN532构建NFC近场通信指南(四):PN532握手数据流详解
  5. STM32与PN532构建NFC近场通信指南(五):一种适用于STM32的通用串口通信架构及与PN532的通信实践

STM32与PN532构建NFC近场通信指南(四):PN532握手数据流详解

本章为系列指南第四章,主要介绍上位机与PN532进行Mifare S50卡片读写全流程的通信数据流。重点需要阅读PN532 User Manual.pdf的第7章,目录如下:

芯片指令集

上一章中,我们了解了PN532的通信协议,其数据帧格式中有一段数据负载区域DATA,从PD0到PDn。在PN532UM 第7章中有如下描述:

如上图,对于0xD4发送包,将DATA区域细化成了Command Code+Optional Input Data,同时在列表中列举了所有的Command Code。对于0xD5接收包,则是Command Code+1 + Optional Output Data

请求版本号测试

我们可以通过以下方法构造一个简单的数据包,来请求PN532的内部固件版本号:

  • TFI + DATA区域:0xD4 0x02
  • LEN: 0x02
  • LCS: 0xFE
  • DCS: 0x00 - checksum = 0x00 - (D4+02) = 0x00 - D6 = 0x2A

包结构构造为:00 00 FF 02 FE D4 02 2A 00

将PN532模块的4根引脚与PC-USB-CH340模块(或者其他USB-TTL串口设备)相连,使用串口调试助手等软件进行上位机模拟:

对照通信协议,我们可以很容易理解:发包后成功收到了一个6字节ACK包,随后收到了一个Reponse数据,解析内部DATA为:03 32 01 06 07,其中03是发送指令02的+1响应,后面32 01 06 07为返回的固件版本号。

继续根据协议解析为:

  • 32:IC,跟文档描述一致,为0x32
  • 01:Ver, 大版本号
  • 06:Rev, 小版本号
  • 07:Support,二进制是0000 0111,表示支持ISO18092,ISO14443B,ISO14443A

OK,至此我们已经成功的理解了所有通信时所涉及的知识点,并且打通了第一次与PN532的通信。下面就是根据实际业务需求,进行数据包的请求和接受了。

Mifare S50卡的读写流程

在本系列教程的第二讲STM32与PN532构建NFC近场通信指南(二):PN532及恩智浦PN系列产品简介中,我们提到,对于Mifare S50卡的读写流程,大致上分为以下步骤:

  • 寻卡
  • 认证
  • 读写卡
  • 释放(不重要)

那么就按照这个步骤来看看上位机应该如何与PN532进行通信:

寻卡


打开手册到7.3.5章节,这一章的InListPassiveTarget指令就是寻卡的意思,可以看到它的Command Code是0x4A,后面还有MaxTgBrTy两个参数,根据它的描述即可构建以下包:
00 00 FF 04 FC D4 4A 01 00 E1 00
如果此时有一张Mifare S50卡在附近,我们将得到以下响应:
ACK:00 00 FF 00 FF 00
Response:

header   len lcs tfi cmd  NbTg tg sens_res sel_res  nfcIDLength NFCID       dcs tail
00 00 FF 0C  F4  D5  4B   01   01 00 04    08       04          39 01 0B B1 D8  00

其中39 01 0B B1是这张卡片的UUID,这个我们需要寄到本本上,后面还需要使用。如果在MCU中,那就设置一个32bit度的变量,将其缓存起来。

认证

搜到卡片后,下面一步就是用密码来进行登录认证。Mifare S50出厂密码一般是FF FF FF FF FF FF,个别情况下,还有A0 A1 A2 A3 A4 A512 34 56 12 34 56这几种情况。我们假定现在的密码是FF FF FF FF FF FF

打开文档7.3.8章,这一章讲InDataExchange指令。这个指令可以与NFC对象进行数据交互,我们需要实现的认证操作,作为这个指令的子指令集包含在其中,后面的数据读写指令也包含在这个指令集中。

仔细阅读手册的Page130页,这里罗列了我们需要的几个子指令集,包括认证和16字节的读写。并且还非常人性化地提供了几个example,我们仿照样例,构建一个对于2号数据块的认证包:

header    len  lcs  tfi  cmd  tg  mifareAuth3 sectionNum Pwd               uid         dcs tail
00 00 FF  0F   F1   D4   40   01  60          02         FF FF FF FF FF FF 39 01 0B B1 99  00

如果一切正常,密码认证通过后,我们将得到以下响应:
ACK:00 00 FF 00 FF 00
Response:

header   len  lcs  tfi  cmdResp data dcs tail
00 00 FF 03   FD   D5   41      00   EA  00

读写

根据文档,我们将很容易推断出16Byte的读写指令数据包,如下:
Request:

header   len lcs tfi cmd tg mifareRead sectionNum dcs tail
00 00 FF 05  FB  D4  40  01 30         02         B9  00

ACK:00 00 FF 00 FF 00
Response:

header   len  lcs  tfi  cmdResp errCode data                                            dcs tail
00 00 FF 13   ED   D5   41      00      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 EA  00

Request:

header   len lcs tfi cmd tg mifareWrite sectionNum data                                            dcs tail
00 00 FF 15  EB  D4  40  01 A0          02         01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 C1  00

ACK:00 00 FF 00 FF 00
Response:00 00 FF 03 FD D5 41 00 EA 00

小结

这一章我们对PN532的通信流程和相关指令集有了一次详细的梳理,根据我们的应用场景,设计出一套读写Mifare S50的最简数据流。下一章我们将用STM32作为上位机,使用串口作为通信介接口,与PN532进行通信,值得注意的是,下一章我们将探讨设计出一套通用的数据流处理框架,无论是使用UART, I2C, SPI都能平滑使用的读写数据流的架构,并不仅限于与PN532通信。