NXP PN5180A0xx / C1 / C2

カードリーダー 設定・動作手順

FT232H SPI接続 — pyftdi — ISO 14443 Type A/B / ISO 15693 対応
STEP 0 SPI 物理層 — BUSY ハンドシェーク

PN5180 は全コマンドで BUSY ピンによる処理完了通知を行う。

# NFCモード (通常動作) の正しいシーケンス spi.write(cmd) NSS HIGH # BUSYが HIGH になるまで待つ (処理開始) wait BUSY HIGH # BUSYが LOW になるまで待つ (処理完了) wait BUSY LOW # 読み出しが必要な場合 spi.read(N)
⚠ COMMON BUG
_wait_low() のみでは BUSY の HIGH 遷移を見逃し全 0xFF を返す。 必ず HIGH → LOW の両エッジを待つこと。
STEP 1 リセット — 起動確認
RST = LOW (20ms以上)
AUX2/DWL_REQ = LOW (通常NFCモード)
HIGH にすると SFWU Download mode に入る
RST = HIGH
BUSY = LOW になるまで待つ
EEPROM 0x16 bit0=1 (IDLE_IRQ_AFTER_BOOT) → IDLE IRQ 発生 → BUSY LOW
# 起動確認: SYSTEM_CONFIG レジスタ読み出し (期待値 0x00000000) WRITE [0x04, 0x00] READ 4B # IRQ_STATUS 確認 (bit2=IDLE_IRQ が立っていること) WRITE [0x04, 0x02] READ 4B # expect bit2=1 (0x00000004) # IRQ クリア (全ビット) WRITE [0x00, 0x03, FF FF FF FF]
STEP 2 プロトコル設定ロード — LOAD_RF_CONFIG (0x11)

EEPROMからRF設定をレジスタに読み込む。RF ON より前に必ず実行すること。

# LOAD_RF_CONFIG: [0x11, TX_config, RX_config] # TX=0xFF は変更しない (TX は前回のまま)
プロトコル TX index RX index コマンド例
ISO 14443A 106kbps 0x00 0x80 [0x11, 0x00, 0x80]
ISO 14443A 212kbps 0x01 0x81 [0x11, 0x01, 0x81]
ISO 14443A 424kbps 0x02 0x82 [0x11, 0x02, 0x82]
ISO 14443B 106kbps 0x04 0x84 [0x11, 0x04, 0x84]
FeliCa 212kbps 0x08 0x88 [0x11, 0x08, 0x88]
ISO 15693 0x0D 0x8D [0x11, 0x0D, 0x8D]
NOTE
EEPROMが消去されている場合(全0xFF)は LOAD_RF_CONFIG の効果がない。 事前に UPDATE_RF_CONFIG (0x12) でRAMにデフォルト値を書き込んでおく必要がある。
STEP 3 RF フィールド ON — RF_ON (0x16)
# RF_ON: [0x16, rf_on_config] # rf_on_config bit0: 0=通常(推奨), 1=外部フィールド検出後ON WRITE [0x16, 0x00] # RF ON 完了確認: IRQ_STATUS bit9 (TX_RFON_IRQ) を待つ wait IRQ_STATUS bit9 = 1 # 0x00000200 # IRQ クリア WRITE [0x00, 0x03, FF FF FF FF]

RF ON後、カードが応答できるまで 5ms以上 待つこと (ISO 14443 仕様)。

STEP 4 コマンド送信 — Transceive + SEND_DATA (0x09)

ISO 14443A の REQA → ATQA → Anticollision → SELECT の流れ:

## ① SYSTEM_CONFIG に Transceive コマンドをセット # WRITE_REGISTER(0x00) で SYSTEM_CONFIG(addr=0x00) の bits[2:0]=3 に設定 WRITE [0x00, 0x00, 03 00 00 00] # COMMAND=Transceive(0x3) ## ② REQA 送信 (7ビット, parity なし) # SEND_DATA: [0x09, num_valid_bits_last_byte, data...] # REQA = 0x26, 7ビット → num_valid_bits=7 WRITE [0x09, 0x07, 26] # START_SEND は SEND_DATA が自動セット → 送信開始 ## ③ 受信完了を IRQ_STATUS で確認 wait IRQ_STATUS bit0 = 1 # RX_IRQ (0x00000001) ## ④ 受信バイト数を RX_STATUS から取得 WRITE [0x04, 0x13] READ 4B # bits[8:0] = RX_NUM_BYTES_RECEIVED ## ⑤ データ受信 — READ_DATA (0x0A) WRITE [0x0A, NN] READ NN bytes # ATQA = 2バイト (e.g. 0x0400 = MIFARE Classic 1K) ## ⑥ IRQ クリア WRITE [0x00, 0x03, FF FF FF FF]
REQA vs WUPA
0x26 (REQA) = HALTed カードには応答しない。 0x52 (WUPA) = HALT 状態のカードも起こす。 どちらも 7ビット送信。
STEP 5 アンチコリジョン → SELECT (ISO 14443A)
## Anticollision Loop — Cascade Level 1 # SEL=0x93, NVB=0x20 (2バイト, フルビット) WRITE [0x00, 0x00, 03 00 00 00] # Transceive WRITE [0x09, 0x00, 93 20] # SEL CL1 + NVB wait RX_IRQ → READ_DATA 5B # UID0~3 + BCC ## SELECT CL1 — UID 確定 WRITE [0x09, 0x00, 93 70 UID0 UID1 UID2 UID3 BCC] wait RX_IRQ → READ_DATA 1B # SAK ## SAK bit6=1 → UID complete (single-size UID) ## SAK bit2=1 → ISO 14443-4 対応 (DESFire, MIFARE Plus etc) ## SAK bit2=0 → MIFARE Classic / Ultralight ## UID 4バイト: CL1 のみ ## UID 7バイト: CL1 (CT+UID0~2) → CL2 (UID3~6) ## UID 10バイト: CL1→CL2→CL3
REF IRQ_STATUS (reg 0x02) — 主要ビット
bit 0 · mask 0x01
RX_IRQ
受信完了 → READ_DATA 可能
bit 1 · mask 0x02
TX_IRQ
送信完了
bit 2 · mask 0x04
IDLE_IRQ
ブート完了 / IDLE状態移行
bit 9 · mask 0x200
TX_RFON_IRQ
RF ON 完了
bit 16 · mask 0x10000
RX_DATA_INTEGRITY_ERR
CRC/Parity エラー
bit 17 · mask 0x20000
GENERAL_ERROR_IRQ
一般エラー
bit 18 · mask 0x40000
RX_COLLISION_DETECTED
衝突検出 → Anticollision 必要
# IRQ 全クリア (IRQ_SET_CLEAR reg 0x03) WRITE [0x00, 0x03, FF FF FF FF] # RX_STATUS (reg 0x13) — 受信バイト数 # bits[8:0] = RX_NUM_BYTES_RECEIVED val = READ_REGISTER(0x13) rx_bytes = val & 0x1FF
REF コマンドコード早見表
コードコマンド送信フォーマットレスポンス
0x00WRITE_REGISTER [0x00, reg, val_LE(4B)]なし
0x01WRITE_REGISTER_OR_MASK [0x01, reg, mask_LE(4B)]なし
0x02WRITE_REGISTER_AND_MASK [0x02, reg, mask_LE(4B)]なし
0x04READ_REGISTER [0x04, reg]4B (LE)
0x06WRITE_EEPROM [0x06, addr, data...]なし
0x07READ_EEPROM [0x07, addr, length]N bytes
0x09SEND_DATA [0x09, valid_bits_last, data...]なし (RX_IRQ待ち)
0x0AREAD_DATA [0x0A, length]N bytes
0x11LOAD_RF_CONFIG [0x11, tx_idx, rx_idx]なし
0x12UPDATE_RF_CONFIG [0x12, proto, reg, val(4B), ...]なし
0x16RF_ON [0x16, config]なし (TX_RFON_IRQ待ち)
0x17RF_OFF [0x17, 0x00]なし
NOTE EEPROM が全0xFF の場合の対処

EEPROMが消去されていても チップは起動できる(0xFF=全ビット1 → IDLE_IRQ_AFTER_BOOT bit0=1 は保たれる)。 ただし RF Config が無効なため、以下の順で手動設定が必要。

## 1. UPDATE_RF_CONFIG でデフォルト値を RAM に書き込む # [0x12, protocol_index, reg_addr, value(4B LE)] # 例: TX ISO14443A 106 — RF_CONTROL_TX_CLK (0x21) WRITE [0x12, 0x00, 0x21, E0 C0 00 00] # val=0x0000C0E0 ## 2. LOAD_RF_CONFIG でレジスタを更新 WRITE [0x11, 0x00, 0x80] # TX=0x00(14443A 106) RX=0x80 ## 3. RF ON → カード検出テスト WRITE [0x16, 0x00] wait TX_RFON_IRQ ... ## 4. 動作確認後 UPDATE_RF_CONFIG で EEPROM に永続化 # NFC Cockpit の "Update EEPROM" ボタンが最も簡単
EEPROM 修復後の重要手順
EEPROM を手動書き込みした場合、 READ_EEPROM 0x160x01 が読めること確認してから動作テストを行うこと。 0xFF のままでは動作するが RF 設定が不正確なため通信距離が極端に短くなる可能性がある。