/******************************************************************************************************** * @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. 根据卡片的SAK(Select 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, "\x11\x22\x33\x44", 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; // rfid_hal_init(); FM176XX_HardInit(); // 2. 复位 FM176XX 芯片 result = FM176XX_SoftReset(); if (result != SUCCESS) { xlog("FM176XX HardReset FAIL\r\n"); } else { xlog("FM176XX HardReset SUCCESS\r\n"); } } // 3. 读取芯片版本号,确认通信是否正常 GetReg(REG_VERSION, ®_data); xlog("REG_VERSION = %02X\r\n", reg_data); // TYPE_A_EVENT(); // TYPE_B_EVENT(); TYPE_V_EVENT(); // TYPE_F_EVENT(); }