143 lines
3.7 KiB
C
143 lines
3.7 KiB
C
#include "mfrc522.h"
|
|
#include "driver/gpio.h"
|
|
#include "esp_log.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static const char *TAG = "MFRC522";
|
|
|
|
#define SPI_MASTER_FREQ_HZ 1000000 // 1MHz
|
|
|
|
mfrc522_handle_t* mfrc522_init(int sck_pin, int mosi_pin, int miso_pin, int cs_pin, int rst_pin)
|
|
{
|
|
mfrc522_handle_t *handle = (mfrc522_handle_t *)malloc(sizeof(mfrc522_handle_t));
|
|
if (!handle) {
|
|
ESP_LOGE(TAG, "Failed to allocate memory");
|
|
return NULL;
|
|
}
|
|
|
|
// 配置 RST 引脚
|
|
gpio_config_t io_conf = {
|
|
.pin_bit_mask = (1ULL << rst_pin),
|
|
.mode = GPIO_MODE_OUTPUT,
|
|
.pull_up_en = GPIO_PULLUP_DISABLE,
|
|
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
|
.intr_type = GPIO_INTR_DISABLE
|
|
};
|
|
gpio_config(&io_conf);
|
|
gpio_set_level(rst_pin, 1);
|
|
|
|
// 配置 SPI
|
|
spi_bus_config_t buscfg = {
|
|
.miso_io_num = miso_pin,
|
|
.mosi_io_num = mosi_pin,
|
|
.sclk_io_num = sck_pin,
|
|
.quadwp_io_num = -1,
|
|
.quadhd_io_num = -1,
|
|
.max_transfer_sz = 4096,
|
|
};
|
|
|
|
spi_device_interface_config_t devcfg = {
|
|
.mode = 0,
|
|
.clock_speed_hz = SPI_MASTER_FREQ_HZ,
|
|
.spics_io_num = cs_pin,
|
|
.queue_size = 7,
|
|
};
|
|
|
|
esp_err_t ret = spi_bus_initialize(HSPI_HOST, &buscfg, SPI_DMA_CH_AUTO);
|
|
if (ret != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to initialize SPI bus");
|
|
free(handle);
|
|
return NULL;
|
|
}
|
|
|
|
ret = spi_bus_add_device(HSPI_HOST, &devcfg, &handle->spi);
|
|
if (ret != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to add SPI device");
|
|
free(handle);
|
|
return NULL;
|
|
}
|
|
|
|
handle->uid_len = 0;
|
|
memset(handle->uid, 0, sizeof(handle->uid));
|
|
|
|
// 复位 MFRC522
|
|
mfrc522_reset(handle);
|
|
|
|
ESP_LOGI(TAG, "MFRC522 initialized successfully");
|
|
return handle;
|
|
}
|
|
|
|
void mfrc522_reset(mfrc522_handle_t *handle)
|
|
{
|
|
mfrc522_write_reg(handle, MFRC522_REG_COMMAND, MFRC522_CMD_RESETPHASE);
|
|
vTaskDelay(pdMS_TO_TICKS(50));
|
|
|
|
// 初始化寄存器
|
|
mfrc522_write_reg(handle, MFRC522_REG_MODE, 0x3D); // CRC初始值
|
|
mfrc522_write_reg(handle, MFRC522_REG_TX_CONTROL, 0x83); // 打开TX1和TX2输出
|
|
mfrc522_write_reg(handle, MFRC522_REG_TX_AUTO, 0x40); // 自动 RF 开启
|
|
|
|
mfrc522_write_reg(handle, MFRC522_REG_COMMAND, MFRC522_CMD_IDLE);
|
|
}
|
|
|
|
void mfrc522_write_reg(mfrc522_handle_t *handle, uint8_t reg, uint8_t val)
|
|
{
|
|
uint8_t tx_data[2];
|
|
tx_data[0] = ((reg << 1) & 0x7E) | 0x00; // 写操作
|
|
tx_data[1] = val;
|
|
|
|
spi_transaction_t t = {
|
|
.length = 16,
|
|
.tx_buffer = tx_data,
|
|
};
|
|
spi_device_transmit(handle->spi, &t);
|
|
}
|
|
|
|
uint8_t mfrc522_read_reg(mfrc522_handle_t *handle, uint8_t reg)
|
|
{
|
|
uint8_t tx_data[2] = {0};
|
|
uint8_t rx_data[2] = {0};
|
|
|
|
tx_data[0] = ((reg << 1) & 0x7E) | 0x80; // 读操作
|
|
|
|
spi_transaction_t t = {
|
|
.length = 16,
|
|
.tx_buffer = tx_data,
|
|
.rx_buffer = rx_data,
|
|
};
|
|
spi_device_transmit(handle->spi, &t);
|
|
|
|
return rx_data[1];
|
|
}
|
|
|
|
uint8_t mfrc522_picc_is_new(mfrc522_handle_t *handle)
|
|
{
|
|
uint8_t status = mfrc522_read_reg(handle, MFRC522_REG_STATUS1);
|
|
return (status & 0x01); // 检查标签检测位
|
|
}
|
|
|
|
uint8_t mfrc522_picc_read_serial(mfrc522_handle_t *handle)
|
|
{
|
|
// 这是一个简化版本,实际实现需要完整的 Mifare 协议
|
|
// 这里仅作示例
|
|
handle->uid_len = 4;
|
|
return handle->uid_len;
|
|
}
|
|
|
|
void mfrc522_picc_halt_a(mfrc522_handle_t *handle)
|
|
{
|
|
mfrc522_write_reg(handle, MFRC522_REG_COMMAND, MFRC522_CMD_IDLE);
|
|
}
|
|
|
|
void mfrc522_deinit(mfrc522_handle_t *handle)
|
|
{
|
|
if (handle) {
|
|
spi_bus_remove_device(handle->spi);
|
|
spi_bus_free(HSPI_HOST);
|
|
free(handle);
|
|
}
|
|
}
|