作为主设备去连接其他蓝牙设备
This commit is contained in:
447
apps/earphone/xtell_remote_control/RFID/reader/CPU_CARD.c
Normal file
447
apps/earphone/xtell_remote_control/RFID/reader/CPU_CARD.c
Normal file
@ -0,0 +1,447 @@
|
||||
#include "../include/READER.h"
|
||||
#include "../include/CPU_CARD.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 CPU_CARD_STR CPU_CARD;
|
||||
|
||||
// 声明一个静态函数用于TPDU传输,因为它只在本文件内部使用
|
||||
static unsigned char FM176XX_TPDU(transmission_struct *tpdu);
|
||||
|
||||
/**
|
||||
* @brief CPU卡事件处理函数(示例)。
|
||||
* @details
|
||||
* 1. 发送RATS (Request for Answer to Select) 命令以激活卡片并获取ATS (Answer to Select)。
|
||||
* 2. 解析ATS,获取卡片能力信息(如FSC, FWI等)。
|
||||
* 3. 发送一系列APDU (Application Protocol Data Unit) 指令与卡片应用进行交互。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||||
*/
|
||||
unsigned char CPU_CARD_EVENT(void)
|
||||
{
|
||||
unsigned char result;
|
||||
unsigned char SendBuffer[255];
|
||||
unsigned char ReceiveBuffer[255];
|
||||
int i;
|
||||
transmission_struct APDU;
|
||||
APDU.pSendBuffer = SendBuffer;
|
||||
APDU.pReceiveBuffer = ReceiveBuffer;
|
||||
|
||||
result = CPU_Rats(&CPU_CARD.ATS.Length, CPU_CARD.ATS.Ats_Data);
|
||||
if (result != SUCCESS)
|
||||
{
|
||||
SetCW(FUN_DISABLE);
|
||||
xlog("-> RATS ERROR!\r\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
xlog("-> ATS = ");
|
||||
for(i = 0; i < CPU_CARD.ATS.Length; i++)
|
||||
xlog("%02X", CPU_CARD.ATS.Ats_Data[i]);
|
||||
xlog("\r\n");
|
||||
|
||||
result = Ats_Process(CPU_CARD.ATS.Length, CPU_CARD.ATS.Ats_Data);
|
||||
if (result != SUCCESS)
|
||||
{
|
||||
SetCW(FUN_DISABLE);
|
||||
xlog("-> ATS Process ERROR!\r\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 选择主文件(MF)
|
||||
memcpy(APDU.pSendBuffer, "\x00\xA4\x00\x00\x02\x3F\x00", 7);
|
||||
APDU.SendLength = 7;
|
||||
result = CPU_APDU(&APDU);
|
||||
if (result != SUCCESS)
|
||||
{
|
||||
SetCW(FUN_DISABLE);
|
||||
xlog("-> APDU ERROR!\r\n");
|
||||
return result;
|
||||
}
|
||||
xlog("-> Select MF Response = ");
|
||||
for(i=0; i<APDU.ReceiveLength; i++)
|
||||
xlog("%02X", APDU.pReceiveBuffer[i]);
|
||||
xlog("\r\n");
|
||||
|
||||
// ... 此处可以添加更多APDU指令 ...
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将数据写入芯片的FIFO缓冲区。
|
||||
* @param length [in] 要写入的数据长度。
|
||||
* @param buff [in] 指向源数据缓冲区的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
static void Write_FIFO(unsigned char length, unsigned char* buff)
|
||||
{
|
||||
unsigned char i;
|
||||
for(i=0; i<length; i++)
|
||||
{
|
||||
SetReg(REG_FIFODATA,buff[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从芯片的FIFO缓冲区读取数据。
|
||||
* @param length [in] 要读取的数据长度。
|
||||
* @param buff [out] 指向目标数据缓冲区的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
static void Read_FIFO(unsigned char length, unsigned char* buff)
|
||||
{
|
||||
unsigned char i;
|
||||
for(i=0; i<length; i++)
|
||||
{
|
||||
GetReg(REG_FIFODATA,&buff[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行TPDU (Transmission Protocol Data Unit) 数据交换。
|
||||
* @param tpdu [in, out] 指向 `transmission_struct` 结构体的指针,包含发送和接收信息。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示超时或出错。
|
||||
* @details
|
||||
* 这是与卡片进行底层数据块交换的核心函数。它负责:
|
||||
* - 将数据写入FIFO。
|
||||
* - 启动TRANSCEIVE命令。
|
||||
* - 等待接收中断或超时。
|
||||
* - 从FIFO读取响应数据。
|
||||
* - 检查错误状态。
|
||||
*/
|
||||
static unsigned char FM176XX_TPDU(transmission_struct *tpdu)
|
||||
{
|
||||
unsigned char irq0, error;
|
||||
unsigned int i;
|
||||
SetCommand(CMD_IDLE);
|
||||
SetReg(REG_TXDATANUM,0x08);
|
||||
SetReg(REG_IRQ0,0x7F); // 清除IRQ0所有中断标志
|
||||
SetReg(REG_IRQ1,0x7F); // 清除IRQ1所有中断标志
|
||||
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,FUN_ENABLE); // 清空FIFO
|
||||
Write_FIFO(tpdu->SendLength,tpdu->pSendBuffer);
|
||||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
// SetTimer(tpdu->Timeout); // 定时器功能可以根据需要启用
|
||||
SetCommand(CMD_TRANSCEIVE);
|
||||
|
||||
// 等待接收完成或超时
|
||||
for(i = 0; i < tpdu->Timeout; i++)
|
||||
{
|
||||
rfid_delay_ms(1);
|
||||
GetReg(REG_IRQ0,&irq0);
|
||||
|
||||
if(irq0 & BIT_RXIRQ) // 检查是否收到数据
|
||||
{
|
||||
GetReg(REG_ERROR, &error); // 获取错误状态
|
||||
error &= (BIT_NODATAERR | BIT_COLLDET | BIT_PROTERR | BIT_INTEGERR);
|
||||
if(error != 0)
|
||||
return FAIL; // 接收到错误
|
||||
GetReg(REG_FIFOLENGTH, &tpdu->ReceiveLength);
|
||||
if(tpdu->ReceiveLength > 0)
|
||||
{
|
||||
Read_FIFO(tpdu->ReceiveLength,tpdu->pReceiveBuffer);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FAIL; // 超时
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 发送RATS (Request for Answer to Select) 命令。
|
||||
* @param ats_len [out] 指向用于存储ATS长度的变量的指针。
|
||||
* @param ats [out] 指向用于存储ATS数据的缓冲区的指针。
|
||||
* @return 操作状态,SUCCESS表示成功。
|
||||
* @details
|
||||
* RATS是激活ISO/IEC 14443-4卡片的第一步,用于获取卡片的基本通信参数。
|
||||
*/
|
||||
unsigned char CPU_Rats(unsigned char *ats_len, unsigned char *ats)
|
||||
{
|
||||
unsigned char result;
|
||||
unsigned char outbuffer[2], inbuffer[64];
|
||||
transmission_struct tpdu;
|
||||
tpdu.pSendBuffer = outbuffer;
|
||||
tpdu.pReceiveBuffer = inbuffer;
|
||||
tpdu.pSendBuffer[0] = 0xE0; // RATS命令起始字节
|
||||
tpdu.pSendBuffer[1] = 0x50; // 参数字节 (FSDI=5, CID=0)
|
||||
tpdu.SendLength = 2;
|
||||
tpdu.Timeout = 160; // 超时时间
|
||||
|
||||
result = FM176XX_TPDU(&tpdu);
|
||||
if (result == SUCCESS)
|
||||
{
|
||||
*ats_len = tpdu.ReceiveLength;
|
||||
memcpy(ats, tpdu.pReceiveBuffer, *ats_len);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 解析ATS (Answer to Select) 数据。
|
||||
* @param ats_len [in] ATS数据的长度。
|
||||
* @param ats [in] 指向ATS数据的指针。
|
||||
* @return 操作状态,SUCCESS表示成功。
|
||||
* @details
|
||||
* 此函数从ATS响应中提取关键参数,如FSC (Frame Size for proximity coupling)、
|
||||
* FWI (Frame Waiting time Integer)等,并存储在全局的 `CPU_CARD` 结构体中。
|
||||
*/
|
||||
unsigned char Ats_Process(unsigned char ats_len, unsigned char *ats)
|
||||
{
|
||||
unsigned char offset;
|
||||
|
||||
if (ats_len < 2) return FAIL;
|
||||
|
||||
// 解析FSCI (Frame Size for proximity coupling Integer) -> FSC
|
||||
CPU_CARD.FSCI = ats[1] & 0x0F;
|
||||
switch(CPU_CARD.FSCI) {
|
||||
case 0: CPU_CARD.FSC = 16; break;
|
||||
case 1: CPU_CARD.FSC = 24; break;
|
||||
case 2: CPU_CARD.FSC = 32; break;
|
||||
case 3: CPU_CARD.FSC = 40; break;
|
||||
case 4: CPU_CARD.FSC = 48; break;
|
||||
case 5: CPU_CARD.FSC = 64; break;
|
||||
case 6: CPU_CARD.FSC = 96; break;
|
||||
case 7: CPU_CARD.FSC = 128; break;
|
||||
case 8: CPU_CARD.FSC = 256; break;
|
||||
default: CPU_CARD.FSC = 32; break; // 默认值
|
||||
}
|
||||
xlog("-> CPU_CARD.FSC = %d\r\n", CPU_CARD.FSC);
|
||||
|
||||
offset = 0;
|
||||
if (ats[1] & BIT4) // TA(1) present
|
||||
{
|
||||
CPU_CARD.TA = ats[2];
|
||||
offset++;
|
||||
}
|
||||
|
||||
if (ats[1] & BIT5) // TB(1) present
|
||||
{
|
||||
CPU_CARD.TB = ats[2 + offset];
|
||||
CPU_CARD.SFGI = CPU_CARD.TB & 0x0F;
|
||||
CPU_CARD.FWI = (CPU_CARD.TB >> 4) & 0x0F;
|
||||
xlog("-> CPU_CARD.SFGI = %02X\r\n", CPU_CARD.SFGI);
|
||||
xlog("-> CPU_CARD.FWI = %02X\r\n", CPU_CARD.FWI);
|
||||
|
||||
// 根据FWI计算FWT (Frame Waiting Time)
|
||||
unsigned long base_fwt = 256 * 16 / 13560; // (256 * 16 / fc) in ms
|
||||
CPU_CARD.FWT = base_fwt * (1 << CPU_CARD.FWI);
|
||||
offset++;
|
||||
} else {
|
||||
CPU_CARD.FWT = 160; // 默认FWT
|
||||
}
|
||||
|
||||
if (ats[1] & BIT6) // TC(1) present
|
||||
{
|
||||
CPU_CARD.TC = ats[2 + offset];
|
||||
offset++;
|
||||
}
|
||||
|
||||
CPU_CARD.PCB = 0x02; // PCB初始值为0x02
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 发送NAK (Negative Acknowledge) 响应。
|
||||
* @param tpdu [in, out] 指向传输结构体的指针。
|
||||
* @return 操作状态。
|
||||
* @details
|
||||
* 在TPDU交换中,如果接收到错误的数据块,会发送NAK请求重发。
|
||||
*/
|
||||
unsigned char CPU_NAK(transmission_struct *tpdu)
|
||||
{
|
||||
unsigned char result, tpdu_send_buffer[1], tpdu_receive_buffer[255];
|
||||
|
||||
tpdu->pSendBuffer = tpdu_send_buffer;
|
||||
tpdu->pReceiveBuffer = tpdu_receive_buffer;
|
||||
|
||||
tpdu->pSendBuffer[0] = 0xB0 | CPU_CARD.PCB; // NAK PCB
|
||||
tpdu->SendLength = 1;
|
||||
|
||||
result = FM176XX_TPDU(tpdu);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 封装了重试逻辑的TPDU传输函数。
|
||||
* @param tpdu [in, out] 指向传输结构体的指针。
|
||||
* @return 操作状态。
|
||||
* @details
|
||||
* 此函数调用底层的 `FM176XX_TPDU`,并在失败时进行最多3次重试。
|
||||
* 它还处理ACK/NAK逻辑,以确保数据的可靠传输。
|
||||
*/
|
||||
unsigned char CPU_TPDU(transmission_struct *tpdu)
|
||||
{
|
||||
unsigned char result, i, pcb_byte;
|
||||
transmission_struct nak_tpdu;
|
||||
|
||||
result = FM176XX_TPDU(tpdu);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (result != SUCCESS)
|
||||
{
|
||||
result = CPU_NAK(&nak_tpdu);
|
||||
if(result == SUCCESS && nak_tpdu.ReceiveLength > 0)
|
||||
{
|
||||
memcpy(&pcb_byte, nak_tpdu.pReceiveBuffer, 1);
|
||||
if((pcb_byte & 0xF0) == 0xA0) // R(ACK)
|
||||
{
|
||||
xlog("...pcb_byte = %02X\r\n", pcb_byte);
|
||||
xlog("...CPU_CARD.PCB = %02X\r\n", CPU_CARD.PCB);
|
||||
if((pcb_byte & 0x01) != (CPU_CARD.PCB & 0x01))
|
||||
{
|
||||
result = FM176XX_TPDU(tpdu);
|
||||
}
|
||||
else
|
||||
{
|
||||
tpdu->pSendBuffer[0] ^= 0x01; // 翻转序列号位
|
||||
CPU_CARD.PCB = tpdu->pSendBuffer[0] & 0x01;
|
||||
result = FM176XX_TPDU(tpdu);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break; // 成功则退出循环
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 发送APDU (Application Protocol Data Unit) 命令。
|
||||
* @param apdu [in, out] 指向传输结构体的指针,包含APDU命令和响应。
|
||||
* @return 操作状态。
|
||||
* @details
|
||||
* 此函数处理APDU的块链接(chaining)逻辑。如果APDU长度超过卡片的最大帧大小(FSC),
|
||||
* 它会自动将APDU分割成多个TPDU块进行传输。
|
||||
*/
|
||||
unsigned char CPU_APDU(transmission_struct *apdu)
|
||||
{
|
||||
unsigned char result, pcb_byte, i;
|
||||
unsigned char tpdu_send_buffer[256], tpdu_receive_buffer[256];
|
||||
unsigned int unsent_length;
|
||||
transmission_struct tpdu;
|
||||
|
||||
tpdu.pSendBuffer = tpdu_send_buffer;
|
||||
tpdu.pReceiveBuffer = tpdu_receive_buffer;
|
||||
tpdu.Timeout = CPU_CARD.FWT;
|
||||
apdu->ReceiveLength = 0;
|
||||
unsent_length = apdu->SendLength;
|
||||
|
||||
// --- 发送阶段 ---
|
||||
for (i = 0; i < 16; i++) // 最多16个链式块
|
||||
{
|
||||
xlog("unsent_length = %d\r\n", unsent_length);
|
||||
if (unsent_length <= (CPU_CARD.FSC - 1))
|
||||
{
|
||||
// 最后一个或唯一的数据块
|
||||
tpdu.pSendBuffer[0] = CPU_CARD.PCB; // I-Block, no chaining
|
||||
memcpy(tpdu.pSendBuffer + 1, apdu->pSendBuffer + apdu->SendLength - unsent_length, unsent_length);
|
||||
tpdu.SendLength = unsent_length + 1;
|
||||
|
||||
xlog("--> ");
|
||||
for(int j=0; j<tpdu.SendLength; j++) xlog("%02X", tpdu.pSendBuffer[j]);
|
||||
xlog("\r\n");
|
||||
|
||||
result = CPU_TPDU(&tpdu);
|
||||
if ((result != SUCCESS) || (tpdu.ReceiveLength == 0))
|
||||
return (result);
|
||||
|
||||
xlog("<-- ");
|
||||
for(int j=0; j<tpdu.ReceiveLength; j++) xlog("%02X", tpdu.pReceiveBuffer[j]);
|
||||
xlog("\r\n");
|
||||
|
||||
unsent_length = 0;
|
||||
break; // 发送完成
|
||||
}
|
||||
else
|
||||
{
|
||||
// 需要分块传输
|
||||
tpdu.pSendBuffer[0] = CPU_CARD.PCB | 0x10; // I-Block with chaining
|
||||
memcpy(tpdu.pSendBuffer + 1, apdu->pSendBuffer + apdu->SendLength - unsent_length, CPU_CARD.FSC - 1);
|
||||
tpdu.SendLength = CPU_CARD.FSC;
|
||||
|
||||
xlog("..--> ");
|
||||
for(int j=0; j<tpdu.SendLength; j++) xlog("%02X", tpdu.pSendBuffer[j]);
|
||||
xlog("\r\n");
|
||||
|
||||
result = CPU_TPDU(&tpdu);
|
||||
|
||||
xlog("<-- ");
|
||||
for(int j=0; j<tpdu.ReceiveLength; j++) xlog("%02X", tpdu.pReceiveBuffer[j]);
|
||||
xlog("\r\n");
|
||||
|
||||
if ((result != SUCCESS) || (tpdu.ReceiveLength != 1))
|
||||
return (result);
|
||||
|
||||
memcpy(&pcb_byte, tpdu.pReceiveBuffer, 1);
|
||||
if ((pcb_byte & 0xE0) == 0xA0) // R(ACK) block
|
||||
{
|
||||
unsent_length -= (CPU_CARD.FSC - 1);
|
||||
CPU_CARD.PCB = (pcb_byte & 0x01) ^ 0x01; // 更新序列号
|
||||
xlog("unsent_length = %d\r\n", unsent_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (FAIL); // 未收到预期的ACK
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- 接收阶段 ---
|
||||
for (i = 0; i < 255; i++) // 最多255个链式块
|
||||
{
|
||||
if ((result != SUCCESS) || (tpdu.ReceiveLength == 0))
|
||||
return (FAIL);
|
||||
|
||||
memcpy(&pcb_byte, tpdu.pReceiveBuffer, 1);
|
||||
|
||||
if ((pcb_byte & 0xC0) == 0x00) // I-Block
|
||||
{
|
||||
CPU_CARD.PCB = (pcb_byte & 0x01) ^ 0x01;
|
||||
memcpy(apdu->pReceiveBuffer + apdu->ReceiveLength, tpdu.pReceiveBuffer + 1, tpdu.ReceiveLength - 1);
|
||||
apdu->ReceiveLength += (tpdu.ReceiveLength - 1);
|
||||
|
||||
if (pcb_byte & 0x10) // 还有后续数据块
|
||||
{
|
||||
tpdu.pSendBuffer[0] = 0xA0 | CPU_CARD.PCB; // 发送ACK
|
||||
tpdu.SendLength = 1;
|
||||
xlog("...--> ACK = %02X\r\n", tpdu.pSendBuffer[0]);
|
||||
result = CPU_TPDU(&tpdu);
|
||||
}
|
||||
else // 最后一个数据块
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
else if ((pcb_byte & 0xE0) == 0xE0) // S-Block (WTX)
|
||||
{
|
||||
// 回复WTX响应
|
||||
memcpy(tpdu.pSendBuffer, tpdu.pReceiveBuffer, tpdu.ReceiveLength);
|
||||
tpdu.SendLength = tpdu.ReceiveLength;
|
||||
xlog("....--> WTX = ");
|
||||
for(int j=0; j<tpdu.SendLength; j++) xlog("%02X", tpdu.pSendBuffer[j]);
|
||||
xlog("\r\n");
|
||||
result = CPU_TPDU(&tpdu);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FAIL; // 未知响应
|
||||
}
|
||||
}
|
||||
return (FAIL); // 接收块过多
|
||||
}
|
||||
455
apps/earphone/xtell_remote_control/RFID/reader/MIFARE.c
Normal file
455
apps/earphone/xtell_remote_control/RFID/reader/MIFARE.c
Normal file
@ -0,0 +1,455 @@
|
||||
#include "../include/MIFARE.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
|
||||
|
||||
|
||||
unsigned char SECTOR,BLOCK,BLOCK_NUM;
|
||||
unsigned char BLOCK_DATA[16];
|
||||
unsigned char KEY_A[16][6]=
|
||||
{{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//0
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//1
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//2
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//3
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//4
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//5
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//6
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//7
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//8
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//9
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//10
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//11
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//12
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//13
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//14
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};//15
|
||||
|
||||
unsigned char KEY_B[16][6]=
|
||||
{{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//0
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//1
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//2
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//3
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//4
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//5
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//6
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//7
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//8
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//9
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//10
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//11
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//12
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//13
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//14
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};//15
|
||||
|
||||
/**
|
||||
* @brief 清除Mifare卡加密认证标志。
|
||||
* @details
|
||||
* 在对Mifare卡进行认证(Authentication)后,芯片内部会设置一个加密标志位(BIT_CRYPTO1ON)。
|
||||
* 此函数用于清除该标志,以便可以对新的扇区进行认证或执行非加密操作。
|
||||
* @return 无。
|
||||
*/
|
||||
void Mifare_Clear_Crypto(void)
|
||||
{
|
||||
ModifyReg(REG_STATUS,BIT_CRYPTO1ON,RESET);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Mifare卡事件处理函数(示例)。
|
||||
* @details
|
||||
* 这是一个示例函数,演示了对Mifare Classic卡进行读写操作的完整流程:
|
||||
* 1. 清除加密状态。
|
||||
* 2. 对指定的扇区(例如扇区1)使用密钥A进行认证。
|
||||
* 3. 如果认证成功,则遍历该扇区的数据块(块0到块2)。
|
||||
* 4. 对每个块先执行写操作,写入16字节的0xFF。
|
||||
* 5. 然后再执行读操作,将数据读回并打印。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||||
*/
|
||||
unsigned char MIFARE_CARD_EVENT(void)
|
||||
{
|
||||
unsigned char result;
|
||||
int i;
|
||||
Mifare_Clear_Crypto();
|
||||
SECTOR = 1;
|
||||
//for(SECTOR = 0;SECTOR < 16; SECTOR++)
|
||||
{
|
||||
BLOCK_NUM = (SECTOR * 4) + BLOCK;
|
||||
result = Mifare_Auth(KEY_A_M1,SECTOR,KEY_A[SECTOR],PICC_A.UID);
|
||||
if(result != SUCCESS)
|
||||
{
|
||||
SetCW(FUN_DISABLE);
|
||||
xlog("-> AUTH ERROR!\r\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
xlog("-> AUTH SUCCESS!\r\n");
|
||||
|
||||
for(BLOCK = 0;BLOCK < 3;BLOCK++)
|
||||
{
|
||||
BLOCK_NUM = (SECTOR * 4) + BLOCK;
|
||||
if(BLOCK_NUM == 0)
|
||||
BLOCK_NUM = 1;
|
||||
xlog("-> SECTOR = %02X\r\n",SECTOR);;
|
||||
xlog("-> BLOCK = %02X\r\n",BLOCK);
|
||||
xlog("-> BLOCK_NUM = %02X\r\n",BLOCK_NUM);
|
||||
memcpy(BLOCK_DATA,"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",16);
|
||||
result = Mifare_Blockwrite(BLOCK_NUM,BLOCK_DATA);
|
||||
if(result != SUCCESS)
|
||||
{
|
||||
SetCW(FUN_DISABLE);
|
||||
xlog("-> WRITE BLOCK ERROR!\r\n");
|
||||
return result;
|
||||
}
|
||||
xlog("-> WRITE BLOCK SUCCESS!\r\n");
|
||||
|
||||
result = Mifare_Blockread(BLOCK_NUM,BLOCK_DATA);
|
||||
if(result != SUCCESS)
|
||||
{
|
||||
SetCW(FUN_DISABLE);
|
||||
xlog("-> READ BLOCK ERROR!\r\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
xlog("-> READ BLOCK = ");
|
||||
for(i=0; i<16; i++) xlog("%02X", BLOCK_DATA[i]);
|
||||
xlog("\r\n");
|
||||
}
|
||||
}
|
||||
SetCW(FUN_DISABLE);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将6字节的Mifare密钥加载到芯片的密钥缓冲区。
|
||||
* @param mifare_key [in] 指向6字节密钥数组的指针。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||||
* @details
|
||||
* 在执行认证命令(Mifare_Auth)之前,必须先调用此函数将要使用的密钥加载到芯片内部。
|
||||
*/
|
||||
unsigned char Mifare_LoadKey(unsigned char *mifare_key)
|
||||
{
|
||||
unsigned char reg_data;
|
||||
SetCommand(CMD_IDLE);
|
||||
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,FUN_ENABLE); //Clear FIFO
|
||||
SetReg(REG_FIFODATA,mifare_key[0]);
|
||||
SetReg(REG_FIFODATA,mifare_key[1]);
|
||||
SetReg(REG_FIFODATA,mifare_key[2]);
|
||||
SetReg(REG_FIFODATA,mifare_key[3]);
|
||||
SetReg(REG_FIFODATA,mifare_key[4]);
|
||||
SetReg(REG_FIFODATA,mifare_key[5]);
|
||||
SetCommand(CMD_LOADKEY);
|
||||
rfid_delay_ms(1);
|
||||
GetReg(REG_COMMAND,®_data);
|
||||
if((reg_data & CMD_MASK) == CMD_IDLE)
|
||||
return SUCCESS;
|
||||
else
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 对Mifare Classic卡片的指定扇区进行认证。
|
||||
* @param key_mode [in] 认证模式,`KEY_A_M1` (0) 表示使用密钥A,`KEY_B_M1` (1) 表示使用密钥B。
|
||||
* @param sector [in] 要认证的扇区号 (0-15)。
|
||||
* @param mifare_key [in] 指向6字节认证密钥的指针。
|
||||
* @param card_uid [in] 指向4字节卡片UID的指针。
|
||||
* @return 操作状态,SUCCESS表示认证成功,FAIL表示失败。
|
||||
* @details
|
||||
* 这是访问Mifare卡数据块之前的必要步骤。认证成功后,芯片会设置加密标志位。
|
||||
*/
|
||||
unsigned char Mifare_Auth(unsigned char key_mode,unsigned char sector,unsigned char *mifare_key,unsigned char *card_uid)
|
||||
{
|
||||
unsigned char result,reg_data;
|
||||
result = Mifare_LoadKey(mifare_key);
|
||||
if (result != SUCCESS)
|
||||
return result;
|
||||
SetCommand(CMD_IDLE);
|
||||
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,FUN_ENABLE); //Clear FIFO
|
||||
if(key_mode == KEY_A_M1)
|
||||
{
|
||||
SetReg(REG_FIFODATA,0x60);// 0x60: Key A认证指令
|
||||
ModifyReg(REG_RXTXCON,BIT_SHMODE,FUN_DISABLE);
|
||||
}
|
||||
if(key_mode == KEY_B_M1)
|
||||
{
|
||||
SetReg(REG_FIFODATA,0x61);// 0x61: Key B认证指令
|
||||
ModifyReg(REG_RXTXCON,BIT_SHMODE,FUN_DISABLE);
|
||||
}
|
||||
|
||||
SetReg(REG_FIFODATA,sector * 4);// 认证扇区的块0地址
|
||||
SetReg(REG_FIFODATA,card_uid[0]);
|
||||
SetReg(REG_FIFODATA,card_uid[1]);
|
||||
SetReg(REG_FIFODATA,card_uid[2]);
|
||||
SetReg(REG_FIFODATA,card_uid[3]);
|
||||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
SetCommand(CMD_AUTHENT);
|
||||
rfid_delay_ms(5);
|
||||
GetReg(REG_COMMAND,®_data);
|
||||
if((reg_data & CMD_MASK) == CMD_IDLE)
|
||||
{
|
||||
GetReg(REG_STATUS,®_data);
|
||||
if(reg_data & BIT_CRYPTO1ON)// 检查加密标志位以确认认证成功
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将4字节数据格式化为Mifare值块格式并写入指定块。
|
||||
* @param block [in] 目标块号。
|
||||
* @param data_buff [in] 指向4字节源数据的指针。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||||
* @details
|
||||
* Mifare值块有特定的数据格式,包含值、值的反码和地址字节。此函数会自动处理格式转换。
|
||||
*/
|
||||
unsigned char Mifare_Blockset(unsigned char block,unsigned char *data_buff)
|
||||
{
|
||||
unsigned char block_data[16],result;
|
||||
// 格式化为值块
|
||||
block_data[0] = data_buff[3];
|
||||
block_data[1] = data_buff[2];
|
||||
block_data[2] = data_buff[1];
|
||||
block_data[3] = data_buff[0];
|
||||
block_data[4] = ~data_buff[3];
|
||||
block_data[5] = ~data_buff[2];
|
||||
block_data[6] = ~data_buff[1];
|
||||
block_data[7] = ~data_buff[0];
|
||||
block_data[8] = data_buff[3];
|
||||
block_data[9] = data_buff[2];
|
||||
block_data[10] = data_buff[1];
|
||||
block_data[11] = data_buff[0];
|
||||
block_data[12] = block;
|
||||
block_data[13] = ~block;
|
||||
block_data[14] = block;
|
||||
block_data[15] = ~block;
|
||||
result = Mifare_Blockwrite(block,block_data);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从Mifare卡读取一个16字节的数据块。
|
||||
* @param block [in] 要读取的块号 (0x00 - 0x3F)。
|
||||
* @param data_buff [out] 指向16字节缓冲区的指针,用于存储读取的数据。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||||
*/
|
||||
unsigned char Mifare_Blockread(unsigned char block,unsigned char *data_buff)
|
||||
{
|
||||
unsigned char reg_data,i;
|
||||
SetCommand(CMD_IDLE);
|
||||
SetReg(REG_TXDATANUM,0x08);
|
||||
SetReg(REG_FIFODATA,0x30);// 0x30: 读块指令
|
||||
SetReg(REG_FIFODATA,block);// 块地址
|
||||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
SetCommand(CMD_TRANSCEIVE);
|
||||
rfid_delay_ms(2);
|
||||
GetReg(REG_FIFOLENGTH,®_data);
|
||||
if (reg_data != 16) // 成功时应返回16字节数据
|
||||
return FAIL;
|
||||
GetReg(REG_ERROR,®_data);
|
||||
if(reg_data & 0x07)
|
||||
return FAIL;
|
||||
for(i=0;i<16;i++)
|
||||
{
|
||||
GetReg (REG_FIFODATA,&data_buff[i]);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 向Mifare卡写入一个16字节的数据块。
|
||||
* @param block [in] 要写入的块号 (0x00 - 0x3F)。
|
||||
* @param data_buff [in] 指向16字节数据的指针。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||||
*/
|
||||
unsigned char Mifare_Blockwrite(unsigned char block,unsigned char *data_buff)
|
||||
{
|
||||
unsigned char reg_data,i;
|
||||
SetCommand(CMD_IDLE);
|
||||
SetReg(REG_TXDATANUM,0x08);
|
||||
SetReg(REG_FIFODATA,0xA0);// 0xA0: 写块指令
|
||||
SetReg(REG_FIFODATA,block);// 块地址
|
||||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_DISABLE);
|
||||
SetCommand(CMD_TRANSCEIVE);
|
||||
rfid_delay_ms(5);
|
||||
GetReg(REG_FIFOLENGTH,®_data);
|
||||
if (reg_data != 1) // 接收到ACK (0x0A)
|
||||
return FAIL;
|
||||
GetReg (REG_FIFODATA,®_data);
|
||||
if(reg_data != 0x0A)
|
||||
return FAIL;
|
||||
for(i=0;i<16;i++)
|
||||
{
|
||||
SetReg(REG_FIFODATA,data_buff[i]);
|
||||
}
|
||||
SetCommand(CMD_TRANSCEIVE);
|
||||
rfid_delay_ms(5);
|
||||
GetReg(REG_FIFOLENGTH,®_data);
|
||||
if (reg_data != 1) // 接收到ACK (0x0A)
|
||||
return FAIL;
|
||||
GetReg (REG_FIFODATA,®_data);
|
||||
if(reg_data != 0x0A)
|
||||
return FAIL;
|
||||
|
||||
return SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 对Mifare卡的指定值块执行增值操作。
|
||||
* @param block [in] 值块的块号。
|
||||
* @param data_buff [in] 指向4字节增值数据的指针。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||||
*/
|
||||
unsigned char Mifare_Blockinc(unsigned char block,unsigned char *data_buff)
|
||||
{
|
||||
unsigned char reg_data,i;
|
||||
SetCommand(CMD_IDLE);
|
||||
SetReg(REG_TXDATANUM,0x08);
|
||||
SetReg(REG_FIFODATA,0xC1);// 0xC1: 增值指令
|
||||
SetReg(REG_FIFODATA,block);// 块地址
|
||||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_DISABLE);
|
||||
SetCommand(CMD_TRANSCEIVE);
|
||||
rfid_delay_ms(5);
|
||||
GetReg(REG_FIFOLENGTH,®_data);
|
||||
if (reg_data != 1)
|
||||
return FAIL;
|
||||
GetReg (REG_FIFODATA,®_data);
|
||||
if(reg_data != 0x0A)
|
||||
return FAIL;
|
||||
for(i=0;i<4;i++)
|
||||
{
|
||||
SetReg(REG_FIFODATA,data_buff[i]);
|
||||
}
|
||||
SetCommand(CMD_TRANSCEIVE);
|
||||
rfid_delay_ms(5);
|
||||
GetReg(REG_FIFOLENGTH,®_data);
|
||||
if (reg_data != 1)
|
||||
return FAIL;
|
||||
GetReg (REG_FIFODATA,®_data);
|
||||
|
||||
if(reg_data != 0x0A)
|
||||
return FAIL;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 对Mifare卡的指定值块执行减值操作。
|
||||
* @param block [in] 值块的块号。
|
||||
* @param data_buff [in] 指向4字节减值数据的指针。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||||
*/
|
||||
unsigned char Mifare_Blockdec(unsigned char block,unsigned char *data_buff)
|
||||
{
|
||||
unsigned char reg_data,i;
|
||||
SetCommand(CMD_IDLE);
|
||||
SetReg(REG_TXDATANUM,0x08);
|
||||
SetReg(REG_FIFODATA,0xC0);// 0xC0: 减值指令
|
||||
SetReg(REG_FIFODATA,block);// 块地址
|
||||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_DISABLE);
|
||||
SetCommand(CMD_TRANSCEIVE);
|
||||
rfid_delay_ms(5);
|
||||
GetReg(REG_FIFOLENGTH,®_data);
|
||||
if (reg_data != 1)
|
||||
return FAIL;
|
||||
GetReg (REG_FIFODATA,®_data);
|
||||
if(reg_data != 0x0A)
|
||||
return FAIL;
|
||||
for(i=0;i<4;i++)
|
||||
{
|
||||
SetReg(REG_FIFODATA,data_buff[i]);
|
||||
}
|
||||
SetCommand(CMD_TRANSCEIVE);
|
||||
rfid_delay_ms(5);
|
||||
GetReg(REG_FIFOLENGTH,®_data);
|
||||
if (reg_data != 1)
|
||||
return FAIL;
|
||||
GetReg (REG_FIFODATA,®_data);
|
||||
if(reg_data != 0x0A)
|
||||
return FAIL;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行Mifare卡的传输(Transfer)命令。
|
||||
* @param block [in] 块号。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||||
* @details
|
||||
* 在对值块进行增/减值操作后,需要调用此函数将结果从内部寄存器写入到块中。
|
||||
*/
|
||||
unsigned char Mifare_Transfer(unsigned char block)
|
||||
{
|
||||
unsigned char reg_data;
|
||||
SetCommand(CMD_IDLE);
|
||||
SetReg(REG_TXDATANUM,0x08);
|
||||
SetReg(REG_FIFODATA,0xB0);// 0xB0: Transfer指令
|
||||
SetReg(REG_FIFODATA,block);// 块地址
|
||||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_DISABLE);
|
||||
SetCommand(CMD_TRANSCEIVE);
|
||||
rfid_delay_ms(5);
|
||||
GetReg(REG_FIFOLENGTH,®_data);
|
||||
if (reg_data != 1)
|
||||
return FAIL;
|
||||
GetReg (REG_FIFODATA,®_data);
|
||||
if(reg_data != 0x0A)
|
||||
return FAIL;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行Mifare卡的恢复(Restore)命令。
|
||||
* @param block [in] 块号。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||||
* @details
|
||||
* 此命令用于将一个块的内容从内部寄存器中恢复。
|
||||
*/
|
||||
unsigned char Mifare_Restore(unsigned char block)
|
||||
{
|
||||
unsigned char reg_data,i;
|
||||
SetCommand(CMD_IDLE);
|
||||
SetReg(REG_TXDATANUM,0x08);
|
||||
SetReg(REG_FIFODATA,0xC2);// 0xC2: Restore指令
|
||||
SetReg(REG_FIFODATA,block);// 块地址
|
||||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_DISABLE);
|
||||
SetCommand(CMD_TRANSCEIVE);
|
||||
rfid_delay_ms(5);
|
||||
GetReg(REG_FIFOLENGTH,®_data);
|
||||
if (reg_data != 1)
|
||||
return FAIL;
|
||||
GetReg (REG_FIFODATA,®_data);
|
||||
if(reg_data != 0x0A)
|
||||
return FAIL;
|
||||
for(i=0;i<4;i++)
|
||||
{
|
||||
SetReg(REG_FIFODATA,0);
|
||||
}
|
||||
SetCommand(CMD_TRANSCEIVE);
|
||||
rfid_delay_ms(5);
|
||||
GetReg(REG_FIFOLENGTH,®_data);
|
||||
if (reg_data != 1)
|
||||
return FAIL;
|
||||
GetReg (REG_FIFODATA,®_data);
|
||||
if(reg_data != 0x0A)
|
||||
return FAIL;
|
||||
return SUCCESS;
|
||||
}
|
||||
108
apps/earphone/xtell_remote_control/RFID/reader/NTAG.c
Normal file
108
apps/earphone/xtell_remote_control/RFID/reader/NTAG.c
Normal file
@ -0,0 +1,108 @@
|
||||
#include "../include/READER.h"
|
||||
#include "../include/NTAG.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
|
||||
|
||||
|
||||
|
||||
unsigned char PAGE_DATA[16];
|
||||
|
||||
/**
|
||||
* @brief NTAG卡事件处理函数(示例)。
|
||||
* @details
|
||||
* 这是一个示例函数,演示了对NTAG系列卡片进行读写操作的流程:
|
||||
* 1. 准备要写入的数据(4字节)。
|
||||
* 2. 调用 `Write_Page()` 函数将数据写入第8页。
|
||||
* 3. 调用 `Read_Page()` 函数从第8页读回数据并打印,以进行验证。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||||
*/
|
||||
unsigned char NTAG_EVENT(void)
|
||||
{
|
||||
unsigned char result;
|
||||
memcpy(PAGE_DATA,"\x01\x02\x03\x04",4);
|
||||
result = Write_Page(8,PAGE_DATA);
|
||||
if (result != SUCCESS)
|
||||
return result;
|
||||
xlog("PAGE 8 Write OK\r\n");
|
||||
result = Read_Page(8,PAGE_DATA);
|
||||
xlog("PAGE 8 = %02X%02X%02X%02X\r\n",PAGE_DATA[0],PAGE_DATA[1],PAGE_DATA[2],PAGE_DATA[3]);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从NTAG卡读取一个或多个页的数据。
|
||||
* @param page_num [in] 要读取的起始页号。
|
||||
* @param page_data [out] 指向缓冲区的指针,用于存储读取的数据。对于NTAG21x系列,一次最少读取16字节(4页)。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||||
*/
|
||||
unsigned char Read_Page(unsigned char page_num,unsigned char *page_data)
|
||||
{
|
||||
unsigned char reg_data,i;
|
||||
SetCommand(CMD_IDLE);
|
||||
Clear_FIFO();
|
||||
SetReg(REG_FIFODATA,0x30); // 读指令
|
||||
SetReg(REG_FIFODATA,page_num);
|
||||
|
||||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
SetCommand(CMD_TRANSCEIVE);
|
||||
rfid_delay_ms(5);
|
||||
GetReg(REG_ERROR,®_data);
|
||||
if(reg_data & 0x07)
|
||||
return FAIL;
|
||||
GetReg(REG_FIFOLENGTH,®_data);
|
||||
if(reg_data != 16) // NTAG一次读取返回16字节
|
||||
return FAIL;
|
||||
for(i=0;i<16;i++)
|
||||
{
|
||||
GetReg(REG_FIFODATA,&page_data[i]);
|
||||
}
|
||||
return SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 向NTAG卡的一个页(Page)写入4字节数据。
|
||||
* @param page_num [in] 要写入的页号。
|
||||
* @param page_data [in] 指向4字节数据的指针。
|
||||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||||
*/
|
||||
unsigned char Write_Page(unsigned char page_num,unsigned char *page_data)
|
||||
{
|
||||
unsigned char reg_data;
|
||||
SetCommand(CMD_IDLE);
|
||||
Clear_FIFO();
|
||||
SetReg(REG_FIFODATA,0xA2); // 写指令
|
||||
SetReg(REG_FIFODATA,page_num);
|
||||
SetReg(REG_FIFODATA,page_data[0]);
|
||||
SetReg(REG_FIFODATA,page_data[1]);
|
||||
SetReg(REG_FIFODATA,page_data[2]);
|
||||
SetReg(REG_FIFODATA,page_data[3]);
|
||||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
|
||||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_DISABLE);
|
||||
SetCommand(CMD_TRANSCEIVE);
|
||||
rfid_delay_ms(5);
|
||||
|
||||
GetReg(REG_FIFOLENGTH,®_data);
|
||||
if(reg_data != 1) // 应该收到一个ACK
|
||||
return FAIL;
|
||||
|
||||
GetReg(REG_FIFODATA,®_data);
|
||||
if(reg_data != 0x0A) // ACK的值为0x0A
|
||||
return FAIL;
|
||||
return SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
784
apps/earphone/xtell_remote_control/RFID/reader/READER.c
Normal file
784
apps/earphone/xtell_remote_control/RFID/reader/READER.c
Normal file
@ -0,0 +1,784 @@
|
||||
/********************************************************************************************************
|
||||
* @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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user