/******************************************************************************************************** * @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(5); 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; SetCommand(CMD_IDLE); SetReg(REG_TXDATANUM, 0x08); ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE); SetReg(REG_FIFODATA, 0x26); 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(10); GetReg(REG_ERROR, ®_data); if ((reg_data & 0x0F) != 0) return FAIL; GetReg(REG_FIFOLENGTH, ®_data); if (reg_data != 10) 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]); } 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; 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; }