NRF52832NFC读写
本文参考了nodic官网的问答。
nrf51822和nrf52832都是nordic公司生产的低功耗ble芯片。nrf52832是nrf51822的升级版,nrf52相比nrf51增加了nfc的功能。
但是官方给的固件中nfc的写功能被禁止了,也就是说如果使用官方给的库的话只能进行nfc的数据读取,而不能将数据写入的nrf52里面。这是个很大的限制,所以我下面将说明如何修改代码使nfc能进行写操作。
官方给的例程使用的是nfc_t2t_lib.h库文件,该库文件只留了一些接口给用户,所以使用起来还是比较麻烦的。在这里我使用的是hal_nfc_t2t.c和hal_nfc_t2t.h这两个文件。并且是在官方给的例程record_text的基础上进行修改的。
下面是具体的步骤:
步骤一:将使用nfc_t2t_lib.h库的函数代替成相应的hal_nfc_t2t.h库中的函数,首先在main文件中修改。
将:
- <code class="language-cpp"><span style="font-size:14px;">err_code = nfc_t2t_setup(nfc_callback, NULL);</span></code>
代换成:
err_code = hal_nfc_setup(nfc_callback, NULL);
相应的回调函数也要修改:
将:
static void nfc_callback(void * p_context, nfc_t2t_event_t event, const uint8_t * p_data, size_t data_length);
修改成:
static void nfc_callback(void * p_context, hal_nfc_event_t event, const uint8_t * p_data, size_t data_length);
即修改了第二个参数。
修改前:
修改后:
接下来将这两行代码删除:
接下来将
err_code = nfc_t2t_emulation_start();
代换为:
err_code = hal_nfc_start();
修改前:
修改后为:
全部修改后main函数为:
步骤二:在main.c文件中添加一个数组
-
static uint8_t Test_Memory_Type2[NFC_T2T_MAX_PAYLOAD_SIZE_RAW] = {
-
0x5F, 0xF6, 0x4C, 0x6D, // Internal 0-3
-
0x2F, 0xF4, 0xDA, 0x59, // Internal 4-7
-
0x58, 0x03, 0x00, 0x00, // Internal 8-9 | Lock0-1 // <-- makes the card
-
0xE1, 0x10, 0x6D, 0x00, // CC0-3 // <-- makes the
-
// page 4
-
0x03, 0x16, 0xC1, 0x01, // TLV Tag field, Length field, Value field
-
0x00, 0x00, 0x00, 0x0F, // NDEF Payload length 15
-
0x54, 0x02, 0x65, 0x6E, // NDEF Message Type : Text UTF8, "Hello World!"
-
0x48, 0x65, 0x6C, 0x6C, //
-
// page 8
-
0x6F, 0x20, 0x57, 0x6F,
-
0x72, 0x6C, 0x64, 0x21, //
-
0x00, 0x00, 0x00, 0x00,
-
0x00, 0x00, 0x00, 0x00,
-
};
步骤三:修改回调函数
-
static void nfc_callback(void * p_context, hal_nfc_event_t event, const uint8_t * p_data, size_t data_length)
-
{
-
uint8_t BNo = p_data[ 1];
-
( void)p_context;
-
uint8_t location;
-
switch (event)
-
{
-
case HAL_NFC_EVENT_FIELD_ON:
-
FLASH_BUFF_READ(&Test_Memory_Type2[ 16], 0, 80);
-
if(Test_Memory_Type2[ 16]== 0x03)
-
{
-
location=Test_Memory_Type2[ 17]+ 18 -16; //¸ù¾ÝurlµÄ³¤¶È¼ÆËãIDËùÔÚµÄλÖÃ
-
memcpy(&Test_Memory_Type2[location],DEVICE_ID, 16);
-
}
-
memcpy(&Test_Memory_Type2[ 10],cc0_3, 6); //ÿ´Î¸´ÖÆÊÇΪÁ˱£Ö¤cc0_3²»»á±»¸Ä±ä£¬·ñÔò¶ÁNFC»á³ö´í
-
break;
-
case HAL_NFC_EVENT_FIELD_OFF:
-
LEDS_OFF(BSP_LED_0_MASK);
-
break;
-
case HAL_NFC_EVENT_DATA_RECEIVED:
-
if (BNo< 252){ /* Max Block number */
-
hal_nfc_send(&Test_Memory_Type2[BNo* 4], 16);
-
}
-
else
-
/* hal_nfc_send(&Dymamic_Memory_Aera[0], 16); */
-
hal_send_ack_nack( 0x0); // NAck
-
break;
-
case HAL_NFC_EVENT_DATA_WRITE:
-
if (data_length== 6){ //NFCÿ´ÎÖ»ÄÜдһ¸ö¿é£¬¼´4¸ö×Ö½Ú¡£
-
uint8_t i, c;
-
for (i= 0;i< 4;i++) {
-
c = p_data[ 2+i];
-
Test_Memory_Type2[BNo* 4 + i] = c;
-
}
-
hal_send_ack_nack( 0xA); // Ack for write command
-
FLASH_BUFF_UPDATE(&Test_Memory_Type2[ 16], 0, 80);
-
}
-
else {
-
hal_send_ack_nack( 0x0); // NAck for write command : should be 0, 1, 4 or 5
-
}
-
default:
-
break;
-
}
-
}
修改后为:
同时需要在hal_nfc_t2t.h中的枚举类型hal_nfc_event_t中增加HAL_NFC_EVENT_DATA_WRITE变量。
步骤四:在hal_nfc_t2t.c中增加函数ret_code_t hal_send_ack_nack(uint8_t ack_nack_code)
-
ret_code_t hal_send_ack_nack( uint8_t ack_nack_code) {
-
static uint8_t Ack;
-
Ack = ack_nack_code;
-
-
nrf_nfct_event_clear(&NRF_NFCT->EVENTS_TXFRAMEEND);
-
-
NRF_NFCT->PACKETPTR = ( uint32_t)(&Ack);
-
NRF_NFCT->TXD.AMOUNT = 4;
-
-
uint32_t reg = 0;
-
/* reg |= (NFCT_TXD_FRAMECONFIG_PARITY_Parity << NFCT_TXD_FRAMECONFIG_PARITY_Pos); */
-
reg |= (NFCT_TXD_FRAMECONFIG_SOF_SoF << NFCT_TXD_FRAMECONFIG_SOF_Pos);
-
NRF_NFCT->TXD.FRAMECONFIG = reg;
-
NRF_NFCT->INTENSET = (NFCT_INTENSET_TXFRAMEEND_Enabled << NFCT_INTENSET_TXFRAMEEND_Pos);
-
NRF_NFCT->TASKS_STARTTX = 1;
-
-
return NRF_SUCCESS;
-
}
增加后为:
步骤五:将hal_nfc_t2t.c中的函数hal_nfc_send修改为:
-
ret_code_t hal_nfc_send( const uint8_t * p_data, size_t data_length)
-
{
-
if (data_length == 0)
-
{
-
return NRF_ERROR_DATA_SIZE;
-
}
-
/* Ignore previous TX END events, SW takes care only for data frames which tranmission is triggered in this function */
-
nrf_nfct_event_clear(&NRF_NFCT->EVENTS_TXFRAMEEND);
-
-
NRF_NFCT->PACKETPTR = ( uint32_t)(p_data);
-
NRF_NFCT->TXD.AMOUNT = (data_length << NFCT_TXD_AMOUNT_TXDATABYTES_Pos) & NFCT_TXD_AMOUNT_TXDATABYTES_Msk;
-
-
uint32_t reg = 0;
-
reg |= (NFCT_TXD_FRAMECONFIG_PARITY_Parity << NFCT_TXD_FRAMECONFIG_PARITY_Pos);
-
reg |= (NFCT_TXD_FRAMECONFIG_DISCARDMODE_DiscardStart << NFCT_TXD_FRAMECONFIG_DISCARDMODE_Pos);
-
reg |= (NFCT_TXD_FRAMECONFIG_SOF_SoF << NFCT_TXD_FRAMECONFIG_SOF_Pos);
-
reg |= (NFCT_TXD_FRAMECONFIG_CRCMODETX_CRC16TX << NFCT_TXD_FRAMECONFIG_CRCMODETX_Pos);
-
NRF_NFCT->TXD.FRAMECONFIG = reg;
-
-
NRF_NFCT->INTENSET = (NFCT_INTENSET_TXFRAMEEND_Enabled << NFCT_INTENSET_TXFRAMEEND_Pos);
-
NRF_NFCT->TASKS_STARTTX = 1;
-
-
// LOG_HAL_NFC("[NFC_HAL]: send");
-
uint8_t i;
-
for (i= 0;i<data_length;i++) {
-
// NRF_LOG_PRINTF(" %02X", *(data+i));
-
}
-
-
// NRF_LOG_PRINTF("\n");
-
return NRF_SUCCESS;
-
}
为:
步骤六:最后在hal_nfc_t2t.c中修改NFCT_IRQHandler(void)函数。
-
else if(m_nfc_rx_buffer[ 0] == T2T_WRITE_CMD)
-
{
-
if(m_nfc_lib_callback != NULL)
-
{
-
/* This callback should trigger transmission of READ Response */
-
m_nfc_lib_callback(m_nfc_lib_context,
-
HAL_NFC_EVENT_DATA_WRITE,
-
( void*)m_nfc_rx_buffer,
-
rx_data_size);
-
}
-
}
添加后为:
好啦,修改到这里就能实现nfc的数据读写了,具体需要实现什么可以根据自己的需求进行修改。
其中数组est_Memory_Type2是模拟nfc的内存,具体代表什么需要查看nfc方面的知识。
能力有限,欢迎纠错!
本文参考了nodic官网的问答。
nrf51822和nrf52832都是nordic公司生产的低功耗ble芯片。nrf52832是nrf51822的升级版,nrf52相比nrf51增加了nfc的功能。
但是官方给的固件中nfc的写功能被禁止了,也就是说如果使用官方给的库的话只能进行nfc的数据读取,而不能将数据写入的nrf52里面。这是个很大的限制,所以我下面将说明如何修改代码使nfc能进行写操作。
官方给的例程使用的是nfc_t2t_lib.h库文件,该库文件只留了一些接口给用户,所以使用起来还是比较麻烦的。在这里我使用的是hal_nfc_t2t.c和hal_nfc_t2t.h这两个文件。并且是在官方给的例程record_text的基础上进行修改的。
下面是具体的步骤:
步骤一:将使用nfc_t2t_lib.h库的函数代替成相应的hal_nfc_t2t.h库中的函数,首先在main文件中修改。
将:
- <code class="language-cpp"><span style="font-size:14px;">err_code = nfc_t2t_setup(nfc_callback, NULL);</span></code>
代换成:
err_code = hal_nfc_setup(nfc_callback, NULL);
相应的回调函数也要修改:
将:
static void nfc_callback(void * p_context, nfc_t2t_event_t event, const uint8_t * p_data, size_t data_length);
修改成:
static void nfc_callback(void * p_context, hal_nfc_event_t event, const uint8_t * p_data, size_t data_length);
即修改了第二个参数。
修改前:
修改后:
接下来将这两行代码删除:
接下来将
err_code = nfc_t2t_emulation_start();
代换为:
err_code = hal_nfc_start();
修改前:
修改后为:
全部修改后main函数为:
步骤二:在main.c文件中添加一个数组
-
static uint8_t Test_Memory_Type2[NFC_T2T_MAX_PAYLOAD_SIZE_RAW] = {
-
0x5F, 0xF6, 0x4C, 0x6D, // Internal 0-3
-
0x2F, 0xF4, 0xDA, 0x59, // Internal 4-7
-
0x58, 0x03, 0x00, 0x00, // Internal 8-9 | Lock0-1 // <-- makes the card
-
0xE1, 0x10, 0x6D, 0x00, // CC0-3 // <-- makes the
-
// page 4
-
0x03, 0x16, 0xC1, 0x01, // TLV Tag field, Length field, Value field
-
0x00, 0x00, 0x00, 0x0F, // NDEF Payload length 15
-
0x54, 0x02, 0x65, 0x6E, // NDEF Message Type : Text UTF8, "Hello World!"
-
0x48, 0x65, 0x6C, 0x6C, //
-
// page 8
-
0x6F, 0x20, 0x57, 0x6F,
-
0x72, 0x6C, 0x64, 0x21, //
-
0x00, 0x00, 0x00, 0x00,
-
0x00, 0x00, 0x00, 0x00,
-
};
步骤三:修改回调函数
-
static void nfc_callback(void * p_context, hal_nfc_event_t event, const uint8_t * p_data, size_t data_length)
-
{
-
uint8_t BNo = p_data[ 1];
-
( void)p_context;
-
uint8_t location;
-
switch (event)
-
{
-
case HAL_NFC_EVENT_FIELD_ON:
-
FLASH_BUFF_READ(&Test_Memory_Type2[ 16], 0, 80);
-
if(Test_Memory_Type2[ 16]== 0x03)
-
{
-
location=Test_Memory_Type2[ 17]+ 18 -16; //¸ù¾ÝurlµÄ³¤¶È¼ÆËãIDËùÔÚµÄλÖÃ
-
memcpy(&Test_Memory_Type2[location],DEVICE_ID, 16);
-
}
-
memcpy(&Test_Memory_Type2[ 10],cc0_3, 6); //ÿ´Î¸´ÖÆÊÇΪÁ˱£Ö¤cc0_3²»»á±»¸Ä±ä£¬·ñÔò¶ÁNFC»á³ö´í
-
break;
-
case HAL_NFC_EVENT_FIELD_OFF:
-
LEDS_OFF(BSP_LED_0_MASK);
-
break;
-
case HAL_NFC_EVENT_DATA_RECEIVED:
-
if (BNo< 252){ /* Max Block number */
-
hal_nfc_send(&Test_Memory_Type2[BNo* 4], 16);
-
}
-
else
-
/* hal_nfc_send(&Dymamic_Memory_Aera[0], 16); */
-
hal_send_ack_nack( 0x0); // NAck
-
break;
-
case HAL_NFC_EVENT_DATA_WRITE:
-
if (data_length== 6){ //NFCÿ´ÎÖ»ÄÜдһ¸ö¿é£¬¼´4¸ö×Ö½Ú¡£
-
uint8_t i, c;
-
for (i= 0;i< 4;i++) {
-
c = p_data[ 2+i];
-
Test_Memory_Type2[BNo* 4 + i] = c;
-
}
-
hal_send_ack_nack( 0xA); // Ack for write command
-
FLASH_BUFF_UPDATE(&Test_Memory_Type2[ 16], 0, 80);
-
}
-
else {
-
hal_send_ack_nack( 0x0); // NAck for write command : should be 0, 1, 4 or 5
-
}
-
default:
-
break;
-
}
-
}
修改后为:
同时需要在hal_nfc_t2t.h中的枚举类型hal_nfc_event_t中增加HAL_NFC_EVENT_DATA_WRITE变量。
步骤四:在hal_nfc_t2t.c中增加函数ret_code_t hal_send_ack_nack(uint8_t ack_nack_code)
-
ret_code_t hal_send_ack_nack( uint8_t ack_nack_code) {
-
static uint8_t Ack;
-
Ack = ack_nack_code;
-
-
nrf_nfct_event_clear(&NRF_NFCT->EVENTS_TXFRAMEEND);
-
-
NRF_NFCT->PACKETPTR = ( uint32_t)(&Ack);
-
NRF_NFCT->TXD.AMOUNT = 4;
-
-
uint32_t reg = 0;
-
/* reg |= (NFCT_TXD_FRAMECONFIG_PARITY_Parity << NFCT_TXD_FRAMECONFIG_PARITY_Pos); */
-
reg |= (NFCT_TXD_FRAMECONFIG_SOF_SoF << NFCT_TXD_FRAMECONFIG_SOF_Pos);
-
NRF_NFCT->TXD.FRAMECONFIG = reg;
-
NRF_NFCT->INTENSET = (NFCT_INTENSET_TXFRAMEEND_Enabled << NFCT_INTENSET_TXFRAMEEND_Pos);
-
NRF_NFCT->TASKS_STARTTX = 1;
-
-
return NRF_SUCCESS;
-
}
增加后为:
步骤五:将hal_nfc_t2t.c中的函数hal_nfc_send修改为:
-
ret_code_t hal_nfc_send( const uint8_t * p_data, size_t data_length)
-
{
-
if (data_length == 0)
-
{
-
return NRF_ERROR_DATA_SIZE;
-
}
-
/* Ignore previous TX END events, SW takes care only for data frames which tranmission is triggered in this function */
-
nrf_nfct_event_clear(&NRF_NFCT->EVENTS_TXFRAMEEND);
-
-
NRF_NFCT->PACKETPTR = ( uint32_t)(p_data);
-
NRF_NFCT->TXD.AMOUNT = (data_length << NFCT_TXD_AMOUNT_TXDATABYTES_Pos) & NFCT_TXD_AMOUNT_TXDATABYTES_Msk;
-
-
uint32_t reg = 0;
-
reg |= (NFCT_TXD_FRAMECONFIG_PARITY_Parity << NFCT_TXD_FRAMECONFIG_PARITY_Pos);
-
reg |= (NFCT_TXD_FRAMECONFIG_DISCARDMODE_DiscardStart << NFCT_TXD_FRAMECONFIG_DISCARDMODE_Pos);
-
reg |= (NFCT_TXD_FRAMECONFIG_SOF_SoF << NFCT_TXD_FRAMECONFIG_SOF_Pos);
-
reg |= (NFCT_TXD_FRAMECONFIG_CRCMODETX_CRC16TX << NFCT_TXD_FRAMECONFIG_CRCMODETX_Pos);
-
NRF_NFCT->TXD.FRAMECONFIG = reg;
-
-
NRF_NFCT->INTENSET = (NFCT_INTENSET_TXFRAMEEND_Enabled << NFCT_INTENSET_TXFRAMEEND_Pos);
-
NRF_NFCT->TASKS_STARTTX = 1;
-
-
// LOG_HAL_NFC("[NFC_HAL]: send");
-
uint8_t i;
-
for (i= 0;i<data_length;i++) {
-
// NRF_LOG_PRINTF(" %02X", *(data+i));
-
}
-
-
// NRF_LOG_PRINTF("\n");
-
return NRF_SUCCESS;
-
}
为:
步骤六:最后在hal_nfc_t2t.c中修改NFCT_IRQHandler(void)函数。
-
else if(m_nfc_rx_buffer[ 0] == T2T_WRITE_CMD)
-
{
-
if(m_nfc_lib_callback != NULL)
-
{
-
/* This callback should trigger transmission of READ Response */
-
m_nfc_lib_callback(m_nfc_lib_context,
-
HAL_NFC_EVENT_DATA_WRITE,
-
( void*)m_nfc_rx_buffer,
-
rx_data_size);
-
}
-
}
添加后为:
好啦,修改到这里就能实现nfc的数据读写了,具体需要实现什么可以根据自己的需求进行修改。
其中数组est_Memory_Type2是模拟nfc的内存,具体代表什么需要查看nfc方面的知识。
能力有限,欢迎纠错!