Last active
December 30, 2025 22:52
-
-
Save jef-sure/f118547f273e2acfa9b4600f053ecca7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "driver/gpio.h" | |
| #include "driver/spi_master.h" | |
| #include "esp_chip_info.h" | |
| #include "esp_flash.h" | |
| #include "esp_heap_caps.h" | |
| #include "esp_log.h" | |
| #include "esp_rom_sys.h" | |
| #include "esp_system.h" | |
| #include "esp_timer.h" | |
| #include "freertos/FreeRTOS.h" | |
| #include "freertos/task.h" | |
| #include "sdkconfig.h" | |
| #include <inttypes.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| /* | |
| #include "hal/gpio_hal.h" | |
| bool get_out_gp_level_hal(gpio_num_t gpio_num) | |
| { | |
| gpio_dev_t *hw = GPIO_HAL_GET_HW(GPIO_PORT_0); | |
| if (gpio_num < 32) { | |
| return (hw->out >> gpio_num) & 0x1; | |
| } else { | |
| return (hw->out1.data >> (gpio_num - 32)) & 0x1; | |
| } | |
| } | |
| */ | |
| 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, | |
| }; | |
| const char *TAG = "PN5180"; | |
| #define PN5180_SPI_HOST SPI3_HOST | |
| #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) | |
| { | |
| int64_t deadline_us = esp_timer_get_time() + ((int64_t)timeout_ms * 1000); | |
| while (gpio_get_level(PN5180_BUSY) != expected_level) { | |
| if (esp_timer_get_time() >= deadline_us) { | |
| ESP_LOGE(TAG, "%s (BUSY=%d)", timeout_log, gpio_get_level(PN5180_BUSY)); | |
| return false; | |
| } | |
| esp_rom_delay_us(1); | |
| } | |
| return true; | |
| } | |
| void pn5180_delay_ms(int ms) | |
| { | |
| int64_t start = esp_timer_get_time(); | |
| while ((esp_timer_get_time() - start) < (ms * 1000)) { | |
| esp_rom_delay_us(100); | |
| } | |
| } | |
| void app_main(void) | |
| { | |
| spi_bus_config_t bus_config = { | |
| .mosi_io_num = PN5180_MOSI, | |
| .miso_io_num = PN5180_MISO, | |
| .sclk_io_num = PN5180_SCK, | |
| .quadwp_io_num = -1, | |
| .quadhd_io_num = -1, | |
| .max_transfer_sz = 0, | |
| }; | |
| spi_device_interface_config_t dev_config = { | |
| .clock_speed_hz = PN5180_FREQ, | |
| .mode = 0, | |
| .spics_io_num = PN5180_CS_DUMMY, | |
| .queue_size = 2, | |
| .flags = 0 // SPI_DEVICE_HALFDUPLEX, | |
| }; | |
| if (spi_bus_initialize(PN5180_SPI_HOST, &bus_config, SPI_DMA_DISABLED) != ESP_OK) { | |
| ESP_LOGE(TAG, "Failed to initialize SPI bus"); | |
| return; | |
| } | |
| spi_device_handle_t spi_handle; | |
| if (spi_bus_add_device(PN5180_SPI_HOST, &dev_config, &spi_handle) != ESP_OK) { | |
| ESP_LOGE(TAG, "Failed to add SPI device"); | |
| return; | |
| } | |
| 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); | |
| gpio_set_direction(PN5180_NSS, GPIO_MODE_OUTPUT); | |
| gpio_set_direction(PN5180_RST, GPIO_MODE_OUTPUT); | |
| gpio_set_direction(PN5180_BUSY, GPIO_MODE_INPUT); | |
| // gpio_config_t busy_cfg = { | |
| // .pin_bit_mask = (1ULL << PN5180_BUSY), // | |
| // .mode = GPIO_MODE_INPUT, // | |
| // .pull_up_en = GPIO_PULLUP_ENABLE, // | |
| // .pull_down_en = GPIO_PULLDOWN_DISABLE, // | |
| // .intr_type = GPIO_INTR_DISABLE // | |
| // }; | |
| // gpio_config(&busy_cfg); | |
| // gpio_dump_io_configuration(stdout, (1ULL << PN5180_RST) | (1ULL << PN5180_NSS) | (1ULL << PN5180_BUSY) | | |
| // (1ULL << PN5180_MOSI) | (1ULL << PN5180_MISO) | (1ULL << PN5180_SCK)); | |
| gpio_set_level(PN5180_NSS, 1); | |
| gpio_set_level(PN5180_RST, 1); // | |
| pn5180_delay_ms(100); | |
| gpio_set_level(PN5180_RST, 0); // reset low | |
| pn5180_delay_ms(50); | |
| gpio_set_level(PN5180_RST, 1); // release reset | |
| pn5180_delay_ms(100); | |
| printf("Initial BUSY state: %d\n", gpio_get_level(PN5180_BUSY)); | |
| spi_transaction_t trans; | |
| memset(&trans, 0, sizeof(trans)); | |
| send_buf[0] = 0x04; // PN5180_READ_REGISTER | |
| send_buf[1] = 0x02; // IRQ_STATUS | |
| trans.tx_buffer = send_buf; | |
| trans.rx_buffer = recv_buf; | |
| trans.length = 2 * 8; // 2 bytes | |
| if (!pn5180_wait_busy_level(0, PN5180_TIMEOUT, "PN5180 BUSY pin timeout")) { | |
| return; | |
| } | |
| gpio_set_level(PN5180_NSS, 0); // assert nss | |
| esp_rom_delay_us(10); | |
| if (spi_device_polling_transmit(spi_handle, &trans) != ESP_OK) { | |
| ESP_LOGE(TAG, "Failed to transmit SPI transaction"); | |
| return; | |
| } | |
| if (!pn5180_wait_busy_level(1, PN5180_TIMEOUT, "PN5180 is not BUSY after transfer")) { | |
| return; | |
| } | |
| gpio_set_level(PN5180_NSS, 1); | |
| if (!pn5180_wait_busy_level(0, PN5180_TIMEOUT, "PN5180 is BUSY after send")) { | |
| return; | |
| } | |
| printf("Reading response...\n"); | |
| memset(&trans, 0, sizeof(trans)); | |
| memset(send_buf, 0xff, PN5180_MAX_BUF_SIZE); | |
| trans.tx_buffer = send_buf; | |
| trans.rx_buffer = recv_buf; | |
| trans.length = 4 * 8; // 4 bytes | |
| gpio_set_level(PN5180_NSS, 0); // | |
| esp_rom_delay_us(10); | |
| if (spi_device_polling_transmit(spi_handle, &trans) != ESP_OK) { | |
| ESP_LOGE(TAG, "Failed to transmit SPI transaction"); | |
| return; | |
| } | |
| if (!pn5180_wait_busy_level(1, PN5180_TIMEOUT, "PN5180 no BUSY after recv")) { | |
| gpio_set_level(PN5180_NSS, 1); | |
| return; | |
| } | |
| gpio_set_level(PN5180_NSS, 1); | |
| if (!pn5180_wait_busy_level(0, PN5180_TIMEOUT, "PN5180 is BUSY after recv")) { | |
| return; | |
| } | |
| ESP_LOGI(TAG, "Received data: %02x %02x %02x %02x", recv_buf[0], recv_buf[1], recv_buf[2], recv_buf[3]); | |
| free(send_buf); | |
| free(recv_buf); | |
| } | |
| /* | |
| Log: | |
| Initial BUSY state: 0 | |
| E (1094) PN5180: PN5180 is not BUSY after transfer (BUSY=0) | |
| */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment