/*********************************************************************************************** *DP1312EAÇý¶¯Îļþ ***********************************************************************************************/ #include #include "ql_rtos.h" #include "ql_application.h" #include "ql_audio.h" #include "ql_iic.h" #include "ql_gpio.h" #include "app_inc.h" #include "ql_fs.h" #include "DP1312EA_Config.h" #include "DP1312EA.h" unsigned char nfc_i2c_no = 1; //CI2C match to twsi1 int8 output_uuid[64]; #define NRSTPD_PIN GPIO_PIN_NO_86 // NTAG213 内存布局 #define NTAG213_PAGES 45 // 总页数 0-44 #define NTAG213_USER_START 4 // 用户数据起始页 #define NTAG213_USER_END 39 // 用户数据结束页(共36页,144字节) #define NTAG213_UID_PAGES 0 // UID 在第0-1页(7字节UID + 1字节校验) extern int g_testmode; extern int g_nfc_bind_status; /*********************************************************************************************** *DP1312EA¼ĴæÆ÷ָ¶¨λÖÃλ ***********************************************************************************************/ void DP1312EA_SetBitMask(u8 reg,u8 mask) { u8 tmp = DP1312EA_ReadRawRC(reg); DP1312EA_WriteRawRC(reg,tmp | mask); } /*********************************************************************************************** *DP1312EA¼ĴæÆ÷ָ¶¨λ¸´λ ***********************************************************************************************/ void DP1312EA_ClearBitMask(uint8_t reg,uint8_t mask) { u8 tmp = DP1312EA_ReadRawRC(reg); DP1312EA_WriteRawRC(reg, tmp & ~mask); } void DP1312EA_WriteRawRC(uint8_t Address, uint8_t value) { ql_i2c_write(nfc_i2c_no, 0x50>>1, Address, &value, 1); } u8 DP1312EA_ReadRawRC(uint8_t Address) { u8 ucResult=0; ql_i2c_read(nfc_i2c_no, 0x50>>1, Address, &ucResult, 1); return ucResult; } void DP1312EA_WriteFIFO(uint8_t *data, uint8_t len) { for(uint8_t i = 0; i < len; i++) { DP1312EA_WriteRawRC(FIFODataReg,data[i]); } } void DP1312EA_ReadFIFO(uint8_t *buf, uint8_t len) { for(uint8_t i = 0; i < len; i++) { buf[i] = DP1312EA_ReadRawRC(FIFODataReg); } } void Check_Chip(void) { u8 temp;; temp=DP1312EA_ReadRawRC(VersionReg); if(temp==0x82) { printf("\r\nDP1312EA is OK!"); } else { printf("\r\nError!"); } } void DP1312EA_Enable(void) { ql_gpio_set_level(NRSTPD_PIN,PIN_LEVEL_LOW); ql_rtos_task_sleep_ms(2); } void DP1312EA_Disable(void) { ql_gpio_set_level(NRSTPD_PIN,PIN_LEVEL_HIGH); ql_rtos_task_sleep_ms(2); } void DP1312EA_Reset(void) { unsigned int iRet=0; unsigned int fastmode = 0; #if 1 ql_gpio_init(NRSTPD_PIN,PIN_DIRECTION_OUT,PIN_PULL_DISABLE,PIN_LEVEL_LOW); ql_gpio_set_level(NRSTPD_PIN,PIN_LEVEL_LOW); ql_rtos_task_sleep_ms(1); ql_gpio_set_level(NRSTPD_PIN,PIN_LEVEL_HIGH); ql_rtos_task_sleep_ms(2); ql_gpio_set_level(NRSTPD_PIN,PIN_LEVEL_LOW); ql_rtos_task_sleep_ms(1); #endif // //delay 500us Çë¿ͻ§ȷÈÏdelay_usº¯ÊýÑÓʱ׼ȷ¡£ // DP1312EA_WriteRawRC(CommandReg,DP1312EA_RESETPHASE);//Èí¸´λ // delay_ms(5); ql_i2c_init(nfc_i2c_no, fastmode); } void DP1312EA_FieldOn(void) { u8 n; n = DP1312EA_ReadRawRC(TxControlReg); if (!(n & 0x03)) DP1312EA_WriteRawRC(TxControlReg, n|0x03); } void DP1312EA_FieldOff(void) { DP1312EA_ClearBitMask(TxControlReg, 0x03); } /********************************************************************************************************** *º¯ÊýÃû³ƣºs8 DP1312EA_PcdComTransceive(struct TranSciveBuffer *pi) *¹¦ÄÜÃèÊö£º ÃüÁËͺ¯Êý£¬¸÷Öֿ¨ͨÓᣠ*ÊäÈë²ÎÊý£º pi£ºÃüÁîºÍÊý¾ÝָÕ룻 *·µ»زÎÊý£º MI_OK£º³ɹ¦£» other£ºʧ°ܣ» *ÆäËüÊä³ö£º ÎÞ **********************************************************************************************************/ s8 DP1312EA_PcdComTransceive(struct TranSciveBuffer *pi) { s8 status = MI_ERR; u8 irqEn,waitFor,n,lastBits; u16 i; switch (pi->MfCommand) { case DP1312EA_AUTHENT: irqEn = 0x12; waitFor = 0x10; break; case DP1312EA_TRANSCEIVE: irqEn = 0x77; waitFor = 0x30; break; default: break; } DP1312EA_WriteRawRC(CommandReg,DP1312EA_IDLE); //01h DP1312EA_SetBitMask(FIFOLevelReg,0x80); //0ah, //FlushFIFO DP1312EA_WriteRawRC(ComIrqReg,0x7F); //04h for (i=0; iMfLength; i++) DP1312EA_WriteRawRC(FIFODataReg, pi->MfData [i]); //09h DP1312EA_WriteRawRC(CommandReg, pi->MfCommand); //01h if (pi->MfCommand == DP1312EA_TRANSCEIVE) DP1312EA_SetBitMask(BitFramingReg,0x80); //StartSend // for(i = 500;i>0;i--) { n = DP1312EA_ReadRawRC(ComIrqReg); //04h if((n&irqEn&0x01)||(n&waitFor)) break; //timerirq idleirq rxirq } DP1312EA_ClearBitMask(BitFramingReg,0x80); //0dh //StartSend if (n&waitFor) //IdleIRq { if(DP1312EA_ReadRawRC(ErrorReg)&0x1B) //06h status = MI_ERR; else { status = MI_OK; if (pi->MfCommand == DP1312EA_TRANSCEIVE) { n = DP1312EA_ReadRawRC(FIFOLevelReg); //0ah lastBits = DP1312EA_ReadRawRC(ControlReg) & 0x07; //0ch if (lastBits) pi->MfLength = (n-1)*8 + lastBits; else pi->MfLength = n*8; if (n == 0) n = 1; if (n > MAXRLEN) n = MAXRLEN; for (i=0; iMfData[i] = DP1312EA_ReadRawRC(FIFODataReg); //09h } } } else if (n & irqEn & 0x01) //TimerIRq { status = MI_NOTAGERR; } else if (!(DP1312EA_ReadRawRC(ErrorReg)&0x1B)) { //temp = DP1312EA_ReadRawRC(ErrorReg); status = MI_ACCESSTIMEOUT; } DP1312EA_SetBitMask(ControlReg,0x80); // stop timer now DP1312EA_WriteRawRC(CommandReg,DP1312EA_IDLE); //01h return status; } // 将十六进制数组转换为十六进制字符串(如 0x48 -> "48") void hex_array_to_hex_string(unsigned char *hex_array, int len, char *output) { for (int i = 0; i < len; i++) { // 每个字节转为2位十六进制字符 sprintf(output + i * 2, "%02X", hex_array[i]); } output[len * 2] = '\0'; // 结尾符 } /********************************************************************************************************** * 函数名称:s8 Read_NTAG213(u8 *uid_buf, u8 *data_buf, u16 *data_len) * 功能描述:读取 NTAG213 标签的 UID 和所有用户数据 * 输入参数:无 * 输出参数: * uid_buf - 返回7字节UID * data_buf - 返回用户数据(144字节),调用者需分配足够空间 * data_len - 返回实际读取的数据长度 * 返回值:MI_OK - 成功,其他 - 失败 **********************************************************************************************************/ s8 Read_NTAG213(u8 *uid_buf, u8 *data_buf, u16 *data_len) { s8 status; u8 atqa[2]; u8 uid[12] = {0}; // 临时存储UID(可能8字节或4字节) u8 ulen; u8 sak; //u8 page_data[16]; // MfulRead一次读4页(16字节) //u8 read_page; // u16 offset = 0; *data_len = 0; // 1. 激活卡片(寻卡 + 防冲突 + 选卡) DP1312EA_Reset(); ql_rtos_task_sleep_ms(1); status = DP1312EA_PcdActivateA(atqa, uid, &ulen, &sak); DP1312EA_Disable(); if(status != MI_OK) { // printf("Activate failed: %d\n", status); return status; } // 2. 判断是否为 NTAG213(或兼容的MIFARE Ultralight系列) // NTAG213 特征:SAK = 0x00, ATQA = 0x0044 或 0x0004 // 且 UID 长度为 7 字节(ulen 可能为 8,表示级联) #if 0 if(sak != 0x00) { printf("Not a NTAG213/Ultralight card! SAK=0x%02X\n", sak); return MI_ERR; // 不是NTAG类型 } #endif // 提取7字节UID(NTAG213是7字节UID) if(ulen == 8) { // 两级联,跳过第一个字节的级联标记0x88 memcpy(uid_buf, &uid[1], 7); hex_array_to_hex_string(uid_buf, 7, output_uuid); } else if(ulen == 4) { // 可能是Ultralight C(4字节UID)或异常 memcpy(uid_buf, uid, 4); printf("Warning: 4-byte UID, may be Ultralight C\n"); hex_array_to_hex_string(uid_buf, 4, output_uuid); } else { printf("Unknown UID length: %d\n", ulen); return MI_ERR; } printf("uid_buf read:%s\r\n", output_uuid); if(g_testmode==0){ if(g_nfc_bind_status==1){ handle_nfc_bind(output_uuid); g_nfc_bind_status = 0; }else{ //nfc 触发流程 然后音频播放完成 再去触发录音 -> vad_leave_message handle_nfc_trigger(output_uuid); } } #if 0 printf("NTAG213 detected, UID: "); for(int i=0; i<7; i++) printf("%02X", uid_buf[i]); printf("\n"); printf("ATQA: %02X%02X, SAK: %02X\n", atqa[1], atqa[0], sak); // 3. 读取所有数据页(0-43,共44页,但通常我们读到39或43) // 注意:DP1312EA_PcdMfulRead 使用 PICC_READ(0x30),一次读4页(16字节) printf("Reading NTAG213 memory...\n"); for(read_page = 0; read_page < NTAG213_PAGES; read_page += 4) { status = DP1312EA_PcdMfulRead(read_page, page_data); if(status != MI_OK) { printf("Read page %d failed: %d\n", read_page, status); break; // 读取失败,可能是到了末尾或卡片移开 } // 将读取的16字节(4页)复制到用户缓冲区 // 注意:不要超过缓冲区大小 if(offset + 16 <= 180) // NTAG213总容量180字节 { memcpy(&data_buf[offset], page_data, 16); offset += 16; } // 打印当前4页的数据 printf("Page %02d-%02d: ", read_page, read_page+3); for(int i=0; i<16; i++) { printf("%02X ", page_data[i]); if(i==3 || i==7 || i==11) printf("| "); } printf("\n"); } *data_len = offset; // 4. 解析 Capability Container(第3页,偏移12-15字节) // CC格式:E1 10 12 00( magic, version, size, read/write access) if(*data_len >= 16) { u8 *cc = &data_buf[12]; // 第3页(偏移12) printf("Capability Container (Page 3): %02X %02X %02X %02X\n", cc[0], cc[1], cc[2], cc[3]); if(cc[0] == 0xE1) { printf(" Magic Number: 0xE1 (NFC Forum Tag)\n"); printf(" Version: %02X\n", cc[1]); printf(" Size: %02X (%d bytes)\n", cc[2], cc[2]*8); // 0x12 = 144 bytes } } #endif return MI_OK; } /********************************************************************************************************** * 函数名称:void Test_NTAG213(void) * 功能描述:测试读取NTAG213并解析NDEF消息(如果有) **********************************************************************************************************/ s8 Test_NTAG213(void) { u8 uid[7]; u8 ntag_data[180]; // NTAG213总容量 u16 data_len; s8 status; // printf("\n=== NTAG213 Read Test ===\n"); status = Read_NTAG213(uid, ntag_data, &data_len); if(status == MI_OK) { printf("Read NTAG213 Success\n"); #if 0 printf("\nRead complete! Total %d bytes\n", data_len); // 解析用户数据区(Page 4-39) // 简单的NDEF检测:查找0x03(NDEF消息TLV起始) printf("\nUser data area (Page 4-39):\n"); for(int i=16; i