785 lines
25 KiB
C
785 lines
25 KiB
C
/********************************************************************************************************
|
||
* @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 修改寄存器的特定位。
|
||
* @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场(载波)。
|
||
* @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(10);
|
||
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, ®_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卡片发送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);
|
||
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, ®_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);
|
||
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, ®_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, ®_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, ®_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);
|
||
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, ®_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);
|
||
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, ®_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);
|
||
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, ®_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);
|
||
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, ®_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);
|
||
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, ®_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, result; // 新增 result 变量
|
||
SetCommand(CMD_IDLE);
|
||
|
||
|
||
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);
|
||
rfid_delay_ms(50);
|
||
|
||
GetReg(REG_ERROR, ®_data);
|
||
if ((reg_data & 0x0F) != 0){
|
||
xlog("REG_ERROR = 0x%02X\n", reg_data);
|
||
return FAIL;
|
||
}
|
||
|
||
GetReg(REG_FIFOLENGTH, ®_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, ®_data); // DSFID
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
GetReg(REG_FIFODATA, &picc_v->UID[i]);
|
||
// xlog("%d ",picc_v->UID[i]);
|
||
}
|
||
// xlog("\r\n");
|
||
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, result;
|
||
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, ®_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);
|
||
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, ®_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);
|
||
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, ®_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);
|
||
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, ®_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;
|
||
}
|
||
|