基于 nRF SDK17.2,Nordic NFC 读写的实现。

Nordic 的 nRF52832 和 nRF52840 具有 NFC 的功能,官方提供 t2t_lib 和 t4t_lib 支持 NFC Type 2 tag 和 NFC Type 4 tag 类型的标签。其中 T2T 的库仅支持读卡,不支持写卡,T4T 的库支持读和写。

目前手头有个标签需要满足 Ntag213(T2T) 数据格式,并支持读写,查阅 Nordic 资料后发现他们不提供 T2T NFC 写的技术支持,并且不开源驱动调用部分的代码,只能自己写。参考 Nordic 论坛这篇博客后,决定抛弃 SDK 中 nfc_t2t_lib_gcc.a,编写一个 T2T 支持读写库。

以下为 Demo 详细部分:

一、前提

1、可以使用 SDK 的 examples\nfc\record_text 进行修改;

2、驱动为官方提供的 nrfx_nfct.c,需要使能的宏定义移植时参考 NFC 的例程。

二、修改 nrfx_nfct.c

1、nrfx_nfct_tx 函数添加以下代码:

nrf_nfct_tx_frame_config_set(NRF_NFCT_TX_FRAME_CONFIG_PARITY        | 
                                     NRF_NFCT_TX_FRAME_CONFIG_DISCARD_START |
                                     NRF_NFCT_TX_FRAME_CONFIG_SOF           |
                                     NRF_NFCT_TX_FRAME_CONFIG_CRC16);

修改前:

修改后: 

 

2、添加 ACK 回复函数,并在头文件 nrfx_nfct.h 中添加该函数

nrfx_err_t nrfx_nfct_tx_ack_nack(uint8_t code)
{
    static uint8_t Ack;
    Ack = code;

    nrfx_err_t err = NRFX_SUCCESS;

    NRFX_CRITICAL_SECTION_ENTER();

    /* In case when NFC frame transmission has already started, it returns an error. */
    if (NRFX_NFCT_EVT_ACTIVE(TXFRAMESTART))
    {
        err = NRFX_ERROR_BUSY;
    }
    else
    {
        /* In case when Tx operation was scheduled with delay, stop scheduled Tx operation. */
        *(volatile uint32_t *)0x40005010 = 0x01;

        nrf_nfct_rxtx_buffer_set(&Ack, 16);
        nrf_nfct_tx_bits_set(4);
        nrf_nfct_tx_frame_config_set(NRF_NFCT_TX_FRAME_CONFIG_SOF);

        nrfx_nfct_rxtx_int_enable(NRFX_NFCT_TX_INT_MASK);
        nrf_nfct_task_trigger(NRF_NFCT_TASK_STARTTX);
    }

    NRFX_CRITICAL_SECTION_EXIT();
    return err;
}

 三、编写 NFC 调用逻辑

这里我命名为 custom_nfc.c,头文件由你们自己定义啦,关于 NFC 的读写过程,命令码什么的参考 NFC 论坛 T2T 使用文档,详细代码如下:

#include <stdint.h>
#include "nrfx_nfct.h"

#define NFC_RX_BUFFER_SIZE          16u                                         /**< NFC Rx data buffer size */
#define T2T_READ_CMD                0x30u                                       /**< Type 2 Tag Read command identifier */
#define T2T_WRITE_CMD               0xA2u


#define ACK_CODE                    0x0Au
#define NACK_CODE                   0x00u


static uint8_t nfc_card_raw[180];
static uint8_t nfc_card_id[7] = {/*自定义*/};

static bool m_is_started;

static nrfx_nfct_config_t nfct_config;
static uint8_t rx_data[NFC_RX_BUFFER_SIZE];
static nrfx_nfct_data_desc_t rx_nfct_data_desc = {
    .p_data = rx_data,
    .data_size = NFC_RX_BUFFER_SIZE,
};

static nrfx_nfct_param_t nfct_param = {
    .id = NRFX_NFCT_PARAM_ID_NFCID1,
    .data.nfcid1.id_size = 7,
};

static void nfc_callback(nrfx_nfct_evt_t const * p_event)
{
    switch(p_event->evt_id)
    {
        case NRFX_NFCT_EVT_FIELD_DETECTED: {
            nrfx_nfct_state_force(NRF_NFCT_TASK_ACTIVATE);    
        } break;
        case NRFX_NFCT_EVT_RX_FRAMEEND: {
            nrfx_nfct_evt_rx_frameend_t const *rx_fram = &p_event->params.rx_frameend;
            uint8_t BNo = rx_fram->rx_data.p_data[1];
            if(rx_fram->rx_status == 0)
            {
                if(rx_fram->rx_data.p_data[0] == T2T_READ_CMD) //读命令
                {
                    if(BNo < 252)
                    {
                        rx_nfct_data_desc.p_data = &nfc_card_raw[BNo * 4];
                        nrfx_nfct_tx(&rx_nfct_data_desc, NRF_NFCT_FRAME_DELAY_MODE_WINDOWGRID);
                        NRF_LOG_HEXDUMP_INFO(rx_nfct_data_desc.p_data, rx_nfct_data_desc.data_size);
                    }
                    else
                    {
                        nrfx_nfct_tx_ack_nack(NACK_CODE);
                    }

                }
                else if(rx_fram->rx_data.p_data[0] == T2T_WRITE_CMD) //写命令
                {
                    if (rx_fram->rx_data.data_size == 6)
                    {
                        uint8_t i, c;
                        NRF_LOG_INFO("Ready to write :");
                        NRF_LOG_HEXDUMP_INFO(rx_nfct_data_desc.p_data, rx_nfct_data_desc.data_size);
                        for (i = 0; i < 4; i++) {
                            c = rx_fram->rx_data.p_data[2 + i];
                            nfc_card_raw[BNo * 4 + i] = c;
                        }
                        nrfx_nfct_tx_ack_nack(ACK_CODE); // Ack for write command
                    }
                    else
                    {
                        nrfx_nfct_tx_ack_nack(NACK_CODE); // NAck for write command : should be 0, 1, 4 or 5
                    }
                }
                else
                {
                    nrfx_nfct_init_substate_force(NRFX_NFCT_ACTIVE_STATE_SLEEP);
                }
            }
            else
            {
                nrfx_nfct_init_substate_force(NRFX_NFCT_ACTIVE_STATE_SLEEP);
            }
        } break;
        case NRFX_NFCT_EVT_SELECTED: {
            rx_nfct_data_desc.p_data = rx_data;
            nrfx_nfct_rx(&rx_nfct_data_desc);
        } break;
        case NRFX_NFCT_EVT_TX_FRAMEEND: {
            rx_nfct_data_desc.p_data = rx_data;
            nrfx_nfct_rx(&rx_nfct_data_desc);
        } break;
        default: break;
    }
}

void nfc_data_update(void *p_data, uint16_t len)
{
    memcpy(nfc_card_raw, p_data, len);
    if(m_is_started)
    {
        nrfx_nfct_disable();
    }
    nrfx_nfct_enable();
    m_is_started = true;
}

void nfc_init(void)
{
    nfct_config.rxtx_int_mask = 0x450;
    nfct_config.cb            = nfc_callback;
    nrfx_nfct_init(&nfct_config);
    nfct_param.data.nfcid1.p_id = nfc_card_id;
    nrfx_nfct_parameter_set(&nfct_param);
}

四、总结

该部分代码写的比较仓促,简单实现了 T2T 的读写功能,不排除有 BUG,若编写存在问题或者是使用起来存在 BUG,麻烦告诉我一声,感谢!

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值