PN532 NFC HAT 是专为树莓派设计的 NFC 扩展板,采用PN532主控,同时支持I2C、SPI和串口通信,可以给树莓派扩展 NFC 通讯功能。
PN532是一个高度集成的、工作于13.56MHz的非接触读写芯片。它包含80C51微控制器内核,集成了40Kbytes ROM 和 1Kbytes RAM。
PN532把调制和解调的概念完全集成在13.56MHz的各种非接触通信方式和协议中,具有易于使用的固件,适用于不同的模式,以及不同的主机控制接口。
用户可以用电脑通过串口快速验证PN532的功能,无需树莓派。验证的时候需要一个串口转USB模块(如 FT232 模块)。
PN532 NFC HAT | 串口模块 |
---|---|
3V3 | 3.3V |
GND | GND |
TX | RX |
RX | TX |
- 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 03 FD D4 14 01 17 00
(参见PN532 User Manual的HSU wake up condition章节)
模块的响应帧:
- 00 00 FF 00 FF 00 00 00 FF 02 FE D5 15 16 00
- 00 00 FF 04 FC D4 4A 01 00 E1 00
把卡贴近模块的线圈部分,模块会响应:
- 00 00 FF 0C F4 D5 4B 01 01 00 04 08 04 XXXXXXXXXX 00
该帧中的XXXXXXXXXX 是指4字节的卡ID和1字节的校验码。(参见PN532 User Manual的InListPassiveTarget章节)
PN532 NFC HAT 支持三个接口:串口、I2C和SPI。用户可以根据需要采用不同的接口,让树莓派和模块进行通讯。把模块连接到树莓派之后,需要通过I0、I1跳线选择工作模式。还需要通过拨码开关,让模块的接口连接到树莓派的对应接口。
请根据自己的实际使用情况选用接口:
从#示例程序下载例程,解压,并将raspberrypi文件夹复制到树莓派的/home/pi目录下。你可先将程序复制到/boot/,再复制到/home/pi 或者在树莓派终端运行:
- sudo apt-get install p7zip-full
- wget http://www.waveshare.net/w/upload/6/67/Pn532-nfc-hat-code.7z
- 7z x Pn532-nfc-hat-code.7z -r -o./Pn532-nfc-hat-code
- sudo chmod 777 -R Pn532-nfc-hat-code/
1. 使用跳线帽,把I0设置为L,l1设置为H
2. 用跳线帽连接RSTPDN->D20
3. 将拨码开关设置为
SCK | MISO | MOSI | NSS | SCL | SDA | RX | TX |
ON | ON | ON | ON | OFF | OFF | OFF | OFF |
4. 将PN532 NFC HAT插入到树莓派的40PIN GPIO上
PN532 NFC HAT | Raspberry Pi (BCM) |
---|---|
SCK | SCK |
MISO | MISO |
MOSI | MOSI |
NSS | P4 |
5. 启用SPI接口
打开树莓派终端,执行sudo raspi-config进入配置界面
选择Interfacing Options -> SPI -> Yes
6. 执行示例程序(以example_get_uid.py和rpi_get_uid.c为例)
打开终端,进入到程序目录:
- cd ~/raspberrypi/
1) python程序:
进入python程序目录: cd ~/raspberrypi/python/
修改example_get_uid.py文件,初始化pn532对象相关语句改成:
- pn532 = PN532_SPI(debug=False, reset=20, cs=4)
- #pn532 = PN532_I2C(debug=False, reset=20, req=16)
- #pn532 = PN532_UART(debug=False, reset=20)
修改完之后保存,并运行例程
- python3 example_get_uid.py
2) C 程序:
进入c程序目录:cd ~/raspberrypi/c/example/
修改rpi_get_uid.c,初始化pn532相关语句改为:
- PN532_SPI_Init(&pn532);
- //PN532_I2C_Init(&pn532);
- //PN532_UART_Init(&pn532);
保存文件,并重新编译:sudo make
运行程序:
- ./rpi_get_uid.exe
7. 预期结果:将卡贴近模块的线圈部分,可以读取卡的UID信息
1. 使用跳线帽,把I0设置为L,l1设置为L
2. 用跳线帽连接RSTPDN ->D20
3. 将拨码开关设置为
SCK | MISO | MOSI | NSS | SCL | SDA | RX | TX |
OFF | OFF | OFF | OFF | OFF | OFF | ON | ON |
4. 将PN532 NFC HAT插入到树莓派的40PIN GPIO上
PN532 NFC HAT | Raspberry Pi |
---|---|
RX | TX |
TX | RX |
5. 启动树莓派串口。默认情况下,树莓派的串口用于登录Shell终端,如果需要使用串口和外部设备通信的话,需要手动开启硬件串口
打开树莓派终端,输入sudo raspi-config 进入配置界面
选择Interfacing Options-> Serial -> No -> Yes
【注】这里开启硬件串口之后,可能需要重启,正常重启即可
6. 运行示例程序(以example_get_uid.py和rpi_get_uid.c为例)
打开终端,进入到程序目录:
- cd ~/raspberrypi/
1) python程序:
进入python程序目录: cd ~/raspberrypi/python/
修改example_get_uid.py文件,初始化pn532对象相关语句改成:
- #pn532 = PN532_SPI(debug=False, reset=20, cs=4)
- #pn532 = PN532_I2C(debug=False, reset=20, req=16)
- pn532 = PN532_UART(debug=False, reset=20)
修改完之后保存,并运行例程
- python3 example_get_uid.py
2) C 程序:
进入c程序目录:cd ~/raspberrypi/c/example/
修改rpi_get_uid.c,初始化pn532相关语句改为:
- //PN532_SPI_Init(&pn532);
- //PN532_I2C_Init(&pn532);
- PN532_UART_Init(&pn532);
保存文件,并重新编译:sudo make
运行程序:
- ./rpi_get_uid.exe
7. 预期结果:将卡贴近模块的线圈部分,可以读取卡的UID信息
- cd ~/raspberrypi/python/
- python3 example_uart_hex.py
输入16进制编码的原始数据然后回车发送,终端会显示发送的数据和接收到的细腻。例如发送以下数据唤醒模块:
- 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 03 FD D4 14 01 17 00
终端显示模块的响应数据:
- 00 00 FF 00 FF 00 00 00 FF 02 FE D5 15 16 00
1. 使用跳线帽,把I0设置为H,l1设置为L
2. 用跳线帽连接RSTPDN ->D20, 连接INT0 -> D16(避免Clock Stretching)
3. 将拨码开关设置为
SCK | MISO | MOSI | NSS | SCL | SDA | RX | TX |
OFF | OFF | OFF | OFF | ON | ON | OFF | OFF |
4. 将PN532 NFC HAT插入到树莓派的40PIN GPIO上
PN532 NFC HAT | Raspberry Pi |
---|---|
SCL | SCL |
SDA | SDA |
5. 启动树莓派I2C接口。
打开树莓派终端,输入sudo raspi-config 进入配置界面
选择Interfacing Options-> I2C -> Yes
6. 运行示例程序(以example_get_uid.py和rpi_get_uid.c为例)
打开终端,进入到程序目录:
- cd ~/raspberrypi/
1) python程序:
进入python程序目录: cd ~/raspberrypi/python/
修改example_get_uid.py文件,初始化pn532对象相关语句改成:
- #pn532 = PN532_SPI(debug=False, reset=20, cs=4)
- pn532 = PN532_I2C(debug=False, reset=20, req=16)
- #pn532 = PN532_UART(debug=False, reset=20)
修改完之后保存,并运行例程
- python3 example_get_uid.py
2) C 程序:
进入c程序目录:cd ~/raspberrypi/c/example/
修改rpi_get_uid.c,初始化pn532相关语句改为:
- //PN532_SPI_Init(&pn532);
- PN532_I2C_Init(&pn532);
- //PN532_UART_Init(&pn532);
保存文件,并重新编译:sudo make
运行程序:
- ./rpi_get_uid.exe
7. 预期结果:将卡贴近模块的线圈部分,可以读取卡的UID信息
1. 电脑需要安装Arduino IDE。
2. 在Arduino的项目文件夹下(默认为C:\Program Files (x86)\Arduino\libraries,可通过Arduino IDE的文件首选项项目文件夹位置进行指定)创建新文件夹,名字改成pn532。
3. 把 pn532.c、pn532.h、pn532_uno.cpp、pn532_uno.h这四个文件复制到Arduino\libraries\pn532 文件夹下。
4. 示例程序位于examples\arduino目录下。
5. 下面以Arduino UNO 开发板为例
1. 通过跳线帽,把I0设置为L,l1设置为H
2. 设置拨码开关为:
SCK | MISO | MOSI | NSS | SCL | SDA | RX | TX |
ON | ON | ON | ON | OFF | OFF | OFF | OFF |
3. 连接PN532 NFC HAT与Arduino:
PN532 NFC HAT | Arduino UNO |
---|---|
SCK | D13 |
MISO | D12 |
MOSI | D11 |
NSS | D4 |
4. 执行示例程序(以examples\arduino\uno_get_uid\ uno_get_uid.ino 为例):
双击打开 uno_get_uid.ino文件,初始化pn532相关语句改为:
- PN532_SPI_Init(&pn532);
- //PN532_I2C_Init(&pn532);
编译和上传程序到Arduino UNO
打开串口监视器,按下Arduino UNO的复位键
5. 预期结果: 把卡贴近模块的线圈部分,即可读取卡的UID
1. 使用跳线帽,把l0设置为L,l1设置为H
2. 拨码开关设置为
SCK | MISO | MOSI | NSS | SCL | SDA | RX | TX |
OFF | OFF | OFF | OFF | ON | ON | OFF | OFF |
3. 连接PN532 NFC HAT和Arduino UNO
PN532 NFC HAT | Arduino UNO |
---|---|
SCL | A5 |
SDA | A4 |
4. 执行示例程序(以examples\arduino\uno_get_uid\ uno_get_uid.ino 为例):
双击打开 uno_get_uid.ino文件,初始化pn532相关语句改为:
- //PN532_SPI_Init(&pn532);
- PN532_I2C_Init(&pn532);
编译和上传程序到Arduino UNO
打开串口监视器,按下Arduino UNO的复位键
5. 预期结果: 把卡贴近模块的线圈部分,即可读取卡的UID
示例程序使用的开发板是Open103C,主控芯片是STM32F103CBT6。STM32程序我们只提供SPI通信方式,如果需要其他通信方式,需要自行添加
1. 使用keil打开工程文件(例程\MDK-ARM\pn532_stm32.uvprojx),点击 Rebuild 编译工程。
2. 选择下载器:Options for Target -> Debug选项卡-> Use,默认情况下是 ST-Link Debugger。
3. 选择下载接口:Options for Target -> Debug选项卡 -> Settings -> Debug 选项卡 -> Port,默认情况下是 JTAG.
4. 通过下载器,连接开发板和电脑。
5. 点击 Download 下载工程。
1. 通过跳线帽,把 I0 设置为 L,I1 设置为 H。
2. 拨码开关设置为
SCK | MISO | MOSI | NSS | SCL | SDA | RX | TX |
ON | ON | ON | ON | OFF | OFF | OFF | OFF |
3. 连接PN532 NFC HAT和STM32开发板
PN532 NFC HAT | STM32F103CBT6 |
---|---|
SCK | PA5 |
MISO | PA6 |
MOSI | PA7 |
NSS | PA4 |
4. 通过USB串口线或者串口模块,连接STM32 开发板的UART1接口(PA9->RX, PA10->TX)到电脑
5. 打开串口监视器,按下STM32开发板的复位键
6. 预期结果: 把卡贴近模块的线圈部分,即可获取卡的 UID。
上面的演示是以获取 Mifare Classic 卡的 ID 作为例子(example_get_uid.py / rpi_get_uid.exe / uno_get_uid.ino / stm32_get_uid),下面将对其他示例程序进行说明。
【注意】
使用这些程序之前,请根据实际情况,设置 PN532 NFC HAT 的I0 / I1 跳线以及拨码开关。拨码开关不能同时设置为ON,否则无法接收到正确的数据。简单起见,这里用0表示拨码开关拨到OFF,用1表示拨码开关拨到ON。
程序 | 开发板 |
example_dump_mifare.py | Raspberry Pi |
rpi_dump_mifare.c | Raspberry Pi |
uno_dump_mifare.ino | Arduino UNO |
stm32_dump_mifare/MDK-ARM/pn532_stm32.uvprojx | STM32F103CBT6 |
预期结果:把Mifare Classic 卡贴近PN532 NFC HAT,卡的内容会被打印出来
- 0 : 37 F9 20 69 87 08 04 00 62 63 64 65 66 67 68 69
- 1 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 2 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 3 : 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF
- 4 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 5 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 6 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 7 : 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF
- 8 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 9 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 11 : 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF
- … …
- 63 : 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF
说明:
以读取第6块为例,必须使用对应扇区的密码,即第7块的前6个字节(KEY A)或者后6字节(KEY B)的密码
- 7 : 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF
前6个字节为KEY A,默认为FF FF FF FF FF FF,但是其读取结果永远为00 00 00 00 00 00。后6字节为KEY B,使用明文存储,Mifare Classic卡默认的KEY A和KEY B均为FF FF FF FF FF FF。
中间的4个字节是访问控制位(Access Bits)。默认值FF 07 80 69,这个数值用于扇区得写的访问权限控制,用户如果对其写入不合适的数值,将会导致卡被锁死。
例如byte6写入0xFF,那么byte7的高4位必须为0b0000, byte 8的低4位必须为0b0000。具体参见MF1S50YYX_V1.pdf 的 Access conditions for data blocks 节
产品随附的卡是魔法卡,通过预留的后门可以解锁,但是用户应当知道,如果使用常规的 Mifare 卡,一旦把访问控制位写错,将会无法修复。所以在写卡的时候要特别注意
程序 | 开发板 |
example_rw_mifare.py | Raspberry Pi |
rpi_rw_mifare.c | Raspberry Pi |
uno_rw_mifare.ino | Arduino UNO |
stm32_rw_mifare/MDK-ARM/pn532_stm32.uvprojx | STM32F103CBT6 |
预期结果:把Mifare Classic卡贴近PN532 NFC HAT,第6块的内容会被改写成00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F。
说明:
程序 | 开发板 |
example_dump_ntag2.py | Raspberry Pi |
rpi_dump_ntag2.c | Raspberry Pi |
uno_dump_ntag2.ino | Arduino UNO |
stm32_dump_ntag2/MDK-ARM/pn532_stm32.uvprojx | STM32F103CBT6 |
预期结果:把Ntag215卡贴近PN532 NFC HAT,卡的内容会被打印出来
- 0: 04 85 32 3b
- 1: 92 a8 64 80
- 2: de 48 00 00
- 3: e1 10 3e 00
- 4: 03 00 fe 00
- 5: 00 00 00 00
- 6: 00 00 00 00
- 7: 00 00 00 00
- … …
- 134: 00 00 00 00
说明:
程序 | 开发板 |
example_rw_ntag2.py | Raspberry Pi |
rpi_rw_ntag2.c | Raspberry Pi |
uno_rw_ntag2.ino | Arduino UNO |
stm32_rw_ntag2/MDK-ARM/pn532_stm32.uvprojx | STM32F103CBT6 |
预期结果:把NTAG215卡贴近PN532 NFC HAT,第6块的内容会被改写成00 01 02 03。
说明:
程序 | 开发板 |
example_write_gpio.py | Raspberry Pi |
rpi_write_gpio.c | Raspberry Pi |
uno_write_gpio.ino | Arduino UNO |
stm32_write_gpio/MDK-ARM/pn532_stm32.uvprojx | STM32F103CBT6 |
预期结果:打印PN532的GPIO电平
- Pin P30: 1
- Pin P31: 0
- Pin P32: 1
- Pin P33: 0
- Pin P34: 1
- Pin P35: 0
- Pin P71: 0
- Pin P72: 1
- Pin I0: 1
- Pin I1: 0
说明:
程序尝试设置管脚电平:P30 -> 高,P31 -> 低,P33 -> 低,P35 -> 低,P71 -> 低,P72 -> 高
注意:
PN532的P30 – P35电平会在硬件复位(RSTPDN置低2ms然后置高)之后,恢复为高电平。
程序 | 开发板 |
example_read_gpio.py | Raspberry Pi |
rpi_read_gpio.c | Raspberry Pi |
uno_read_gpio.ino | Arduino UNO |
stm32_read_gpio/MDK-ARM/pn532_stm32.uvprojx | STM32F103CBT6 |
预期结果:会打印PN532的GPIO电平
- Port P3: 0x3f
- Port P7: 0x07
- Port I: 0x07
- Pin P30: 1
- Pin P31: 1
- Pin P32: 1
- Pin P33: 1
- Pin P34: 1
- Pin P35: 1
- Pin I0: 1
- Pin I1: 0
说明: