PN532 Complete Guide

NXP's Most Popular NFC Controller

| 5 min read

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"
  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

Terms in This Guide