feat(firmware): add MFRC522 driver implementation and configuration
This commit is contained in:
142
hardware/firmware/lib/mfrc522_driver/mfrc522.c
Normal file
142
hardware/firmware/lib/mfrc522_driver/mfrc522.c
Normal file
@@ -0,0 +1,142 @@
|
||||
#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);
|
||||
}
|
||||
}
|
||||
120
hardware/firmware/lib/mfrc522_driver/mfrc522.h
Normal file
120
hardware/firmware/lib/mfrc522_driver/mfrc522.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#ifndef MFRC522_H
|
||||
#define MFRC522_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <driver/spi_master.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// MFRC522 SPI 命令
|
||||
#define MFRC522_CMD_IDLE 0x00
|
||||
#define MFRC522_CMD_AUTHENT 0x0E
|
||||
#define MFRC522_CMD_RECEIVE 0x08
|
||||
#define MFRC522_CMD_TRANSMIT 0x04
|
||||
#define MFRC522_CMD_TRANSCEIVE 0x0C
|
||||
#define MFRC522_CMD_RESETPHASE 0x0F
|
||||
#define MFRC522_CMD_CALCCRC 0x03
|
||||
|
||||
// MFRC522 寄存器
|
||||
#define MFRC522_REG_COMMAND 0x01
|
||||
#define MFRC522_REG_COMM_IE_N 0x04
|
||||
#define MFRC522_REG_DIV_IE_N 0x05
|
||||
#define MFRC522_REG_COMM_IRQ 0x04
|
||||
#define MFRC522_REG_DIV_IRQ 0x05
|
||||
#define MFRC522_REG_ERROR 0x06
|
||||
#define MFRC522_REG_STATUS1 0x07
|
||||
#define MFRC522_REG_STATUS2 0x08
|
||||
#define MFRC522_REG_FIFO_DATA 0x09
|
||||
#define MFRC522_REG_FIFO_LEVEL 0x0A
|
||||
#define MFRC522_REG_WATER_LEVEL 0x0B
|
||||
#define MFRC522_REG_CONTROL 0x0C
|
||||
#define MFRC522_REG_BITFRAMING 0x0D
|
||||
#define MFRC522_REG_COLL 0x0E
|
||||
#define MFRC522_REG_MODE 0x11
|
||||
#define MFRC522_REG_TX_CONTROL 0x14
|
||||
#define MFRC522_REG_TX_AUTO 0x15
|
||||
#define MFRC522_REG_TX_SELREQ 0x16
|
||||
#define MFRC522_REG_RX_SELREQ 0x17
|
||||
#define MFRC522_REG_RX_THRESHOLD 0x18
|
||||
#define MFRC522_REG_DEMOD 0x19
|
||||
#define MFRC522_REG_MIFARE_TX 0x1C
|
||||
#define MFRC522_REG_MIFARE_RX 0x1D
|
||||
#define MFRC522_REG_SERIAL_SPEED 0x1F
|
||||
#define MFRC522_REG_TIMER_MODE 0x2A
|
||||
#define MFRC522_REG_TIMER_PRESCALER 0x2B
|
||||
#define MFRC522_REG_TIMER_RELOAD_HI 0x2C
|
||||
#define MFRC522_REG_TIMER_RELOAD_LO 0x2D
|
||||
#define MFRC522_REG_TIMER_COUNTER_HI 0x2E
|
||||
#define MFRC522_REG_TIMER_COUNTER_LO 0x2F
|
||||
#define MFRC522_REG_TEST_SEN_SEL 0x38
|
||||
#define MFRC522_REG_TEST_BUS 0x39
|
||||
#define MFRC522_REG_AUTO_TEST 0x3A
|
||||
#define MFRC522_REG_VERSION 0x37
|
||||
|
||||
// MFRC522 Mifare 命令
|
||||
#define MFRC522_MIFARE_CMD_AUTH_KEY_A 0x60
|
||||
#define MFRC522_MIFARE_CMD_AUTH_KEY_B 0x61
|
||||
#define MFRC522_MIFARE_CMD_READ 0x30
|
||||
#define MFRC522_MIFARE_CMD_WRITE 0xA0
|
||||
#define MFRC522_PICC_CMD_SELECT_CL 0x93
|
||||
#define MFRC522_PICC_CMD_HALT_A 0x50
|
||||
|
||||
typedef struct {
|
||||
spi_device_handle_t spi;
|
||||
uint8_t uid[10];
|
||||
uint8_t uid_len;
|
||||
} mfrc522_handle_t;
|
||||
|
||||
/**
|
||||
* 初始化 MFRC522
|
||||
* @param sck_pin SCK 引脚
|
||||
* @param mosi_pin MOSI 引脚
|
||||
* @param miso_pin MISO 引脚
|
||||
* @param cs_pin CS 引脚
|
||||
* @param rst_pin RST 引脚
|
||||
* @return mfrc522_handle_t 指针
|
||||
*/
|
||||
mfrc522_handle_t* mfrc522_init(int sck_pin, int mosi_pin, int miso_pin, int cs_pin, int rst_pin);
|
||||
|
||||
/**
|
||||
* 复位 MFRC522
|
||||
*/
|
||||
void mfrc522_reset(mfrc522_handle_t *handle);
|
||||
|
||||
/**
|
||||
* 写寄存器
|
||||
*/
|
||||
void mfrc522_write_reg(mfrc522_handle_t *handle, uint8_t reg, uint8_t val);
|
||||
|
||||
/**
|
||||
* 读寄存器
|
||||
*/
|
||||
uint8_t mfrc522_read_reg(mfrc522_handle_t *handle, uint8_t reg);
|
||||
|
||||
/**
|
||||
* 检测卡片
|
||||
*/
|
||||
uint8_t mfrc522_picc_is_new(mfrc522_handle_t *handle);
|
||||
|
||||
/**
|
||||
* 读卡 UID
|
||||
*/
|
||||
uint8_t mfrc522_picc_read_serial(mfrc522_handle_t *handle);
|
||||
|
||||
/**
|
||||
* 停止与卡通信
|
||||
*/
|
||||
void mfrc522_picc_halt_a(mfrc522_handle_t *handle);
|
||||
|
||||
/**
|
||||
* 关闭 MFRC522
|
||||
*/
|
||||
void mfrc522_deinit(mfrc522_handle_t *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // MFRC522_H
|
||||
Reference in New Issue
Block a user