This commit is contained in:
lmx
2025-12-01 10:01:10 +08:00
parent 627780ea20
commit 6248a4fc34
96 changed files with 9752 additions and 11943 deletions

View File

@ -0,0 +1,833 @@
/********************************************************************************************************
* @file READER.c
* @brief RFID 读卡器底层驱动及协议实现
* @details
* 本文件实现了与FM176XX系列RFID芯片的底层通信协议。它包含以下功能
* - 控制芯片进入不同工作模式如Type A, B, V, F
* - 实现各种卡片类型的寻卡、防冲突、选择和数据交换命令。
* - 管理芯片的FIFO、定时器和RF场。
* 所有硬件相关的操作均通过 `rfid_hal.h` 中定义的接口完成。
********************************************************************************************************/
#include "../include/READER.h"
#include "../include/READER_REG.h"
#include "../include/rfid_main.h"
#include "../rfid_hal.h" // 引入硬件抽象层
#define FUN_ENABLE_XLOG 1
#ifdef xlog
#undef xlog
#endif
#if FUN_ENABLE_XLOG
#define xlog(format, ...) printf("[XT:%s] " format, __func__, ##__VA_ARGS__)
#else
#define xlog(format, ...) ((void)0)
#endif
// 定义全局变量以存储不同类型卡片的信息
struct picc_a_struct PICC_A;
struct picc_b_struct PICC_B;
struct picc_v_struct PICC_V;
struct picc_f_struct PICC_F;
/**
* @brief 等待FM176XX芯片内部中断标志。
* @param wait_irq_flag [in] 要等待的中断标志位 (例如 BIT_IDLE_IRQ, BIT_TIMER_IRQ)。
* @return 操作状态SUCCESS表示成功等到目标标志FAIL表示超时或出错。
* @details
* 该函数会轮询REG_INTREQ寄存器直到指定的标志位被置位
* 或者芯片自身的定时器超时。同时包含一个软件超时以防止死循环。
*/
static unsigned char Wait_IRQ(unsigned char wait_irq_flag)
{
unsigned char irq0_val, irq1_val;
unsigned int timeout = 200; // 软件超时计数,大约 200ms
// 清除所有中断标志位 (通过写1来清除)
SetReg(REG_IRQ0, 0xFF);
SetReg(REG_IRQ1, 0xFF);
do {
GetReg(REG_IRQ0, &irq0_val);
GetReg(REG_IRQ1, &irq1_val);
// 检查是否等到我们需要的标志 (Idle IRQ 在 IRQ0)
if (irq0_val & wait_irq_flag) {
return SUCCESS;
}
// 检查是否是芯片硬件定时器超时 (Timer IRQs 在 IRQ1)
if (irq1_val & BIT_TIMER0IRQ) {
xlog("Wait_IRQ: Hardware Timer Timeout!\n");
return FAIL;
}
rfid_delay_ms(1); // 短暂延时避免CPU空转
timeout--;
} while (timeout > 0);
xlog("Wait_IRQ: Software Timeout!\n");
return FAIL;
}
/********************************************************************************************************
* 公共接口函数
********************************************************************************************************/
/**
* @brief 修改寄存器的特定位。
* @param reg_address [in] 目标寄存器的地址。
* @param mask [in] 要修改的位的掩码。
* @param set [in] 如果为非0则将掩码对应的位设置为1如果为0则清零。
* @return 无。
* @details
* 这是一个“读-改-写”操作。首先读取寄存器的当前值,然后根据掩码和`set`参数修改它,
* 最后将修改后的值写回寄存器。
*/
void ModifyReg(unsigned char reg_address, unsigned char mask, unsigned char set)
{
unsigned char reg_data;
GetReg(reg_address, &reg_data);
if (set)
{
reg_data |= mask;
}
else
{
reg_data &= ~mask;
}
SetReg(reg_address, reg_data);
}
/**
* @brief 向命令寄存器写入一个命令。
* @param command [in] 要执行的命令代码如CMD_IDLE, CMD_TRANSCEIVE等
* @return 操作状态SUCCESS表示成功。
*/
unsigned char SetCommand(unsigned char command)
{
return SetReg(REG_COMMAND, CMD_MASK & command);
}
/**
* @brief 设置芯片内部定时器的超时时间。
* @param timeout [in] 超时时间,单位为毫秒(ms)。
* @return 无。
* @details
* 根据输入的超时时间计算合适的预分频值和重载值并配置T0和T1定时器。
* 这用于在收发数据时进行超时检测。
*/
void SetTimer(unsigned int timeout)
{
unsigned long prescale = 1;
unsigned long t, fc;
fc = timeout * 13560; // 13.56MHz时钟频率
t = fc;
while (fc > 65535)
{
prescale *= 2;
fc = t / prescale;
if (fc * prescale != t)
fc++;
}
if (prescale > 1)
{
SetReg(REG_T0CONTROL, BIT_TSTOP_RX | BIT_TSTART_TX | BIT_TAUTORESTARTED | VALUE_TCLK_1356_MHZ);
SetReg(REG_T0RELOADHI, (unsigned char)(fc >> 8));
SetReg(REG_T0RELOADLO, (unsigned char)fc);
SetReg(REG_T1CONTROL, BIT_TSTOP_RX | BIT_TSTART_TX | VALUE_TCLK_T0);
SetReg(REG_T1RELOADHI, (unsigned char)(prescale >> 8));
SetReg(REG_T1RELOADLO, (unsigned char)prescale);
}
else
{
SetReg(REG_T1CONTROL, BIT_TSTOP_RX | BIT_TSTART_TX | VALUE_TCLK_1356_MHZ);
SetReg(REG_T1RELOADHI, (unsigned char)(fc >> 8));
SetReg(REG_T1RELOADLO, (unsigned char)fc);
}
}
/**
* @brief 打开或关闭RF场载波
* @param mode [in] FUN_ENABLE表示打开FUN_DISABLE表示关闭。
* @return 操作状态SUCCESS表示成功。
*/
unsigned char SetCW(unsigned char mode)
{
if (mode == FUN_ENABLE)
{
ModifyReg(REG_COMMAND, BIT_MODEMOFF, FUN_DISABLE);
ModifyReg(REG_TXMODE, BIT_TPUSHON | BIT_TPULLON, FUN_ENABLE);
}
else
{
ModifyReg(REG_COMMAND, BIT_MODEMOFF, FUN_ENABLE);
ModifyReg(REG_TXMODE, BIT_TPUSHON | BIT_TPULLON, FUN_DISABLE);
}
rfid_delay_ms(5);
return SUCCESS;
}
/**
* @brief 清空芯片内部的FIFO缓冲区。
* @return 无。
*/
void Clear_FIFO(void)
{
unsigned char fifolength;
GetReg(REG_FIFOLENGTH, &fifolength);
if (fifolength != 0)
{
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
}
}
/**
* @brief 加载指定的通信协议参数到芯片。
* @param p_rx [in] 接收协议代码。
* @param p_tx [in] 发送协议代码。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
* @details
* 不同的卡片类型A, B, V, F使用不同的通信速率和编码方式
* 此函数用于将这些协议参数加载到芯片中。
*/
unsigned char LoadProtocol(unsigned char p_rx, unsigned char p_tx)
{
unsigned char reg_data = 0;
SetCommand(CMD_IDLE);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE); // 清空FIFO
SetReg(REG_FIFODATA, p_rx); // 写入接收协议
SetReg(REG_FIFODATA, p_tx); // 写入发送协议
SetCommand(CMD_LOADPROTOCOL);
rfid_delay_ms(2);
GetReg(REG_COMMAND, &reg_data);
if (reg_data != CMD_IDLE)
return FAIL;
return SUCCESS;
}
/**
* @brief 设置发送和接收的奇偶校验位使能状态。
* @param state [in] FUN_ENABLE或FUN_DISABLE。
* @return 无。
*/
void SetParity(unsigned char state)
{
ModifyReg(REG_FRAMECON, BIT_TXPARITYEN | BIT_RXPARITYEN, state);
}
/**
* @brief 初始化读卡器以支持Type A卡片。
* @return 操作状态SUCCESS表示成功。
*/
unsigned char ReaderA_Initial(void)
{
LoadProtocol(RX_TYPEA_106, TX_TYPEA_106);
ModifyReg(REG_TXMODE, BIT_RFON, FUN_ENABLE); // FORCE 100ask FUN_ENABLE
SetReg(REG_TXAMP, AMPLITUDE_A);
SetReg(REG_TXCON, 0x00);
SetReg(REG_RXANA, (HPCF_A << 3) | GAIN_A);
SetReg(0x5F, 0x08);
SetReg(REG_THNSET, 0xFF);
SetReg(REG_THNMIN, 0xC0);
SetReg(REG_RXTXCON, 0x80);
SetParity(FUN_ENABLE);
SetReg(REG_STATUS, 0); // 清除Crypto1On位
return SUCCESS;
}
/**
* @brief 初始化读卡器以支持Type B卡片。
* @return 操作状态SUCCESS表示成功。
*/
unsigned char ReaderB_Initial(void)
{
LoadProtocol(RX_TYPEB_106, TX_TYPEB_106);
ModifyReg(REG_TXMODE, BIT_RFON, FUN_DISABLE); // FORCE 100ask FUN_DISABLE
SetReg(REG_TXAMP, AMPLITUDE_B);
SetReg(REG_TXCON, MODULATION_B);
SetReg(REG_RXANA, (HPCF_B << 3) | GAIN_B);
SetReg(0x5F, 0x08);
SetReg(REG_THNSET, 0xFF);
SetReg(REG_THNMIN, 0xC0);
SetReg(REG_RXTXCON, 0x80);
return SUCCESS;
}
/**
* @brief 初始化读卡器以支持Type V (ISO15693) 卡片。
* @return 操作状态SUCCESS表示成功。
*/
unsigned char ReaderV_Initial(void)
{
LoadProtocol(RX_TYPEV_26, RX_TYPEV_26);
ModifyReg(REG_RXANA, MASK_RCV_GAIN | MASK_RCV_HPCF, FUN_DISABLE);
ModifyReg(REG_RXANA, (HPCF_V << 3) | GAIN_V, FUN_ENABLE);
SetParity(FUN_DISABLE);
SetReg(REG_TXAMP, AMPLITUDE_V);
SetReg(REG_TXCON, MODULATION_V);
SetReg(REG_TXI, 0x06);
SetReg(REG_THNSET, 0xFF);
SetReg(REG_THNMIN, 0x80);
SetReg(REG_THNADJ, 0x08);
SetReg(REG_RXTXCON, 0);
return SUCCESS;
}
/**
* @brief 初始化读卡器以支持Type F (FeliCa) 卡片。
* @return 操作状态SUCCESS表示成功。
*/
unsigned char ReaderF_Initial(void)
{
ModifyReg(REG_MISC, 0x04, FUN_ENABLE);
LoadProtocol(RX_FELICA_212, TX_FELICA_212);
SetReg(REG_TXAMP, AMPLITUDE_F);
SetReg(REG_TXCON, MODULATION_F);
ModifyReg(REG_RXANA, MASK_RCV_GAIN | MASK_RCV_HPCF, FUN_DISABLE);
ModifyReg(REG_RXANA, (HPCF_F << 3) | GAIN_F, FUN_ENABLE);
SetParity(FUN_DISABLE);
SetReg(REG_THNSET, 0xFF);
SetReg(REG_THNMIN, 0x80);
SetReg(REG_THNADJ, 0x08);
ModifyReg(REG_MISC, 0x04, FUN_DISABLE);
return SUCCESS;
}
/**
* @brief 向Type A卡片发送WUPAWake-Up A命令。
* @param picc_a [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderA_Wakeeup(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x0F);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, RF_CMD_WUPA);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_DISABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_DISABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(2);
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 2)
return FAIL;
GetReg(REG_FIFODATA, &picc_a->ATQA[0]);
GetReg(REG_FIFODATA, &picc_a->ATQA[1]);
return SUCCESS;
}
/**
* @brief 向Type A卡片发送REQARequest A命令。
* @param picc_a [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderA_Request(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x0F);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, RF_CMD_REQA);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_DISABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_DISABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(2);
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 2)
return FAIL;
GetReg(REG_FIFODATA, &picc_a->ATQA[0]);
GetReg(REG_FIFODATA, &picc_a->ATQA[1]);
return SUCCESS;
}
/**
* @brief 执行Type A卡片的防冲突流程。
* @param picc_a [in, out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderA_Anticoll(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, RF_CMD_ANTICOLL[picc_a->CASCADE_LEVEL]);
SetReg(REG_FIFODATA, 0x20);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_DISABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_DISABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(2);
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 5)
return FAIL;
GetReg(REG_FIFODATA, &picc_a->UID[picc_a->CASCADE_LEVEL * 4]);
GetReg(REG_FIFODATA, &picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 1]);
GetReg(REG_FIFODATA, &picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 2]);
GetReg(REG_FIFODATA, &picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 3]);
GetReg(REG_FIFODATA, &picc_a->BCC[picc_a->CASCADE_LEVEL]);
if ((picc_a->UID[picc_a->CASCADE_LEVEL * 4] ^ picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 1] ^ picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 2] ^ picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 3]) == picc_a->BCC[picc_a->CASCADE_LEVEL])
return SUCCESS;
return FAIL;
}
/**
* @brief 选择一个已经过防冲突的Type A卡片。
* @param picc_a [in, out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderA_Select(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, RF_CMD_ANTICOLL[picc_a->CASCADE_LEVEL]);
SetReg(REG_FIFODATA, 0x70);
SetReg(REG_FIFODATA, picc_a->UID[picc_a->CASCADE_LEVEL * 4]);
SetReg(REG_FIFODATA, picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 1]);
SetReg(REG_FIFODATA, picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 2]);
SetReg(REG_FIFODATA, picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 3]);
SetReg(REG_FIFODATA, picc_a->BCC[picc_a->CASCADE_LEVEL]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(2);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA, &picc_a->SAK[picc_a->CASCADE_LEVEL]);
return SUCCESS;
}
/**
* @brief 激活Type A卡片完成REQA, Anticoll, Select全过程
* @param picc_a [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderA_CardActivate(struct picc_a_struct *picc_a)
{
unsigned char result, cascade_level;
result = ReaderA_Request(picc_a);
if (result != SUCCESS)
return result;
if ((picc_a->ATQA[0] & 0xC0) == 0x00) // 单倍UID
{
cascade_level = 1;
picc_a->UID_Length = 4;
}
else if ((picc_a->ATQA[0] & 0xC0) == 0x40) // 双倍UID
{
cascade_level = 2;
picc_a->UID_Length = 7; // 实际是7字节
}
else if ((picc_a->ATQA[0] & 0xC0) == 0x80) // 三倍UID
{
cascade_level = 3;
picc_a->UID_Length = 10; // 实际是10字节
}
else
{
return FAIL; // 未知UID长度
}
for (picc_a->CASCADE_LEVEL = 0; picc_a->CASCADE_LEVEL < cascade_level; picc_a->CASCADE_LEVEL++)
{
result = ReaderA_Anticoll(picc_a);
if (result != SUCCESS)
return result;
result = ReaderA_Select(picc_a);
if (result != SUCCESS)
return result;
}
picc_a->CASCADE_LEVEL--;
return result;
}
/**
* @brief 向Type B卡片发送WUPBWake-Up B命令。
* @param picc_b [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderB_Wakeup(struct picc_b_struct *picc_b)
{
unsigned char reg_data, i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x05); // APf
SetReg(REG_FIFODATA, 0x00); // AFI (00:for all cards)
SetReg(REG_FIFODATA, 0x08); // PARAM(WUPB, Number of slots = 0)
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 12)
return FAIL;
for (i = 0; i < 12; i++)
GetReg(REG_FIFODATA, &picc_b->ATQB[i]);
memcpy(picc_b->PUPI, picc_b->ATQB + 1, 4);
memcpy(picc_b->APPLICATION_DATA, picc_b->ATQB + 6, 4);
memcpy(picc_b->PROTOCOL_INF, picc_b->ATQB + 10, 3);
return SUCCESS;
}
/**
* @brief 向Type B卡片发送REQBRequest B命令。
* @param picc_b [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderB_Request(struct picc_b_struct *picc_b)
{
unsigned char reg_data, i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x05); // APf
SetReg(REG_FIFODATA, 0x00); // AFI (00:for all cards)
SetReg(REG_FIFODATA, 0x00); // PARAM(REQB, Number of slots = 0)
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 12)
return FAIL;
for (i = 0; i < 12; i++)
GetReg(REG_FIFODATA, &picc_b->ATQB[i]);
memcpy(picc_b->PUPI, picc_b->ATQB + 1, 4);
memcpy(picc_b->APPLICATION_DATA, picc_b->ATQB + 6, 4);
memcpy(picc_b->PROTOCOL_INF, picc_b->ATQB + 10, 3);
return SUCCESS;
}
/**
* @brief 向Type B卡片发送ATTRIB命令以选择卡片并设置通信参数。
* @param picc_b [in, out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderB_Attrib(struct picc_b_struct *picc_b)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x1D);
SetReg(REG_FIFODATA, picc_b->PUPI[0]);
SetReg(REG_FIFODATA, picc_b->PUPI[1]);
SetReg(REG_FIFODATA, picc_b->PUPI[2]);
SetReg(REG_FIFODATA, picc_b->PUPI[3]);
SetReg(REG_FIFODATA, 0x00); // Param1
SetReg(REG_FIFODATA, 0x08); // Param2
SetReg(REG_FIFODATA, 0x01); // COMPATIBLE WITH 14443-4
SetReg(REG_FIFODATA, 0x01); // CID:01
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA, &reg_data);
picc_b->CID = reg_data & 0x0F;
return SUCCESS;
}
/**
* @brief 向Type B卡片发送HALT命令使其进入休眠状态。
* @param picc_b [in, out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderB_Halt(struct picc_b_struct *picc_b)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x50);
SetReg(REG_FIFODATA, picc_b->PUPI[0]);
SetReg(REG_FIFODATA, picc_b->PUPI[1]);
SetReg(REG_FIFODATA, picc_b->PUPI[2]);
SetReg(REG_FIFODATA, picc_b->PUPI[3]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA, &reg_data);
*picc_b->Answer_to_HALT = reg_data & 0x0F;
return SUCCESS;
}
/**
* @brief 获取Type B卡片的序列号这是一个自定义命令非标准
* @param picc_b [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderB_Get_SN(struct picc_b_struct *picc_b)
{
unsigned char reg_data, i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x00);
SetReg(REG_FIFODATA, 0x36);
SetReg(REG_FIFODATA, 0x00);
SetReg(REG_FIFODATA, 0x00);
SetReg(REG_FIFODATA, 0x08);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 10)
return FAIL;
for (i = 0; i < 8; i++)
GetReg(REG_FIFODATA, &picc_b->SN[i]);
return SUCCESS;
}
/**
* @brief 向Type V (ISO15693) 卡片发送Inventory命令。
* @param picc_v [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderV_Inventory(struct picc_v_struct *picc_v)
{
unsigned char reg_data, i, result; // 新增 result 变量
SetCommand(CMD_IDLE);
// 设置15ms的硬件超时
SetTimer(15);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x26); // Corrected Inventory flag to indicate AFI is present
SetReg(REG_FIFODATA, 0x01);
SetReg(REG_FIFODATA, 0x00);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
// 使用新的等待函数,等待命令完成或硬件超时
result = Wait_IRQ(BIT_IDLE_IRQ);
SetTimer(0); // 关闭定时器
if (result != SUCCESS) {
xlog("Wait_IRQ failed after TRANSCEIVE.\n");
SetCommand(CMD_IDLE); // 尝试让芯片恢复IDLE状态
return FAIL;
}
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0){
xlog("REG_ERROR = 0x%02X\n", reg_data);
return FAIL;
}
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 10){
xlog("FIFO Length is %d, expected 10.\n", reg_data);
return FAIL;
}
GetReg(REG_FIFODATA, &picc_v->RESPONSE);
GetReg(REG_FIFODATA, &reg_data); // DSFID
for (i = 0; i < 8; i++)
{
GetReg(REG_FIFODATA, &picc_v->UID[i]);
}
return SUCCESS;
}
/**
* @brief 选择一个已获取UID的Type V卡片。
* @param picc_v [in, out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderV_Select(struct picc_v_struct *picc_v)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x22); // Addressed flag
SetReg(REG_FIFODATA, 0x25); // Select command
SetReg(REG_FIFODATA, picc_v->UID[0]);
SetReg(REG_FIFODATA, picc_v->UID[1]);
SetReg(REG_FIFODATA, picc_v->UID[2]);
SetReg(REG_FIFODATA, picc_v->UID[3]);
SetReg(REG_FIFODATA, picc_v->UID[4]);
SetReg(REG_FIFODATA, picc_v->UID[5]);
SetReg(REG_FIFODATA, picc_v->UID[6]);
SetReg(REG_FIFODATA, picc_v->UID[7]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA, &picc_v->RESPONSE);
return SUCCESS;
}
/**
* @brief 读取Type V卡片的单个数据块。
* @param block_num [in] 要读取的块号。
* @param picc_v [out] 指向存储卡片信息的结构体,读取的数据将存入 `BLOCK_DATA`。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderV_ReadSingleBlock(unsigned char block_num, struct picc_v_struct *picc_v)
{
unsigned char reg_data, i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x02); // Addressed flag
SetReg(REG_FIFODATA, 0x20); // Read Single Block command
SetReg(REG_FIFODATA, block_num);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 5) // 1 byte response flag + 4 bytes data
return FAIL;
GetReg(REG_FIFODATA, &picc_v->RESPONSE);
for (i = 0; i < 4; i++)
{
GetReg(REG_FIFODATA, &picc_v->BLOCK_DATA[i]);
}
return SUCCESS;
}
/**
* @brief 向Type V卡片的单个数据块写入数据。
* @param block_num [in] 要写入的块号。
* @param picc_v [in] 指向存储卡片信息的结构体,要写入的数据在 `BLOCK_DATA` 中。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderV_WriteSingleBlock(unsigned char block_num, struct picc_v_struct *picc_v)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x02); // Addressed flag
SetReg(REG_FIFODATA, 0x21); // Write Single Block command
SetReg(REG_FIFODATA, block_num);
SetReg(REG_FIFODATA, picc_v->BLOCK_DATA[0]);
SetReg(REG_FIFODATA, picc_v->BLOCK_DATA[1]);
SetReg(REG_FIFODATA, picc_v->BLOCK_DATA[2]);
SetReg(REG_FIFODATA, picc_v->BLOCK_DATA[3]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA, &picc_v->RESPONSE);
return SUCCESS;
}
/**
* @brief 向Type F (FeliCa) 卡片发送Inventory命令。
* @param picc_f [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderF_Inventory(struct picc_f_struct *picc_f)
{
unsigned char reg_data, i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x06);
SetReg(REG_FIFODATA, 0x00);
SetReg(REG_FIFODATA, 0xFF);
SetReg(REG_FIFODATA, 0xFF);
SetReg(REG_FIFODATA, 0x10);
SetReg(REG_FIFODATA, 0x00);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 18)
return FAIL;
GetReg(REG_FIFODATA, &reg_data); // Length
GetReg(REG_FIFODATA, &reg_data); // Response code
for (i = 0; i < 8; i++)
{
GetReg(REG_FIFODATA, &picc_f->UID[i]);
}
return SUCCESS;
}