PN532 Complete Guide
NXP's Most Popular NFC Controller
Complete guide to the NXP PN532 NFC controller covering I2C/SPI/UART interfaces, firmware commands, and integration examples.
PN532 Complete Guide: NXP's Most Popular NFC Controller
The PN532 is NXP's most widely deployed NFC nfc-controller for hobbyist and prototyping use. Released in 2007, it remains the default choice for Arduino, Raspberry Pi, and ESP32 NFC projects because of its mature library ecosystem and dual-interface (I2C + SPI + HSU) support.
PN532 at a Glance
| Property | Value |
|---|---|
| Manufacturer | NXP Semiconductors |
| Operating frequency | 13.56 MHz |
| Supply voltage | 3.3 V (I/O tolerant to 5 V via level shifter) |
| Current (active) | ~100 mA (RF on) |
| Current (standby) | ~5 mA |
| Interface | I2C, SPI (up to 5 MHz), HSU (UART) |
| Tag support | ISO 14443A/B, iso-15693, FeliCa, MIFARE |
| Host controller modes | Reader/Writer, card-emulation-mode, peer-to-peer-mode |
| Max read-range | ~5 cm (antenna dependent) |
Hardware Interface Selection
The PN532 exposes three interfaces simultaneously but activates only one based on the I0/I1 pin states at power-up:
| I1 | I0 | Interface |
|---|---|---|
| 0 | 0 | HSU (UART, 115200 baud default) |
| 0 | 1 | I2C |
| 1 | 0 | SPI |
Most breakout boards (Adafruit PN532, Elechouse v3) provide DIP switches or solder jumpers for I0/I1. SPI is the fastest and most reliable for long cable runs. I2C allows address configuration but is limited to ~400 kHz and sensitive to bus capacitance.
Connecting to Arduino
SPI wiring (recommended):
| PN532 Pin | Arduino Uno |
|---|---|
| VCC | 3.3 V (or 5 V via onboard regulator) |
| GND | GND |
| SCK | 13 (SCK) |
| MISO | 12 (MISO) |
| MOSI | 11 (MOSI) |
| SSEL | 10 (SS, configurable) |
Install the Adafruit PN532 library via Library Manager. The library abstracts the TFI (Transport Frame Interface) framing and handles the PN532's acknowledgement handshake automatically.
#include <Adafruit_PN532.h>
#define PN532_SS 10
Adafruit_PN532 nfc(PN532_SS);
void setup() {
nfc.begin();
nfc.SAMConfig(); // Configure the Secure Access Module
}
void loop() {
uint8_t uid[7];
uint8_t uidLength;
if (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength)) {
// Tag detected
}
}
Connecting to Raspberry Pi
On Raspberry Pi, use the I2C or SPI interface via the GPIO header.
I2C setup:
1. Enable I2C: sudo raspi-config → Interface Options → I2C → Enable
2. Install libnfc: sudo apt install libnfc-bin libnfc-dev
3. Configure /etc/nfc/libnfc.conf:
device.name = "PN532 I2C"
device.connstring = "pn532_i2c:/dev/i2c-1"
- Test:
nfc-list— should print connected tags
The Python nfcpy library also supports the PN532 and provides a higher-level ndef read/write API:
import nfc
def on_connect(tag):
print(tag.ndef.message)
with nfc.ContactlessFrontend('i2c') as clf:
clf.connect(rdwr={'on-connect': on_connect})
Supported Tag Operations
| Operation | Tags Supported | Library Function |
|---|---|---|
| Read UID | All ISO 14443A/B, FeliCa, ISO 15693 | readPassiveTargetID() |
| Read NDEF | Type 1/2/3/4/5 | readNdefMessage() |
| Write NDEF | Type 2/4 (with password if protected) | writeNdefMessage() |
| MIFARE Classic auth | MIFARE Classic 1K/4K | mifareclassic_AuthenticateBlock() |
| MIFARE read/write | MIFARE Classic | mifareclassic_ReadDataBlock() |
| DESFire AES auth | DESFire EV1/EV2/EV3 | Via raw APDU commands |
| Card emulation | ISO 14443-4 (HCE-like) | tgInitAsTarget() |
Raw APDU Commands
For Type 4 tags and DESFire, the PN532 passes ISO 7816 APDUs directly. Use InDataExchange to send APDUs and receive responses:
uint8_t apdu[] = {0x00, 0xA4, 0x04, 0x00, 0x07,
0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01, 0x00};
uint8_t response[64];
uint8_t responseLen = sizeof(response);
nfc.inDataExchange(apdu, sizeof(apdu), response, &responseLen);
Performance Tuning
| Tuning Parameter | Default | Optimised |
|---|---|---|
| RF field on/off timing | Continuous | Pulse on demand (saves power) |
InListPassiveTarget timeout |
100 ms | Reduce for faster polling |
| Retry count | 3 | Set to 1 for single-poll scan |
| Baud rate (HSU) | 115200 | 460800 for lower latency |
PN532 vs Alternatives
| Controller | Interface | NDEF Library | Cost | Best For |
|---|---|---|---|---|
| PN532 | SPI/I2C/UART | Mature (Adafruit, nfcpy) | ~$5–15 | General prototyping |
| PN7150 | I2C (NCI) | NCI stack required | ~$10–20 | Linux embedded, Android |
| ST25R3916 | SPI | ST25R SDK | ~$8–20 | Multi-protocol, HF RFID |
| RC522 | SPI | MFRC522 library | ~$1–3 | MIFARE Classic only |
| ACR122U | USB | libnfc | ~$30 | PC-attached reader |
Common Issues and Fixes
| Issue | Likely Cause | Fix |
|---|---|---|
nfc.begin() hangs |
Wrong interface selected (I0/I1 mismatch) | Check DIP switch matches code |
| Tag not detected | Antenna detuned by nearby metal | Move away from metal; use ferrite-backed tag |
| MIFARE auth fails | Wrong key (default 0xFF×6) | Try both key A and key B; try default keys |
| SPI data corruption | Long cable, no decoupling caps | Shorten cable; add 100 nF cap on VCC |
| I2C address conflict | Another I2C device at 0x24 | Change I2C address or use SPI |
See Also
Frequently Asked Questions
Our guides cover a range of experience levels. Getting Started guides are written for beginners with no prior NFC knowledge. Programming guides target developers integrating NFC into mobile apps or embedded systems. Security guides are for engineers designing secure NFC deployments for payments, access control, or authentication.
Most guides require only an NFC-enabled smartphone (iPhone 7+ or any modern Android device) and a few NFC tags (NTAG213 or NTAG215 recommended for beginners, available for under $1 each). Advanced guides may reference USB NFC readers like the ACR122U or Proxmark3 for development and testing.
Yes. Programming guides include code examples for Android (Kotlin/Java with the Android NFC API), iOS (Swift with Core NFC), and web-based tools (Web NFC API for Chrome on Android). All code samples are tested and include inline comments explaining each step.