- 数据传输:NFC 标签可以存储和传输各种类型的数据,例如文本信息、URL、联系人信息、地理位置等。通过与支持 NFC 功能的设备(如智能手机、平板电脑等)进行触碰,用户可以轻松地获取标签上的数据,实现快速的信息交换和传输。
- 应用启动:NFC 标签可以配置为触发特定的操作或启动应用程序。例如,在一张 NFC 标签上配置一个任务,当用户触碰该标签时,自动打开指定的应用程序或执行特定的操作。这可以方便地实现一键连接、快速导航等功能。
- 门禁和支付:NFC 标签可以用于门禁系统和支付系统,使得用户可以通过刷标签的方式快速进入某个区域或进行支付。这种方式比传统的刷卡、输入密码或扫描二维码更加方便和高效。
- 电子票务:NFC 标签可以用于电子票务系统,例如电影票、公交卡、火车票等。用户可以通过触碰 NFC 标签,快速验证并使用电子票务,避免了纸质票据的使用和管理。
- 产品认证和防伪:NFC 标签可以用于产品的认证和防伪。通过在产品上附加 NFC 标签,在用户购买时可以使用支持 NFC 的设备来验证产品的真伪和合法性。这对于一些高价值、易伪造的产品尤为重要。
- 互动体验:NFC 标签可以用于增强用户的互动体验。例如,在博物馆或展览中,通过触碰 NFC 标签,用户可以获取更多的展品信息、导览解说、音频、视频等内容,提升参观者的体验和知识获取效果。
- nRF7002 DK 是 nRF7002 和 nRF7001 Wi-Fi 6 协同 IC 的开发套件。它包含在单个板上开始开发所需的一切。DK 采用 nRF5340 多协议系统级芯片(SoC) 作为 nRF7002 的主机处理器。该DK 支持低功耗 Wi-Fi 应用的开发,并支持 Wi-Fi 6 功能,如 OFDMA、波束成形和目标唤醒时间。nRF7002 是一款 Wi-Fi 6 协同 IC,提供无缝连接和基于 Wi-Fi 的定位(本地 Wi-Fi 集线器的 SSID 嗅探)。它旨在与Nordic现有的nRF52®和nRF53®系列蓝牙系统级芯片(SoC)以及nRF91®系列蜂窝物联网系统级封装(SiP)一起使用。nRF7002 还可以与非Nordic主机设备结合使用。
- nRF7002是Nordic独特Wi-Fi产品组合中的第一款设备,它将与Nordic现有的超低功耗技术无缝结合。Nordic 将其数十年的超低功耗无线物联网和硅设计专业知识带到 Wi-Fi 中。Wi-Fi 6 为物联网应用带来了更多优势,包括进一步提高效率,支持长寿命的电池供电 Wi-Fi 操作。
- nRF7002借助 Wi-Fi 6,Nordic 支持用于 Matter 的所有无线协议、用于调试的蓝牙 BLE、用于低功耗网状网络的 Thread 以及用于高吞吐量的 Wi-Fi。Matter是苹果、亚马逊、谷歌、Nordic、三星和消费者物联网中数百家其他公司倡导的协议。
- 支持板载J-link调试,使用自家的nRF5340芯片,有正版的license。
- 用于nRF7002双频带Wi-Fi 6配套IC的开发套件
- nRF5340 SoC主机器件
- Wi-Fi 6 (IEEE 802.11 a/b/g/n/ac/ax)、蓝牙低功耗 (LE)、蓝牙网状网络、802.15.4、Thread、Zigbee®、ANT、2.4GHz专有和NFC无线协议支持
- 2.4GHz、5GHz芯片和NFC天线
- SWF射频连接器
- SEGGER J-Link板载编程器/调试器
- 用户可编程LED (2x) 和按钮 (2x)
- 用于测量功耗的引脚
- 来自USB、外部或锂聚合物电池的2.9V至5.0V电源
- Arduino连接器
//项目的一些配置文件、参数介绍
#prj.conf : nRF Connect SDK 项目中的一个配置文件,可用于设置各种编译选项和系统参数,以满足应用程序的需求。在 prj.conf 文件中,可以设置以下选项:
#CONFIG_NCS_SAMPLES_DEFAULTS=y:该参数用于启用 nRF Connect SDK (NCS) 示例的默认设置。当设置为 "y" 时,编译系统将使用示例程序的默认配置,以便快速创建和构建示例应用程序。
#CONFIG_REBOOT=y:该参数用于启用系统重启功能。当设置为 "y" 时,系统可以通过调用适当的函数来执行软件重启操作。
#CONFIG_DK_LIBRARY=y:该参数用于启用开发套件 (Development Kit, DK) 库的支持。当设置为 "y" 时,编译系统将包括 DK 库,并允许您在应用程序中使用与开发套件配套的功能。
#CONFIG_NFC_T2T_NRFXLIB=y:该参数用于启用 NFC 读写器 (Tag) 支持的 Nordic nRF5x 原生库 (nrfxlib)。当设置为 "y" 时,编译系统将包括相关的 nrfxlib 库,并允许您在应用程序中使用与 NFC 标签通信相关的功能。
#CONFIG_NFC_NDEF=y:该参数用于启用 NFC NDEF (NFC Data Exchange Format) 功能。NDEF 是一种定义了在 NFC 设备之间传输数据的标准格式。当设置为 "y" 时,编译系统将启用 NDEF 相关的功能和接口。
#CONFIG_NFC_NDEF_MSG=y:该参数用于启用 NFC NDEF 消息的支持。NDEF 消息是一种结构化的数据容器,可用于在 NFC 设备之间传输数据。当设置为 "y" 时,编译系统将包括 NDEF 消息的相关功能和接口。
#CONFIG_NFC_NDEF_RECORD=y:该参数用于启用 NFC NDEF 记录的支持。NDEF 记录是 NDEF 消息的基本组成部分,用于包含特定类型的数据。当设置为 "y" 时,编译系统将包括 NDEF 记录的相关功能和接口。
#CONFIG_NFC_NDEF_TEXT_RECORD=y:该参数用于启用 NFC NDEF 文本记录的支持。NDEF 文本记录是一种特定类型的 NDEF 记录,用于包含文本数据。当设置为 "y" 时,编译系统将包括 NDEF 文本记录的相关功能和接口。
$sample.yaml 是 Zephyr 操作系统中的一个示例配置文件,可以用作其他应用程序的参考。在 sample.yaml 文件中,可以设置以下选项:
$board:设置目标硬件板卡的名称和版本号。
$kernel:设置内核配置选项,例如中断优先级、栈大小等。
$device-tree:设置设备树配置选项,例如硬件资源分配、外设驱动等。
$applications:设置应用程序的编译选项和参数。
Kconfig 是一个基于菜单式界面的配置系统,用于在 nRF Connect SDK 项目中手动配置某些选项和参数。在 Kconfig 中,用户可以选择需要的配置选项,并进行配置和编译,以生成符合需求的应用程序。例如,在 Kconfig 中,用户可以选择是否启用蓝牙功能、USB 功能、NFC 功能等。
CMakeLists.txt 是一个 CMake 编译系统的配置文件,用于定义编译过程中所需的相关参数和选项。在 CMakeLists.txt 文件中,可以设置编译选项、链接库、依赖关系等,并按照目标编译系统的不同,生成适应性强的代码。
prj.conf 、sample.yaml 、Kconfig 和 CMakeLists.txt 等是 nRF Connect SDK 项目中常用的一些配置文件,用于设置和管理项目中的各种选项和参数,并根据需要进行相应的配置和编译操作。这些文件可以提高项目开发的效率和灵活性,帮助用户快速生成符合需求的应用程序
要实现这个NFC项目,可以按照以下思路进行:
-
硬件设置:首先需要利用板卡上的按钮1和按钮2可编程。还有两个LED,并能够通过代码控制。
-
NFC模拟功能初始化:在程序启动时,需要对NFC模拟功能进行初始化设置,包括设置NFC的工作模式、启动NFC模拟功能和设置LED指示灯的初始状态。
-
编写NFC、按钮事件处理函数:创建一个按钮事件处理函数,用于处理按钮的状态变化。在函数内部,定义静态全局变量用于保存NFC工作状态和信息索引。创建一个NFC事件处理函数,用于处理NFC感应指示。
-
实现按钮1的功能切换:在按钮事件处理函数中,检测到按钮1被按下后,首先停止NFC模拟功能。然后根据定义的全局变量值,切换NFC工作状态,并加载对应的应用程序或文本信息。根据不同的NFC工作状态,启动NFC模拟功能并设置LED指示灯的状态。最后打印NFC工作模式切换的信息。
-
实现按钮2的内容切换:在按钮事件处理函数中,检测到按钮2被按下后,首先停止NFC模拟功能。根据当前的NFC工作状态,更新相应的信息索引。根据不同的信息索引,加载对应的应用程序或文本信息。启动NFC模拟功能并设置LED指示灯的状态。当按钮2连续按下时,根据索引顺序依次切换内容,直到最后一个内容再次按下时,切换到第一个内容。
////“感谢硬禾学堂以及德捷电子 以及nordic公司 希望funpack越办越好”字符串使用UTF-8编码
static const uint8_t text_record_2[] = {
0xE6, 0x84, 0x9F, 0xE8, 0xB0, 0xA2, 0xE7, 0xA1, 0xAC, 0xE7, 0xA6, 0xBE, 0xE5, 0xAD, 0xA6,
0xE5, 0xA0, 0x82, 0xE4, 0xBB, 0xA5, 0xE5, 0x8F, 0x8A, 0xE5, 0xBE, 0xB7, 0xE6, 0x8D, 0xB7,
0xE7, 0x94, 0xB5, 0xE5, 0xAD, 0x90, 0x20, 0xE4, 0xBB, 0xA5, 0xE5, 0x8F, 0x8A, 0x6E, 0x6F,
0x72, 0x64, 0x69, 0x63, 0xE5, 0x85, 0xAC, 0xE5, 0x8F, 0xB8, 0x20, 0xE5, 0xB8, 0x8C, 0xE6,
0x9C, 0x9B, 0x66, 0x75, 0x6E, 0x70, 0x61, 0x63, 0x6B, 0xE8, 0xB6, 0x8A, 0xE5, 0x8A, 0x9E,
0xE8, 0xB6, 0x8A, 0xE5, 0xA5, 0xBD
};
//\x025A48
static const uint8_t text_encode_2[] = {'Z', 'H'}; //\x5A48
//defiene apk packages information
static const uint8_t android_pkg_name_1[] = {
't', 'v', '.', 'd', 'a', 'n', 'm', 'a', 'k', 'u', '.', 'b', 'i', 'l', 'i'};
static const uint8_t android_pkg_name_2[] = {
'c','o','m','.','z','h','i','h','u','.','a','n','d','r','o','i','d'};
static const uint8_t android_pkg_name_3[] = {
'c','o','m','.','t','e','n','c','e','n','t','.','q','q','m','u','s','i','c'};
//存储NEDF信息的buffer
static uint8_t ndef_msg_buf_1[NDEF_MSG_BUF_SIZE];
static uint8_t ndef_msg_buf_2[NDEF_MSG_BUF_SIZE];
static uint8_t ndef_app_buf_1[NDEF_MSG_BUF_SIZE];
static uint8_t ndef_app_buf_2[NDEF_MSG_BUF_SIZE];
static uint8_t ndef_app_buf_3[NDEF_MSG_BUF_SIZE];
//NFC事件回调函数。
//当NFC发现附近场强后,它会打开一个LED,当NFC场强消失后,它会关闭该LED。
static void nfc_callback(void *context,
nfc_t2t_event_t event,
const uint8_t *data,
size_t data_length)
{
ARG_UNUSED(context);
ARG_UNUSED(data);
ARG_UNUSED(data_length);
switch (event) {
case NFC_T2T_EVENT_FIELD_ON:
dk_set_led_on(NFC_FIELD_LED);
break;
case NFC_T2T_EVENT_FIELD_OFF:
dk_set_led_off(NFC_FIELD_LED);
break;
default:
break;
}
}
定义一个按键事件回调函数
按下板卡上的按键后,触发回调函数,该函数用于处理按钮的状态变化。在函数内部,定义了三个静态全局变量nfc_state
、app_info_index
和text_info_index
,用于保存NFC工作状态和相关信息的索引。
板卡上有 button_1 和 button_2 两个可编程按键,利用这两个按键实现NFC功能、内容切换的操作。
按钮1用于切换NFC的不同功能。 当按钮1被按下时,首先会停止NFC模拟功能。然后切换NFC工作状态nfc_state
(在0和1之间切换),nfc_state=0
对应 文本信息读取状态 ,nfc_state=1
对应 跳转相关APP功能。 根据不同的NFC工作状态,分别加载对应的应用程序或文本信息,并启动NFC模拟功能以及设置LED指示灯状态。同时,会打印出NFC工作模式切换的信息。
按钮2用于切换当前功能下的不同内容。 当按钮2被按下时,首先会停止NFC模拟功能,然后根据当前的NFC工作状态(0或1),更新相应的信息索引app_info_index
表示APP信息的索引, text_info_index
表示文本信息的索引。根据不同的信息索引,加载对应的应用程序或文本信息,并启动NFC模拟功能以及设置LED指示灯状态。一直按 button2 根据顺序切换内容,到最后一个内容时再按会切换到第一个内容。
整体功能上,该函数实现了根据按钮状态切换NFC工作模式,并加载相应的应用程序或文本信息。
/**
* @typedef button_handler_t
* @brief Callback that is executed when a button state change is detected.
*
* @param button Bitmask of button states.
* @param has_changed Bitmask that shows which buttons have changed.
*/
static int my_button_handler(uint32_t button, uint32_t has_changed)
{
// 在这里处理按钮事件
// 定义全局变量来保存NFC工作状态和信息索引
static int nfc_state = 0;
static int app_info_index = 0;
static int text_info_index = 0;
uint32_t button_state = button & has_changed;
// button_state 参数表示当前按钮状态
if (button_state & DK_BTN1_MSK) {
// 按钮1被按下
// 切换NFC工作状态
nfc_t2t_emulation_stop();
nfc_state = (nfc_state == 0) ? 1 : 0;
if (nfc_state == 1) {
// 打开App
load_app1_nfc_payload();
nfc_t2t_emulation_start();
dk_set_led_on(NFC_MODE_LED);
printk("NFC mode switch to APP\n");
} else if (nfc_state == 0) {
// 读取信息
load_text1_nfc_payload();
nfc_t2t_emulation_start();
dk_set_led_off(NFC_MODE_LED);
printk("NFC mode switch to TEXT\n");
}
}
if (button_state & DK_BTN2_MSK) {
// 按钮2被按下
// int err = 0;
nfc_t2t_emulation_stop();
if (nfc_state == 1){
if (app_info_index + 1 < APP_MSG_COUNT) {
app_info_index++;
} else {
app_info_index = 0;
}
switch (app_info_index)
{
case 0:
load_app1_nfc_payload();
nfc_t2t_emulation_start();
dk_set_led_on(NFC_MODE_LED);
break;
case 1:
load_app2_nfc_payload();
nfc_t2t_emulation_start();
dk_set_led_on(NFC_MODE_LED);
break;
case 2:
load_app3_nfc_payload();
nfc_t2t_emulation_start();
dk_set_led_on(NFC_MODE_LED);
break;
default:
break;
}
}else if (nfc_state == 0){
if (text_info_index + 1 < TEXT_MSG_COUNT) {
text_info_index++;
} else {
text_info_index = 0;
}
switch (text_info_index)
{
case 0:
load_text1_nfc_payload();
nfc_t2t_emulation_start();
dk_set_led_on(NFC_MODE_LED);
break;
case 1:
load_text2_nfc_payload();
nfc_t2t_emulation_start();
dk_set_led_on(NFC_MODE_LED);
break;
default:
break;
}
}
}
// ...
}
//用于编码NDEF信息
static int nfc_msg2_encoder(uint8_t *buffer, uint32_t *len)
{
int err;
//创建NDEF文本记录
NFC_NDEF_TEXT_RECORD_DESC_DEF(nfc_ch_text_rec,
UTF_8,
text_encode_2,
sizeof(text_encode_2),
text_record_2,
sizeof(text_record_2));
/* Create NFC NDEF message description, capacity - MAX_REC_COUNT
* records
*/
NFC_NDEF_MSG_DEF(nfc_text_msg, MAX_REC_COUNT);
//将文本信息添加到NDEF信息
err = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_text_msg),
&NFC_NDEF_TEXT_RECORD_DESC(nfc_ch_text_rec));
if (err < 0) {
printk("Cannot add record!\n");
return err;
}
//将最终显示的 NDEF 文本消息进行编码
err = nfc_ndef_msg_encode(&NFC_NDEF_MSG(nfc_text_msg),
buffer,
len);
if (err < 0) {
printk("Cannot encode message!\n");
}
return err;
}
int load_text1_nfc_payload()
{
uint32_t len = sizeof(ndef_msg_buf_1);
//编码NDEF格式数据
if (nfc_msg1_encoder(ndef_msg_buf_1, &len) < 0) {
printk("Cannot encode message!\n");
return -1;
}
//将NEDF数据载入NFC payload
if (nfc_t2t_payload_set(ndef_msg_buf_1, len) < 0) {
printk("Cannot set payload!\n");
return -1;
}
printk("NFC configuration done\n");
return 0;
}
//初始化函数
int init() {
printk("Starting NFC Text Record example\n");
//配置 LED 引脚作为输出
if (dk_leds_init() < 0) {
printk("Cannot init LEDs!\n");
return -1;
}
//注册NFC回调函数
if (nfc_t2t_setup(nfc_callback, NULL) < 0) {
printk("Cannot setup NFC T2T library!\n");
return -1;
}
//开机预先加载payload
load_text1_nfc_payload();
//开启NFC
if (nfc_t2t_emulation_start() < 0) {
printk("Cannot start emulation!\n");
return -1;
}
//注册按键回调函数
if (dk_buttons_init(my_button_handler)) {
printk("Cannot init buttons\n");
return -1;
}
return 0;
}