理解 PN532 的命令是进行二次开发和功能实现的核心,其命令体系主要分为两大类:

- 来自主机的命令:由你的主控MCU(如Arduino)发送给PN532芯片,要求它执行某个操作。
- 来自PN532的中断/响应:PN532在完成操作或检测到特定事件后,主动向主机发出的通知或对主机命令的回应。
下面我们将详细介绍这两类命令,并提供一些常用的命令示例。
核心概念:通信帧格式
在深入具体命令之前,必须理解 PN532 的通信帧格式,所有命令和响应都遵循这个结构,否则无法被正确解析。
帧结构:
| 域 | 描述 | 长度 | 示例值 |
|---|---|---|---|
| Preamble (前导码) | 固定为 0x00 |
1 字节 | 0x00 |
| Start Code (起始码) | 固定为 0x00 0xFF |
2 字节 | 0x00, 0xFF |
| Length (长度) | 数据长度字段的长度 + 命令码字段的长度 | 1 字节 | 0x06 (表示后面有6个字节的数据) |
| Length Check (长度校验) | ~Length (Length字节的按位取反) |
1 字节 | 0xF9 (如果Length是0x06) |
| Data (数据) | TFI (协议指示符) + Packet Identifier (命令码) + 参数 | 可变 | 0xD5 (TFI主机->目标) + 0x40 (命令码) + ... |
| Postamble (后缀码) | 固定为 0x00 |
1 字节 | 0x00 |
数据字段详解:

- TFI (Target Field Identifier): 标识数据包的来源和去向。
0xD4: 主机 -> PN5320xD5: PN532 -> 主机
- Packet Identifier (PID / 命令码): 这是一个字节,定义了具体的命令或响应类型,这是命令的核心。
来自主机的命令 (Host -> PN532)
这些命令由主控MCU发起,告诉PN532“做什么”,下面是一些最常用的命令。
固件/信息查询命令
InFirmwareCommand (命令码: 0x00)
用于读取PN532的固件版本、库版本和芯片回读版本,是调试和识别芯片的第一步。
- 数据字段: 无
- 示例 (使用 Adafruit PN532 库):
// 在 Arduino 中调用库函数 nfc.firmwareVersion(); // 库会自动构建并发送完整的帧,然后解析响应
初始化与配置命令
SAMConfiguration (命令码: 0x14)
配置 PN532 的安全接入模块,这是NFC读卡器模式下的关键配置,决定了PN532如何与卡片/标签通信。
-
参数:
(图片来源网络,侵删)mode: 配置模式0x00: 普通模式 (Normal mode),PN532作为读卡器,主动检测和初始化卡片。0x01: 虚拟SAM卡模式 (Virtual card mode),PN532模拟成一张卡,等待其他读卡器来读取。0x02: 双重角色模式 (Dual role mode),PN532既可以作为读卡器,也可以作为卡。0x03:mode+0x20: 在普通模式下开启高驱动能力。
-
示例 (配置为普通读卡器模式):
// 构造数据: TFI(0xD4) + Command(0x14) + Param(0x00) uint8_t_tfi = 0xD4; uint8_t_tfi = 0x14; // SAMConfiguration command uint8_t_params[] = {0x00}; // Normal mode // 发送命令... (需要手动构造完整的帧)
ConfigurePH (命令码: 0x32)
配置高频通信的调制参数,如ASK调制指数和波特率。
- 参数:
Protocol: 协议类型,固定为0x01(ISO/IEC 14443 Type A/B)。BaudRate: 波特率,0x00为 106 kbps (标准)。FRAMING: 帧结构,0x01为标准帧。SENS_RES: 卡片响应的第一个字节。NAD: 下一地址,通常为0x00。
- 示例 (配置为106kbps的Type A):
// 这个命令比较底层,通常库会自动处理
寻卡与通信命令
InListPassiveTarget (命令码: 0x4A)
这是最核心的寻卡命令,它让PN532在指定范围内寻找被动的NFC标签/卡片。
- 参数:
BaudRate: 目标通信速率,0x00为 106 kbps。TargetNumber: 要寻找的目标数量,0x01(找1个)。TargetType: 目标类型0x00: 14443-3A (Type A)0x01: 14443-3B (Type B)0x02: ISO/IEC 156930x03: FeliCa (Sony)0x04: ISO/IEC 14443-4A (Type A with T=CL)0x05: ISO/IEC 14443-4B (Type B with T=CL)
- 示例 (寻找一张Type A卡):
// 构造数据: TFI(0xD4) + Command(0x4A) + Params uint8_t params[] = {0x01, 0x00, 0x00}; // 1 target, 106kbps, Type A // 发送命令...
InDataExchange (命令码: 0x40)
当找到卡片后,使用此命令与卡片进行数据交换(如读取M1卡的数据块)。
- 参数:
TargetNumber: 目标索引,通常是0x00(找到的第一个目标)。cmd_len: 发送给卡片的命令长度。cmd_data: 发送给卡片的命令数据 (读取块0x04的命令0x30 0x04 0x04)。
- 示例 (读取M1卡第4块的数据):
// M1卡读取块命令: [0x30] [块地址] [CRC校验] // 块地址为0x04, CRC计算后为0xA4, 0xB1 uint8_t cmd_to_card[] = {0x30, 0x04, 0xA4, 0xB1}; uint8_t params[] = {0x00, sizeof(cmd_to_card)}; // Target 0, cmd length // 发送数据: TFI(0xD4) + Command(0x40) + params + cmd_to_card // PN532会将此命令发给卡片,然后将卡片返回的数据再发回给主机
来自PN532的响应/中断 (PN532 -> Host)
PN532在执行完命令或发生特定事件(如检测到卡片)后,会向主机发送响应。
响应帧结构
响应帧和命令帧的结构类似,只是TFI是 0xD5 (PN532 -> 主机)。
| 域 | 描述 | 示例值 |
|---|---|---|
| Preamble | 0x00 |
0x00 |
| Start Code | 0x00 0xFF |
0x00, 0xFF |
| Length | 数据长度 + 命令码长度 | 0x01 (对于 ACK 响应) |
| Length Check | ~Length |
0xFE |
| Data | TFI (0xD5) + Packet Identifier (响应码) + 参数 | 0xD5 + 0x00 + ... |
| Postamble | 0x00 |
0x00 |
常见响应码
ACK (响应码: 0x00)
表示PN532成功接收了主机的命令,但并不意味着命令已成功执行,它只是一个“我收到了”的确认,对于某些命令(如 SAMConfiguration),成功执行后会返回 ACK。
NACK (响应码: 0x01)
表示PN532未能接收主机的命令,通常是数据校验错误或帧格式错误。
Command Response (响应码: 0x80)
这是对大多数主机命令(如 InFirmwareCommand, InListPassiveTarget)的成功响应,它包含了命令执行后的具体数据。
-
示例1: 对
InFirmwareCommand的响应- 数据:
0xD5(TFI) +0x80(响应码) +0x04(数据长度) +0x32(IC版本) +0x01(支持协议) +0x04(固件版本) +0x00(支持特性) - 解析后可知:IC版本
v32,支持协议v1.4,固件版本v4.0。
- 数据:
-
示例2: 对
InListPassiveTarget的响应 (找到Type A卡)- 数据:
0xD5(TFI) +0x80(响应码) +0x0A(数据长度) +0x01(找到目标数) +0x00(目标类型: 14443-3A) +0x04(目标NUID长度) +0x08+0x04+0x04+0x04(卡片的UID) +0x00(额外信息长度) - 解析后可知:找到了1张Type A卡,UID为
0x08 0x04 0x04 0x04。
- 数据:
Ready (响应码: 0xD1)
这是一个中断响应,当PN532检测到RF场内有卡片或标签时,会主动向主机发送这个 Ready 响应,而不是等待主机发送 InListPassiveTarget 命令,这通常在PN532配置为自动检测模式时发生。
- 数据:
0xD5+0xD1+0x01+0x00(表示1个目标就绪) - 主机收到
Ready后,通常会再发送InListPassiveTarget来获取卡片的详细信息。
实际应用流程示例 (作为读卡器读取M1卡)
-
初始化:
- 主机发送
SAMConfiguration(命令码0x14),参数设为0x00(普通模式)。 - PN532 返回
ACK(0xD5 0x00)。
- 主机发送
-
等待卡片:
- 方法A (轮询): 主机循环发送
InListPassiveTarget(命令码0x4A),参数设为寻找Type A卡,直到返回Command Response表示找到卡。 - 方法B (中断): PN532在检测到卡片后,主动向主机发送
Ready(0xD5 0xD1),主机收到后,再发送InListPassiveTarget。
- 方法A (轮询): 主机循环发送
-
获取卡片信息:
- 主机发送
InListPassiveTarget。 - PN532 返回
Command Response,其中包含卡片的类型和UID。
- 主机发送
-
与卡片通信 (读取数据):
- 主机构造M1卡读取指令 (如
0x30 0x04 0xA4 0xB1)。 - 主机发送
InDataExchange(命令码0x40),参数包含目标索引和读取指令。 - PN532 将读取指令转发给卡片。
- PN532 收到卡片返回的数据后,再向主机发送
Command Response,其中包含16字节的M1卡块数据。
- 主机构造M1卡读取指令 (如
-
关闭通信:
- 主机可以发送
InDeselect(命令码0x44) 来取消与当前卡片的连接,以便检测下一张卡片。
- 主机可以发送
| 命令/响应 | 命令码 | 方向 | 主要用途 |
|---|---|---|---|
| InFirmwareCommand | 0x00 |
H -> P | 读取版本信息 |
| SAMConfiguration | 0x14 |
H -> P | 设置工作模式 (读卡器/模拟卡) |
| ConfigurePH | 0x32 |
H -> P | 配置高频通信参数 |
| InListPassiveTarget | 0x4A |
H -> P | 寻找被动式标签/卡片 |
| InDataExchange | 0x40 |
H -> P | 与已找到的卡片进行数据交换 |
| ACK | 0x00 |
P -> H | 命令接收成功 |
| Command Response | 0x80 |
P -> H | 命令执行成功,返回数据 |
| Ready | 0xD1 |
P -> H | 检测到卡片,通知主机 |
对于开发者来说,通常不需要手动构造和解析这些底层的帧格式,可以使用现成的库(如 Adafruit PN532 Library for Arduino, libnfc, PN532 Python Library),这些库已经封装好了所有复杂的通信细节,你只需要调用高级API(如 nfc.targetPresent(), nfc.getData())即可,理解这些底层命令对于调试和实现特殊功能非常有帮助。
