Files
99_7018_lmx/apps/earphone/remote_control/RFID/rfid_event.c
2025-12-01 18:05:09 +08:00

304 lines
7.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************************************************************
* @file rfid_main.c
* @brief RFID 读卡器应用层主逻辑文件
********************************************************************************************************/
#include "./include/rfid_main.h"
#include "./include/READER.h"
#include "./include/READER_REG.h"
#include "./include/MIFARE.h"
#include "./include/NTAG.h"
#include "./include/CPU_CARD.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
/**
* @brief 处理Type A卡片事件。
* @details
* 该函数执行ISO/IEC 14443 Type A卡片的完整激活流程包括
* 1. 初始化读卡器以支持Type A协议。
* 2. 打开RF场。
* 3. 请求Request和防冲突Anticollision最终激活卡片。
* 4. 根据卡片的SAKSelect Acknowledge判断卡片具体类型如Mifare, NTAG, CPU卡并调用相应的处理函数。
* 5. 操作结束后关闭RF场。
* @return 无。
*/
void TYPE_A_EVENT(void)
{
unsigned char result;
int i;
xlog("TYPE_A_EVENT begin\n");
// 初始化读卡器为Type A模式
result = ReaderA_Initial();
if (result != SUCCESS)
{
xlog("INIT_ERROR\r\n");
SetCW(FUN_DISABLE);
return;
}
// 打开RF场载波
result = SetCW(FUN_ENABLE);
if (result != SUCCESS)
{
xlog("CW_ERROR\r\n");
SetCW(FUN_DISABLE);
return;
}
// 激活Type A卡片
result = ReaderA_CardActivate(&PICC_A);
if (result != SUCCESS)
{
xlog("ReaderA_CardActivate_ERROR\r\n");
SetCW(FUN_DISABLE);
return;
}
xlog("************* TYPE A CARD ************* \r\n");
xlog("-> ATQA = %02X%02X\r\n", PICC_A.ATQA[0], PICC_A.ATQA[1]);
if (PICC_A.UID_Length > 0)
{
xlog("-> UID = ");
for (i = 0; i < PICC_A.UID_Length; i++)
{
xlog("%02X", PICC_A.UID[i]);
}
xlog("\r\n");
}
xlog("-> SAK = %02X\r\n", PICC_A.SAK[0]);
// 根据SAK值判断卡片类型
if (PICC_A.SAK[0] == 0x08)
{
xlog("************* Mifare CARD ************* \r\n");
result = MIFARE_CARD_EVENT();
}
else if ((PICC_A.SAK[0] == 0x28) || (PICC_A.SAK[0] == 0x20))
{
xlog("************* CPU CARD ************* \r\n");
result = CPU_CARD_EVENT();
}
else if (PICC_A.SAK[0] == 0x04)
{
xlog("************* NTAG CARD ************* \r\n");
result = NTAG_EVENT();
}
SetCW(FUN_DISABLE); // 关闭RF场
}
/**
* @brief 处理Type B卡片事件。
* @details
* 该函数执行ISO/IEC 14443 Type B卡片的激活流程包括
* 1. 初始化读卡器以支持Type B协议。
* 2. 打开RF场。
* 3. 发送REQB/WUPB命令寻卡。
* 4. 发送ATTRIB命令选卡。
* 5. 获取卡片序列号SN
* 6. 操作结束后关闭RF场。
* @return 无。
*/
void TYPE_B_EVENT(void)
{
unsigned char result;
int i;
xlog("TYPE_B_EVENT begin\n");
ReaderB_Initial();
SetCW(FUN_ENABLE);
result = ReaderB_Request(&PICC_B);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
return;
}
xlog("************* TYPE B CARD ************* \r\n");
// 打印ATQB信息
xlog("-> ATQB = ");
for(i=0; i<12; i++) xlog("%02X", PICC_B.ATQB[i]);
xlog("\r\n");
result = ReaderB_Attrib(&PICC_B);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
return;
}
xlog("-> ATTRIB = %02X\r\n", PICC_B.CID);
result = ReaderB_Get_SN(&PICC_B);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
return;
}
xlog("-> SN = ");
for(i=0; i<8; i++) xlog("%02X", PICC_B.SN[i]);
xlog("\r\n");
SetCW(FUN_DISABLE);
}
/**
* @brief 处理Type V (ISO/IEC 15693) 卡片事件。
* @details
* 该函数执行ISO/IEC 15693 Vicinity卡片的交互流程包括
* 1. 初始化读卡器以支持15693协议。
* 2. 打开RF场。
* 3. 发送Inventory命令寻卡并获取UID。
* 4. 发送Select命令选择卡片。
* 5. 示例性地对第4块进行写操作然后再读回校验。
* 6. 操作结束后关闭RF场。
* @return 无。
*/
void TYPE_V_EVENT(void)
{
unsigned char result, i;
xlog("TYPE_V_EVENT begin\n");
ReaderV_Initial();
SetCW(FUN_ENABLE);
result = ReaderV_Inventory(&PICC_V);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> ReaderV Inventory ERROR!\r\n");
return;
}
xlog("************* TYPE V CARD ************* \r\n");
xlog("UID=");
for (i = 0; i < 8; i++)
{
xlog("%02X", PICC_V.UID[i]);
}
xlog("\r\n");
result = ReaderV_Select(&PICC_V);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> ReaderV Select ERROR!\r\n");
return;
}
// 示例:写单个块
memcpy(PICC_V.BLOCK_DATA, "\x00\x00\x00\x00", 4);
result = ReaderV_WriteSingleBlock(4, &PICC_V);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> ReaderV WriteSingleBlock ERROR!\r\n");
return;
}
xlog("WriteSingleBlock SUCCESS\r\n");
// 示例:读单个块
result = ReaderV_ReadSingleBlock(4, &PICC_V);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> ReaderV ReadSingleBlock ERROR!\r\n");
return;
}
xlog("BLOCK DATA = %02X%02X%02X%02X \r\n", PICC_V.BLOCK_DATA[0], PICC_V.BLOCK_DATA[1], PICC_V.BLOCK_DATA[2], PICC_V.BLOCK_DATA[3]);
SetCW(FUN_DISABLE);
}
/**
* @brief 处理Type F (FeliCa) 卡片事件。
* @details
* 该函数执行FeliCa卡片的交互流程包括
* 1. 初始化读卡器以支持FeliCa协议。
* 2. 打开RF场。
* 3. 发送Inventory命令寻卡并获取UID。
* 4. 后续可以添加与FeliCa卡的数据交换命令。
* 5. 操作结束后关闭RF场。
* @note 当前实现仅包含寻卡部分。
* @return 无。
*/
void TYPE_F_EVENT(void)
{
unsigned char result, i;
xlog("TYPE_F_EVENT begin\n");
ReaderF_Initial();
SetCW(FUN_ENABLE);
result = ReaderF_Inventory(&PICC_F);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
return;
}
xlog("************* TYPE F CARD ************* \r\n");
xlog("->TYPE F UID = ");
for(i=0; i<8; i++) xlog("%02X", PICC_F.UID[i]);
xlog("\r\n");
SetCW(FUN_DISABLE);
}
/**
* @brief RFID模块的主任务函数。
* @details
* 利用定时器调用
* @return 无。
*/
void rfid_task_fuc(void)
{
unsigned char result, reg_data;
static u8 first_init = 0;
if(first_init == 0){
first_init = 1;
FM176XX_HardInit();
rfid_delay_ms(5); // 硬件初始化后增加一个短暂延时,确保芯片稳定
// 2. 复位 FM176XX 芯片
result = FM176XX_SoftReset();
if (result != SUCCESS)
{
xlog("FM176XX HardReset FAIL\r\n");
}
else
{
xlog("FM176XX HardReset SUCCESS\r\n");
}
rfid_delay_ms(10); // 复位后延时
}
// 3. 读取芯片版本号,确认通信是否正常
GetReg(REG_VERSION, &reg_data);
xlog("REG_VERSION = %02X\r\n", reg_data);
// TYPE_A_EVENT();
// TYPE_B_EVENT();
TYPE_V_EVENT();
// TYPE_F_EVENT();
}