Files
99_7018_lmx/apps/earphone/RFID/reader/rfid_main.c

361 lines
11 KiB
C
Raw Normal View History

2025-11-24 13:55:10 +08:00
/********************************************************************************************************
* @file rfid_main.c
* @brief RFID
* @details
* RFID读卡器的主要应用逻辑RFID模块Type A, B, V, F
*
* 51GPIOSPIUART的直接操作
* HAL `rfid_hal.h`
* 便STM32等不同平台上进行移植
*
* @author Kilo Code
* @date 2025-11-24
* @version 1.0
*
* @note
* - 使 `rfid_hal.h`
* - `rfid_task()`
* - `TYPE_A_EVENT`, `TYPE_B_EVENT`
* RFID协议的核心逻辑
********************************************************************************************************/
#include "../include/rfid_main.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "../include/READER.h"
#include "../include/READER_REG.h"
#include "../include/MIFARE.h"
#include "../include/NTAG.h"
#include "rfid_hal.h" // 引入硬件抽象层头文件
// 宏定义,用于调试信息输出。您需要实现 rfid_hal.h 中的 rfid_log_debug 函数
#define rfid_printf rfid_log_debug
/**
* @brief
* @param buf [out] 3
* @param num [in]
* @return
*/
static void IntToHex(unsigned char *buf, unsigned char num)
{
const unsigned char digits[] = "0123456789ABCDEF";
buf[0] = digits[(num >> 4) & 0x0F]; // 高4位
buf[1] = digits[num & 0x0F]; // 低4位
buf[2] = '\0';
}
/**
* @brief
* @param num [in]
* @return
*/
static void printHex(unsigned char num)
{
unsigned char buf[3];
IntToHex(buf, num);
rfid_printf((const char *)buf);
}
/**
* @brief Type A卡片事件
* @details
* ISO/IEC 14443 Type A卡片的完整激活流程
* 1. Type A协议
* 2. RF场
* 3. RequestAnticollision
* 4. SAKSelect AcknowledgeMifare, NTAG, CPU卡
* 5. RF场
* @return
*/
void TYPE_A_EVENT(void)
{
unsigned char result;
rfid_printf("TYPE_A_EVENT begin\n");
// 初始化读卡器为Type A模式
result = ReaderA_Initial();
if (result != SUCCESS)
{
rfid_printf("INIT_ERROR\r\n");
SetCW(DISABLE);
return;
}
// 打开RF场载波
result = SetCW(ENABLE);
if (result != SUCCESS)
{
rfid_printf("CW_ERROR\r\n");
SetCW(DISABLE);
return;
}
// 激活Type A卡片
result = ReaderA_CardActivate(&PICC_A);
if (result != SUCCESS)
{
// rfid_printf("ReaderA_CardActivate_ERROR\r\n");
SetCW(DISABLE);
return;
}
rfid_printf("************* TYPE A CARD ************* \r\n");
rfid_printf("-> ATQA = %02X%02X\r\n", PICC_A.ATQA[0], PICC_A.ATQA[1]);
if (PICC_A.UID_Length == 4)
{
rfid_printf("-> UID = %02X%02X%02X%02X\r\n", PICC_A.UID[0], PICC_A.UID[1], PICC_A.UID[2], PICC_A.UID[3]);
}
else if (PICC_A.UID_Length > 4) // 支持更长的UID
{
rfid_printf("-> UID = ");
for (int i = 0; i < PICC_A.UID_Length; i++)
{
rfid_printf("%02X", PICC_A.UID[i]);
}
rfid_printf("\r\n");
}
rfid_printf("-> SAK = %02X\r\n", PICC_A.SAK[0]);
// 根据SAK值判断卡片类型
if (PICC_A.SAK[0] == 0x08)
{
rfid_printf("************* Mifare CARD ************* \r\n");
result = MIFARE_CARD_EVENT();
}
else if ((PICC_A.SAK[0] == 0x28) || (PICC_A.SAK[0] == 0x20))
{
rfid_printf("************* CPU CARD ************* \r\n");
// result = CPU_CARD_EVENT(); // CPU卡处理函数暂未实现
}
else if (PICC_A.SAK[0] == 0x04)
{
rfid_printf("************* NTAG CARD ************* \r\n");
result = NTAG_EVENT();
}
SetCW(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;
rfid_printf("TYPE_B_EVENT begin\n");
ReaderB_Initial();
SetCW(ENABLE);
result = ReaderB_Request(&PICC_B);
if (result != SUCCESS)
{
SetCW(DISABLE);
return;
}
rfid_printf("************* TYPE B CARD ************* \r\n");
// 打印ATQB信息
rfid_printf("-> ATQB = ");
for(int i=0; i<12; i++) rfid_printf("%02X", PICC_B.ATQB[i]);
rfid_printf("\r\n");
result = ReaderB_Attrib(&PICC_B);
if (result != SUCCESS)
{
SetCW(DISABLE);
return;
}
rfid_printf("-> ATTRIB = %02X\r\n", PICC_B.CID);
result = ReaderB_Get_SN(&PICC_B);
if (result != SUCCESS)
{
SetCW(DISABLE);
return;
}
rfid_printf("-> SN = ");
for(int i=0; i<8; i++) rfid_printf("%02X", PICC_B.SN[i]);
rfid_printf("\r\n");
SetCW(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;
rfid_printf("TYPE_V_EVENT begin\n");
ReaderV_Initial();
SetCW(ENABLE);
result = ReaderV_Inventory(&PICC_V);
if (result != SUCCESS)
{
SetCW(DISABLE);
rfid_printf("-> ReaderV Inventory ERROR!\r\n");
return;
}
rfid_printf("************* TYPE V CARD ************* \r\n");
rfid_printf("UID=");
for (i = 0; i < 8; i++)
{
printHex(PICC_V.UID[i]);
}
rfid_printf("\r\n");
result = ReaderV_Select(&PICC_V);
if (result != SUCCESS)
{
SetCW(DISABLE);
rfid_printf("-> 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(DISABLE);
rfid_printf("-> ReaderV WriteSingleBlock ERROR!\r\n");
return;
}
rfid_printf("WriteSingleBlock SUCCESS\r\n");
// 示例:读单个块
result = ReaderV_ReadSingleBlock(4, &PICC_V);
if (result != SUCCESS)
{
SetCW(DISABLE);
rfid_printf("-> ReaderV ReadSingleBlock ERROR!\r\n");
return;
}
rfid_printf("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(DISABLE);
}
/**
* @brief Type F (FeliCa)
* @details
* FeliCa卡片的交互流程
* 1. FeliCa协议
* 2. RF场
* 3. Inventory命令寻卡并获取UID
* 4. FeliCa卡的数据交换命令
* 5. RF场
* @note TPDU命令交换被注释掉了 `CPU_TPDU`
* @return
*/
void TYPE_F_EVENT(void)
{
unsigned char result, i;
// unsigned char SendBuffer[255];
// unsigned char ReceiveBuffer[255];
// transmission_struct TPDU;
// TPDU.pSendBuffer = SendBuffer;
// TPDU.pReceiveBuffer = ReceiveBuffer;
rfid_printf("TYPE_F_EVENT begin\n");
ReaderF_Initial();
SetCW(ENABLE);
result = ReaderF_Inventory(&PICC_F);
if (result != SUCCESS)
{
SetCW(DISABLE);
return;
}
rfid_printf("************* TYPE F CARD ************* \r\n");
rfid_printf("->TYPE F UID = ");
for(i=0; i<8; i++) rfid_printf("%02X", PICC_F.UID[i]);
rfid_printf("\r\n");
// 此处省略了原代码中复杂的TPDU数据交换部分
// 因为它依赖于一个未定义的 CPU_TPDU 函数。
// 如果需要与CPU卡进行数据交换您需要实现相关的APDU指令封装和解析。
SetCW(DISABLE);
}
/**
* @brief RFID模块的主任务函数
* @details
* RFID芯片并进入一个无限循环来轮询不同类型的卡片
*
* 1. `rfid_hal_init()`
* 2. `FM176XX_HardReset()` RFID芯片
* 3.
* 4.
* @return
*/
void rfid_task(void)
{
unsigned char result, reg_data;
// 1. 初始化底层硬件 (SPI, GPIO, UART, Delay)
// 这个函数需要您在 rfid_hal.c 中实现
rfid_hal_init();
// 2. 硬复位 FM176XX 芯片
while (1)
{
result = FM176XX_HardReset();
if (result != SUCCESS)
{
rfid_printf("FM176XX HardReset FAIL\r\n");
rfid_delay_ms(1000); // 延时后重试
}
else
{
rfid_printf("FM176XX HardReset SUCCESS\r\n");
break;
}
}
// 3. 读取芯片版本号,确认通信是否正常
GetReg(REG_VERSION, &reg_data);
rfid_printf("REG_VERSION = %02X\r\n", reg_data);
// 4. 进入主循环,轮询不同类型的卡
while (1)
{
// 您可以根据需要取消注释来测试不同类型的卡
// TYPE_A_EVENT();
// TYPE_B_EVENT();
TYPE_V_EVENT(); // 当前默认只测试 Type V (15693) 卡
// TYPE_F_EVENT();
rfid_delay_ms(500); // 每次轮询后延时
}
}