Skip to content

Instantly share code, notes, and snippets.

@jef-sure
Created December 30, 2025 22:53
Show Gist options
  • Select an option

  • Save jef-sure/42f96dc34245958bbaa3245891c325cb to your computer and use it in GitHub Desktop.

Select an option

Save jef-sure/42f96dc34245958bbaa3245891c325cb to your computer and use it in GitHub Desktop.
#include "driver/gpio.h"
#include <Arduino.h>
#include <SPI.h>
enum
{
PN5180_RST = GPIO_NUM_12,
PN5180_SCK = GPIO_NUM_18,
PN5180_MOSI = GPIO_NUM_23,
PN5180_MISO = GPIO_NUM_19,
PN5180_NSS = GPIO_NUM_5,
PN5180_CS_DUMMY = GPIO_NUM_22,
PN5180_BUSY = GPIO_NUM_21,
PN5180_FREQ = 7000000,
};
SPIClass PN5180_SPI(VSPI);
SPISettings SPI_SETTINGS(7000000, MSBFIRST, SPI_MODE0);
#define PN5180_MAX_BUF_SIZE 512
#define PN5180_TIMEOUT 500 // ms
static bool pn5180_wait_busy_level(int expected_level, int timeout_ms, const char *timeout_log)
{
uint32_t start = millis();
while (digitalRead(PN5180_BUSY) != expected_level) {
if (millis() - start >= (uint32_t)timeout_ms) {
Serial.printf("PN5180 timeout waiting for BUSY=%d: %s\n", expected_level, timeout_log);
return false;
}
}
return true;
}
void setup()
{
Serial.begin(115200);
delay(1000);
pinMode(PN5180_NSS, OUTPUT);
pinMode(PN5180_BUSY, INPUT);
pinMode(PN5180_RST, OUTPUT);
digitalWrite(PN5180_NSS, HIGH); // disable
digitalWrite(PN5180_RST, HIGH); // no reset
PN5180_SPI.begin(PN5180_SCK, PN5180_MISO, PN5180_MOSI, PN5180_CS_DUMMY);
uint8_t *send_buf = (uint8_t *)heap_caps_calloc(1, PN5180_MAX_BUF_SIZE, MALLOC_CAP_DMA);
uint8_t *recv_buf = (uint8_t *)heap_caps_calloc(1, PN5180_MAX_BUF_SIZE, MALLOC_CAP_DMA);
delay(100);
Serial.println("Resetting PN5180...");
digitalWrite(PN5180_RST, 0); // reset low
delay(50);
digitalWrite(PN5180_RST, 1); // release reset
delay(100); // Wait for PN5180 to boot
Serial.printf("Initial BUSY state: %d\n", digitalRead(PN5180_BUSY));
send_buf[0] = 0x04; // PN5180_READ_REGISTER
send_buf[1] = 0x02; // IRQ_STATUS
if (!pn5180_wait_busy_level(0, PN5180_TIMEOUT, "PN5180 BUSY pin timeout (waiting for idle)")) {
return;
}
Serial.println("Selecting PN5180 (NSS -> LOW)...");
PN5180_SPI.beginTransaction(SPI_SETTINGS);
digitalWrite(PN5180_NSS, 0); // select PN5180
delayMicroseconds(10); // Small stabilization delay
PN5180_SPI.transferBytes(send_buf, recv_buf, 2);
if (!pn5180_wait_busy_level(1, PN5180_TIMEOUT, "PN5180 is not BUSY after transfer")) {
return;
}
digitalWrite(PN5180_NSS, 1); // deselect PN5180
if (!pn5180_wait_busy_level(0, PN5180_TIMEOUT, "PN5180 is BUSY after send")) {
return;
}
Serial.println("Reading response...");
memset(send_buf, 0xff, PN5180_MAX_BUF_SIZE);
digitalWrite(PN5180_NSS, 0); // select PN5180
delayMicroseconds(10);
PN5180_SPI.transferBytes(send_buf, recv_buf, 4);
if (!pn5180_wait_busy_level(1, PN5180_TIMEOUT, "PN5180 no BUSY after recv")) {
digitalWrite(PN5180_NSS, 1);
PN5180_SPI.endTransaction();
return;
}
digitalWrite(PN5180_NSS, 1); // deselect PN5180
PN5180_SPI.endTransaction();
if (!pn5180_wait_busy_level(0, PN5180_TIMEOUT, "PN5180 is BUSY after recv")) {
return;
}
Serial.printf("PN5180 IRQ_STATUS: %02X %02X %02X %02X\n", recv_buf[0], recv_buf[1], recv_buf[2], recv_buf[3]);
free(send_buf);
free(recv_buf);
}
void loop()
{
}
/*
Log:
Initial BUSY state: 0
Selecting PN5180 (NSS -> LOW)...
Reading response...
PN5180 IRQ_STATUS: 04 00 00 00
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment