2025-11-24 16:33:33 +08:00
|
|
|
|
/********************************************************************************************************
|
|
|
|
|
|
* @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" // 引入硬件抽象层
|
|
|
|
|
|
|
2025-11-24 18:58:32 +08:00
|
|
|
|
#define FUN_ENABLE_XLOG 1
|
2025-11-24 16:33:33 +08:00
|
|
|
|
#ifdef xlog
|
|
|
|
|
|
#undef xlog
|
|
|
|
|
|
#endif
|
2025-11-24 18:58:32 +08:00
|
|
|
|
#if FUN_ENABLE_XLOG
|
2025-11-24 16:33:33 +08:00
|
|
|
|
#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 修改寄存器的特定位。
|
|
|
|
|
|
* @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, ®_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场(载波)。
|
2025-11-24 18:58:32 +08:00
|
|
|
|
* @param mode [in] FUN_ENABLE表示打开,FUN_DISABLE表示关闭。
|
2025-11-24 16:33:33 +08:00
|
|
|
|
* @return 操作状态,SUCCESS表示成功。
|
|
|
|
|
|
*/
|
|
|
|
|
|
unsigned char SetCW(unsigned char mode)
|
|
|
|
|
|
{
|
2025-11-24 18:58:32 +08:00
|
|
|
|
if (mode == FUN_ENABLE)
|
2025-11-24 16:33:33 +08:00
|
|
|
|
{
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_COMMAND, BIT_MODEMOFF, FUN_DISABLE);
|
|
|
|
|
|
ModifyReg(REG_TXMODE, BIT_TPUSHON | BIT_TPULLON, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_COMMAND, BIT_MODEMOFF, FUN_ENABLE);
|
|
|
|
|
|
ModifyReg(REG_TXMODE, BIT_TPUSHON | BIT_TPULLON, FUN_DISABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
rfid_delay_ms(5);
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 清空芯片内部的FIFO缓冲区。
|
|
|
|
|
|
* @return 无。
|
|
|
|
|
|
*/
|
|
|
|
|
|
void Clear_FIFO(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
unsigned char fifolength;
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, &fifolength);
|
|
|
|
|
|
if (fifolength != 0)
|
|
|
|
|
|
{
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE); // 清空FIFO
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetReg(REG_FIFODATA, p_rx); // 写入接收协议
|
|
|
|
|
|
SetReg(REG_FIFODATA, p_tx); // 写入发送协议
|
|
|
|
|
|
|
|
|
|
|
|
SetCommand(CMD_LOADPROTOCOL);
|
|
|
|
|
|
rfid_delay_ms(2);
|
|
|
|
|
|
GetReg(REG_COMMAND, ®_data);
|
|
|
|
|
|
if (reg_data != CMD_IDLE)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 设置发送和接收的奇偶校验位使能状态。
|
2025-11-24 18:58:32 +08:00
|
|
|
|
* @param state [in] FUN_ENABLE或FUN_DISABLE。
|
2025-11-24 16:33:33 +08:00
|
|
|
|
* @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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXMODE, BIT_RFON, FUN_ENABLE); // FORCE 100ask FUN_ENABLE
|
2025-11-24 16:33:33 +08:00
|
|
|
|
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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
SetParity(FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetReg(REG_STATUS, 0); // 清除Crypto1On位
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 初始化读卡器以支持Type B卡片。
|
|
|
|
|
|
* @return 操作状态,SUCCESS表示成功。
|
|
|
|
|
|
*/
|
|
|
|
|
|
unsigned char ReaderB_Initial(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
LoadProtocol(RX_TYPEB_106, TX_TYPEB_106);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXMODE, BIT_RFON, FUN_DISABLE); // FORCE 100ask FUN_DISABLE
|
2025-11-24 16:33:33 +08:00
|
|
|
|
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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_RXANA, MASK_RCV_GAIN | MASK_RCV_HPCF, FUN_DISABLE);
|
|
|
|
|
|
ModifyReg(REG_RXANA, (HPCF_V << 3) | GAIN_V, FUN_ENABLE);
|
|
|
|
|
|
SetParity(FUN_DISABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
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)
|
|
|
|
|
|
{
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_MISC, 0x04, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
LoadProtocol(RX_FELICA_212, TX_FELICA_212);
|
|
|
|
|
|
SetReg(REG_TXAMP, AMPLITUDE_F);
|
|
|
|
|
|
SetReg(REG_TXCON, MODULATION_F);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_RXANA, MASK_RCV_GAIN | MASK_RCV_HPCF, FUN_DISABLE);
|
|
|
|
|
|
ModifyReg(REG_RXANA, (HPCF_F << 3) | GAIN_F, FUN_ENABLE);
|
|
|
|
|
|
SetParity(FUN_DISABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetReg(REG_THNSET, 0xFF);
|
|
|
|
|
|
SetReg(REG_THNMIN, 0x80);
|
|
|
|
|
|
SetReg(REG_THNADJ, 0x08);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_MISC, 0x04, FUN_DISABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
return SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 向Type A卡片发送WUPA(Wake-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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetReg(REG_FIFODATA, RF_CMD_WUPA);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_DISABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_DISABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(2);
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_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卡片发送REQA(Request 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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetReg(REG_FIFODATA, RF_CMD_REQA);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_DISABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_DISABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(2);
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetReg(REG_FIFODATA, RF_CMD_ANTICOLL[picc_a->CASCADE_LEVEL]);
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x20);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_DISABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_DISABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(2);
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
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]);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(2);
|
|
|
|
|
|
GetReg(REG_ERROR, ®_data);
|
|
|
|
|
|
if ((reg_data & 0x0F) != 0)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_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卡片发送WUPB(Wake-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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetReg(REG_FIFODATA, 0x05); // APf
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x00); // AFI (00:for all cards)
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x08); // PARAM(WUPB, Number of slots = 0)
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(10);
|
|
|
|
|
|
GetReg(REG_ERROR, ®_data);
|
|
|
|
|
|
if ((reg_data & 0x0F) != 0)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_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卡片发送REQB(Request 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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetReg(REG_FIFODATA, 0x05); // APf
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x00); // AFI (00:for all cards)
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x00); // PARAM(REQB, Number of slots = 0)
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(10);
|
|
|
|
|
|
GetReg(REG_ERROR, ®_data);
|
|
|
|
|
|
if ((reg_data & 0x0F) != 0)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
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
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(10);
|
|
|
|
|
|
GetReg(REG_ERROR, ®_data);
|
|
|
|
|
|
if ((reg_data & 0x0F) != 0)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_data);
|
|
|
|
|
|
if (reg_data != 1)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFODATA, ®_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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
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]);
|
|
|
|
|
|
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(10);
|
|
|
|
|
|
GetReg(REG_ERROR, ®_data);
|
|
|
|
|
|
if ((reg_data & 0x0F) != 0)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_data);
|
|
|
|
|
|
if (reg_data != 1)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFODATA, ®_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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetReg(REG_FIFODATA, 0x00);
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x36);
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x00);
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x00);
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x08);
|
|
|
|
|
|
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(10);
|
|
|
|
|
|
GetReg(REG_ERROR, ®_data);
|
|
|
|
|
|
if ((reg_data & 0x0F) != 0)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_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;
|
|
|
|
|
|
SetCommand(CMD_IDLE);
|
|
|
|
|
|
SetReg(REG_TXDATANUM, 0x08);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetReg(REG_FIFODATA, 0x26);
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x01);
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x00);
|
|
|
|
|
|
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
|
|
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(10);
|
|
|
|
|
|
GetReg(REG_ERROR, ®_data);
|
|
|
|
|
|
if ((reg_data & 0x0F) != 0)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_data);
|
|
|
|
|
|
if (reg_data != 10)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFODATA, &picc_v->RESPONSE);
|
|
|
|
|
|
GetReg(REG_FIFODATA, ®_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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
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]);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
|
|
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(10);
|
|
|
|
|
|
GetReg(REG_ERROR, ®_data);
|
|
|
|
|
|
if ((reg_data & 0x0F) != 0)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
SetReg(REG_FIFODATA, 0x02); // Addressed flag
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x20); // Read Single Block command
|
|
|
|
|
|
SetReg(REG_FIFODATA, block_num);
|
|
|
|
|
|
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
|
|
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(10);
|
|
|
|
|
|
GetReg(REG_ERROR, ®_data);
|
|
|
|
|
|
if ((reg_data & 0x0F) != 0)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
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]);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
|
|
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(10);
|
|
|
|
|
|
GetReg(REG_ERROR, ®_data);
|
|
|
|
|
|
if ((reg_data & 0x0F) != 0)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_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);
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x06);
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x00);
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0xFF);
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0xFF);
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x10);
|
|
|
|
|
|
SetReg(REG_FIFODATA, 0x00);
|
|
|
|
|
|
|
2025-11-24 18:58:32 +08:00
|
|
|
|
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
|
|
|
|
|
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
|
2025-11-24 16:33:33 +08:00
|
|
|
|
|
|
|
|
|
|
SetCommand(CMD_TRANSCEIVE);
|
|
|
|
|
|
rfid_delay_ms(10);
|
|
|
|
|
|
GetReg(REG_ERROR, ®_data);
|
|
|
|
|
|
if ((reg_data & 0x0F) != 0)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFOLENGTH, ®_data);
|
|
|
|
|
|
if (reg_data != 18)
|
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
GetReg(REG_FIFODATA, ®_data); // Length
|
|
|
|
|
|
GetReg(REG_FIFODATA, ®_data); // Response code
|
|
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
GetReg(REG_FIFODATA, &picc_f->UID[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|