CH584NFC读Ultrlight卡代码

前言:

针对CH584读Ultrlight卡做讲解。

Ultrlight卡的ATQA=0x0044,SAK=00。

#define SECTOR_1 4

/*********************************************************************
 * @fn      parse_ndef_text_record
 *
 * @brief   解析NDEF Text Record TLV数据
 *
 * @param   data - 包含NDEF数据的缓冲区
 * @param   length - 数据的长度
 *
 * @return  none
 */
void parse_ndef_text_record(uint8_t *data, uint16_t length)
{
    uint8_t *p = data;
    uint16_t index = 0;

    // 寻找 NDEF Message TLV (Type 0x03)
    while (index < length)
    {
        uint8_t t = p[index];
        uint8_t l = 0;
        uint16_t v_index = 0;

        if (t == 0x03) // NDEF Message TLV
        {
            index++;
            l = p[index];
            index++;
            v_index = index;

            PRINTF("Found NDEF Message TLV, Length: %d\n", l);

            // 解析 NDEF 记录
            if (l > 0)
            {
                uint8_t header = p[v_index];
                uint8_t type_len = p[v_index + 1];
                uint8_t payload_len = p[v_index + 2];
                uint8_t type_offset = 3;

                // 检查是否是 Text Record (Type 'T')
                if (type_len == 1 && p[v_index + type_offset] == 'T')
                {
                    PRINTF("Found NDEF Text Record\n");
                    uint8_t payload_offset = v_index + type_offset + type_len;
                    uint8_t status_byte = p[payload_offset];
                    uint8_t lang_code_len = status_byte & 0x3F;
                    
                    uint8_t text_offset = payload_offset + 1 + lang_code_len;
                    uint8_t text_len = payload_len - 1 - lang_code_len;

                    // 打印文本内容
                    PRINTF("Text: ");
                    for (int i = 0; i < text_len; i++)
                    {
                        PRINTF("%c ", p[text_offset + i]);
                    }
                    PRINTF("\n");
                }
            }
            index += l;
        }
        else if (t == 0x00) // Null TLV
        {
            index++;
        }
        else if (t == 0xFE) // Terminator TLV
        {
            PRINTF("Found Terminator TLV\n");
            break;
        }
        else // 其他类型的 TLV
        {
            index++;
            l = p[index];
            index += (1 + l);
        }
    }
}

#define PCD_READ_OVER_TIME              5

uint16_t PcdNTAG21xRead(uint8_t addr, uint8_t *pData)
{
    uint16_t res = PCD_COMMUNICATE_ERROR;
    nfca_pcd_controller_state_t status;

    nfca_pcd_set_wait_ms(PCD_READ_OVER_TIME);

    g_nfca_pcd_send_buf[0] = PICC_READ;
    g_nfca_pcd_send_buf[1] = addr;

    ISO14443AAppendCRCA((uint8_t *)g_nfca_pcd_send_buf, 2);

    ISO14443ACalOddParityBit((uint8_t *)g_nfca_pcd_send_buf, (uint8_t *)g_nfca_pcd_parity_buf, 4);

    if (nfca_pcd_communicate((4 * 8), NFCA_PCD_REC_MODE_NORMAL, 0) == 0)
    {
        status = nfca_pcd_wait_communicate_end();
        if(status == NFCA_PCD_CONTROLLER_STATE_DONE)
        {
            if (g_nfca_pcd_recv_bits == (18 * 9))
            {
                if (ISO14443ACheckOddParityBit(g_nfca_pcd_recv_buf, g_nfca_pcd_parity_buf, 18))
                {
                    if(ISO14443_CRCA(g_nfca_pcd_recv_buf, 18) == 0)
                    {
                        __MCPY(pData, g_nfca_pcd_recv_buf, g_nfca_pcd_recv_buf + 16);
                        res = PCD_NO_ERROR;
                    }
                    else
                    {
                        res = PCD_CRC_ERROR;
                    }
                }
                else
                {
                    res = PCD_ODD_PARITY_ERROR;
                }
            }
            else if (g_nfca_pcd_recv_bits == ACK_NAK_FRAME_SIZE)
            {
                res = PICC_NAK_HEAD | g_nfca_pcd_recv_buf[0];
            }
            else
            {
                res = PCD_UNKNOWN_ERROR;
            }
        }
    }

end:
    return res;
}

         if(res == 0x0044)   /* Mifare Ultrlight卡片 */
            {
                res = PcdAnticoll(PICC_ANTICOLL1);
                if (res == PCD_NO_ERROR)
                {
                    if(g_nfca_pcd_recv_buf[0] == 0x88)
                    {
                        picc_uid[0] = g_nfca_pcd_recv_buf[1];
                        picc_uid[1] = g_nfca_pcd_recv_buf[2];
                        picc_uid[2] = g_nfca_pcd_recv_buf[3];

                        res = PcdSelect(PICC_ANTICOLL1, g_nfca_pcd_recv_buf);
                        if (res == PCD_NO_ERROR)
                        {
                            res = PcdAnticoll(PICC_ANTICOLL2);
                            if (res == PCD_NO_ERROR)
                            {
                                picc_uid[3] = g_nfca_pcd_recv_buf[0];
                                picc_uid[4] = g_nfca_pcd_recv_buf[1];
                                picc_uid[5] = g_nfca_pcd_recv_buf[2];
                                picc_uid[6] = g_nfca_pcd_recv_buf[3];
                                PRINTF("Ultrlight uid: %02x %02x %02x %02x %02x %02x %02x\n", picc_uid[0], picc_uid[1],
                                        picc_uid[2], picc_uid[3], picc_uid[4], picc_uid[5], picc_uid[6]);

                                res = PcdSelect(PICC_ANTICOLL2, g_nfca_pcd_recv_buf);
                                if (res == PCD_NO_ERROR)
                                {
                                    /* 防冲突第二层选中成功 */
                                    PRINTF("SELECT OK, SAK: %02x\n", g_nfca_pcd_recv_buf[0]);
                                    mDelaymS(10);
                                    uint8_t sector_data[64];
                                    uint8_t block_count = 0;

                                    for (uint8_t i = SECTOR_1; i < SECTOR_1 + 8; i++)
                                    {
                                        // res = PcdRead(i);
                                        PcdNTAG21xRead(i, g_nfca_pcd_test_buf);
                                        if (res != PCD_NO_ERROR)
                                        {
                                            PRINTF("Read block %d ERR: 0x%x\n", i, res);
                                            goto nfc_halt_ul;
                                        }
                                        memcpy(&sector_data[block_count * 4], g_nfca_pcd_test_buf, 4);
                                        block_count++;
                                    }
                                    
                                    // 打印整个扇区的数据
                                    PRINTF("Sector %d Data:\n", SECTOR_1 / 4);
                                    for (uint8_t i = 0; i < sizeof(sector_data); i++)
                                    {
                                        PRINTF("%02x ", sector_data[i]);
                                        if ((i + 1) % 4 == 0)
                                        {
                                            PRINTF("\n");
                                        }
                                    }

                                    // 解析NDEF数据
                                    parse_ndef_text_record(sector_data, sizeof(sector_data));
nfc_halt_ul:
                                    PcdHalt();
                                }
                            }
                            else
                            {
                                PRINTF("ERROR ANTICOLL2\n");
                            }
                        }
                        else
                        {
                            PRINTF("CARD PcdSelect error: %d\n", res);
                        }
                    }
                    else
                    {
                        PRINTF("ERROR UID0\n");
                    }
                }
            }

读取数据内容和NDEF解析日志:

image

posted @ 2026-03-12 15:56  SweetTea_lllpc  阅读(66)  评论(0)    收藏  举报