基于nRF7002-DK的NFC功能切换系统(nRF Connect SDK+NFC)

news2024/9/28 15:26:42

目录

  • 项目介绍
  • 硬件介绍
  • 项目设计
    • 开发环境及工程目录
    • 总体流程图
    • 硬件初始化
    • NFC功能实现
      • 文本记录
      • 安卓应用打开
      • 按键切换功能
  • 功能展示
  • 项目总结

👉 【Funpack2-6】基于nRF7002-DK的NFC功能切换系统
👉 Github: EmbeddedCamerata/nRF7002-DK-nfc-function-switching

项目介绍

本项目基于nRF7002-DK,使用nRF Connect SDK v2.4.2 开发,使用NFC外设,实现NFC记录英文文本信息、中文文本信息与打开安卓应用三个功能,并可通过按键切换,通过手机NFC触碰即可触发。

👉 官网:nRF Connect SDK

硬件介绍

nRF7002-DK是用于nRF7002 Wi-Fi 6协同IC的开发套件,该开发套件采用nRF5340多协议片上系统 (SoC) 作为nRF7002的主处理器,在单一的电路板上包含了开发工作所需的一切,可让开发人员轻松开启基于nRF7002 的物联网项目。该 DK 包括 Arduino 连接器、两个可编程按钮、一个 Wi-Fi 双频段天线和一个低功耗蓝牙天线,以及电流测量引脚。

这款DK支持低功耗 Wi-Fi 应用开发,并实现了多项 Wi-Fi 6 功能,比如 OFDMA、波束成型和 TWT。nRF7002 Wi-Fi 6配套IC为另一个主机添加了低功耗Wi-Fi 6功能,提供无缝连接和基于Wi-Fi的定位(本地Wi-Fi集线器的SSID嗅探)功能。该IC设计用于搭配Nordic现有的nRF52®和nRF53®系列多协议片上系统 (SoC) 和nRF91®系列蜂窝物联网系统级封装 (SiP) 使用。nRF7002 IC 还可与非nordic主机器件搭配使用。通过SPI或QSPI与主机通信,并带有额外的共存功能,可与其他协议如蓝牙、Thread或Zigbee无缝共存。

nRF7002在Nordic的nRF Connect SDK中提供集成和支持。

板卡特性:

  • 用于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连接器

nRF7002结构框图

项目设计

开发环境及工程目录

根据 官网文档 手动安装SDK等依赖,nRF Connect SDK 版本 v2.4.2 。由于笔者是Linux环境,且有一定的洁癖,因此在安装 west 的时候单独为其使用Poetry,创建了一个Python虚拟环境。并在此基础上,安装额外的Python依赖。每次使用 west 先激活Python虚拟环境即可。

👉 Poetry

工程目录可根据 ncs/nrf/samples 中的sample复制一份,并在此基础上添加自己的代码或配置。例如:

├ build(编译时所产生的构建文件)
├ src
│ ├ main.c
│ └ ...(如有需要,其他的源代码)
├ CMakeLists.txt
├ prj.conf
├ sample.yaml
├ README.rst(项目说明文档)
└ ...

prj.conf 中配置需要启用的库,从而在编译程序的时候编译对应的头文件。sample.yaml 仅做描述示例程序之用。此外,Kconfig 是为了用户可在menuconfig内手动配置某些选项(主要是可选功能),在本工程中省略。

CMakeLists.txt 内,额外添加 set(BOARD nrf7002dk_nrf5340_cpuapp) ,从而在 west build 时可省略 -b nrf7002dk_nrf5340_cpuapp) 参数。

cmake_minimum_required(VERSION 3.20.0)
set(BOARD nrf7002dk_nrf5340_cpuapp)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(nfc_function_switching)
FILE(GLOB app_sources src/*.c)
# NORDIC SDK APP START
target_sources(app PRIVATE ${app_sources})
# NORDIC SDK APP END

总体流程图

工程流程图

硬件初始化

在此初始化板卡上的LED与按键。并将LED2打开以表示板卡正常工作。

dk_buttons_init(NULL);
dk_leds_init();
dk_set_led_on(SYSTEM_ON_LED);

NFC功能实现

首先通过 nfc_t2t_setup 注册NFC事件的回调函数,其回调函数内主要响应NFC标签检测到外部NFC场时与移除时的事件。当检测到外部NFC场时,LED1亮起,移除时灭。

nfc_t2t_setup(nfc_callback, NULL)

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;
	}
}

文本记录

主要使用nRF提供的nfc库。先生成NDEF文本记录描述符,再将这个记录加入NDEF消息中,之后 nfc_ndef_msg_encode 编码,并存入 buffer 内,长度为 len

static int nfc_text_encode(uint8_t *buffer, uint32_t *len)
{
	NFC_NDEF_TEXT_RECORD_DESC_DEF(nfc_text_rec,
								  UTF_8,
								  en_code,
								  sizeof(en_code),
								  en_payload,
								  sizeof(en_payload));

	NFC_NDEF_MSG_DEF(nfc_text_msg, MAX_REC_COUNT);

	/* Add record */
	if (nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_text_msg),
								&NFC_NDEF_TEXT_RECORD_DESC(nfc_text_rec)) < 0)
	{
		printk("Cannot add record!\n");
		return -1;
	}

	/* Encode text message */
	if (nfc_ndef_msg_encode(&NFC_NDEF_MSG(nfc_text_msg), buffer, len) < 0)
	{
		printk("Cannot encode message!\n");
		return -1;
	}

	return 0;
}

需要注意的是如何编码中英文文本信息至NDEF。对于英文使用UTF-8编码,直接编码ASCII字符,例如“Hello, World!”:

static const uint8_t en_payload[] = {
	'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'};
static const uint8_t en_code[] = {'e', 'n'};

NFC_NDEF_TEXT_RECORD_DESC_DEF(nfc_text_rec,
						      UTF_8,
							  en_code,
							  sizeof(en_code),
							  en_payload,
							  sizeof(en_payload));

而对于中文信息,例如“遥遥领先!”,每个中文字符需要UTF-16编码,但是 NFC_NDEF_TEXT_RECORD_DESC_DEF 宏内传入的数据的类型却是 uint8_t const* ,因此需要将“遥遥领先!”对应十六进制“\u6590\u6590\u8698\u4851\u01ff”拆分,先写低位再高位,使用UTF-16编码:

static const uint8_t zh_payload[] = {
	'\x90', '\x65', '\x90', '\x65', '\x98', '\x86', '\x51', '\x48', '\xff', '\x01'};
static const uint8_t zh_code[] = {'z', 'h'};

NFC_NDEF_TEXT_RECORD_DESC_DEF(nfc_text_rec,
							  UTF_16,
							  zh_code,
							  sizeof(zh_code),
							  zh_payload,
							  sizeof(zh_payload));

安卓应用打开

所需要的是安卓应用的名称 android_pkg_name。在此,将打开明日方舟 com.hypergryph.arknights 。并通过 nfc_launchapp_msg_encode 完成该类型消息的创建与编码,并存到 buffer,长度为 len

/* Package: com.hypergryph.arknights */
static const uint8_t android_pkg_name[] = {
	'c', 'o', 'm', '.',
	'h', 'y', 'p', 'e', 'r', 'g', 'r', 'y', 'p', 'h', '.',
	'a', 'r', 'k', 'n', 'i', 'g', 'h', 't', 's'};
static int nfc_launchapp_encode(uint8_t *buffer, uint32_t *len)
{
	/* Encode launch app data  */
	if (nfc_launchapp_msg_encode(android_pkg_name,
								 sizeof(android_pkg_name), NULL, 0, buffer, len) < 0)
	{
		printk("Cannot encode message!\n");
		return -1;
	}

	return 0;
}

按键切换功能

实现该功能,需要一个 enum 类型变量 nfc_app_t 存储当前功能的类别。并在初始化NFC功能后,在 while (true) 循环内扫描按键,判断 DK_BTN1 是否按下,按下则切换功能类别,同时根据 nfc_app 重新生成NFC payload并设置。

typedef enum
{
	NFC_APP_TEXT = 0U,
	NFC_APP_LAUNCHAPP
} nfc_app_t;

// In main() function
while (true)
{
	dk_read_buttons(&button_state, NULL);

	if (button_state & DK_BTN1_MSK)
	{
		nfc_app = 1 - nfc_app;
		/* Stop sensing NFC field */
		if (nfc_t2t_emulation_stop() < 0)
		{
			printk("Cannot stop emulation!\n");
			return -1;
		}
		if (nfc_payload_set(nfc_app) < 0)
		{
			printk("NFC payload set failed!\n");
			goto fail;
		}
	}
	k_sleep(K_MSEC(200));
}

需要注意的是,两种功能的payload,长度、内容不同,如果它们共用同一个buffer存储NDEF消息,例如 static uint8_t buffer[256]; ,实测会出错。因此,单独为两个功能各自设置一个buffer用于存储NDEF消息。那么,根据 nfc_app 的值,编码与设置不同类别的NDEF消息:

/* Buffer used to hold an NFC NDEF message. */
#define NDEF_MSG_BUF_SIZE 256
static uint8_t text_msg_buf[NDEF_MSG_BUF_SIZE];
static uint8_t launch_app_msg_buf[NDEF_MSG_BUF_SIZE];

// When nfc_app_t == NFC_APP_TEXT
len = sizeof(text_msg_buf);
nfc_text_encode(text_msg_buf, &len);
/* Set created message as the NFC payload */
nfc_t2t_payload_set(text_msg_buf, len);

// When nfc_app_t == NFC_APP_LAUNCHAPP
len = sizeof(launch_app_msg_buf);
nfc_launchapp_encode(launch_app_msg_buf, &len);
/* Set created message as the NFC payload */
nfc_t2t_payload_set(launch_app_msg_buf, len);

功能展示

板卡:

板卡全貌
通过按键切换NFC功能,串口打印提示语句:

串口打印
当功能为记录英文文本信息时,手机NFC触碰后,可读取文本信息“Hello, World!” UTF-8编码。

NFC读取英文文本信息
当功能为记录中文文本信息时,手机NFC触碰后,可读取文本信息“遥遥领先!” UTF-16编码。

NFC读取中文文本信息
当功能为记录安卓应用信息时,手机NFC触碰后,可读取应用信息“com.hypergryph.arknights”,即明日方舟包名。此外,当不用NFC标签助手等APP读取NFC信息,而直接触碰,则会唤起应用。

NFC读取安卓应用信息
在手机NFC触碰后,LED2将亮起,手机移开后,NFC连接移除,LED2灭。

👉 详细展示参见:B站:基于nRF7002-DK的NFC功能切换系统

项目总结

本次项目使用nRF7002-DK开发板,使我接触了Nordic家产品的开发环境,N家的开发环境如果使用VSCode插件全套的话,体验还算不错。但只是在笔者Linux端上VSCode插件识别不到板子,因此只能手动安装SDK、Zypher等工具,这个流程上倒是不难,只不过west工具还需要依赖Python,但隔离得不如esp-idf优雅。在编译流程上,有esp-idf的经验那么对于N家的流程就差不多。

工程上,借助NFC实现了多个功能切换,这让我学习了有关NFC的概念,对NFC功能了解更为深入,同时还让我接触到安卓设备投屏至Linux端的软件(推荐scrcpy)。希望日后再有机会用N家的开发板,能更深入地学习设备树、Kconfig、prj.conf、Zypher 等知识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1025979.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智慧养殖:浅谈视频监控与AI智能识别技术助力奶牛高效、智慧养殖

一、方案背景 随着科技的飞速发展&#xff0c;智能化养殖逐渐成为现代畜牧业的发展趋势。人工智能技术、物联网、视频技术、云计算、大数据等新兴技术&#xff0c;正在为奶牛养殖业带来全新的变革。越来越多的牧场、养殖场开始运用新技术来进行智能监管、提高生产效率、降低生…

就只说 3 个 Java 面试题

在面试时&#xff0c;即使是经验丰富的开发人员&#xff0c;也可能会发现这是一些很棘手的问题&#xff1a; 1、Java中“transient”关键字的用途是什么&#xff1f;如何才能实现这一目标&#xff1f; 在 Java 中&#xff0c;“transient”关键字用于指示类的特定字段不应包含…

蒙特卡洛方法的数学基础-1

蒙特卡洛方法的数学基础-1 概率论 Bayes 公式 常用分布 Binominal Distribution Poisson Distribution Gaussian Distribution Exponential Distribution Uniform Distribution 大数定理 均匀概率分布随机地取N个数xi &#xff0c;函数值之和的算术平均收敛于函数的期望值 …

Cesium 空间量算——生成点位坐标

文章目录 需求分析1. 点击坐标点实现2. 输入坐标实现 需求 用 Cesium 生成点位坐标&#xff0c;并明显标识 分析 以下是我的两种实现方式 第一种是坐标点击实现 第二种是输入坐标实现 1. 点击坐标点实现 //点位坐标getLocation() {this.hoverIndex 0;let that this;this.view…

八一书《乡村振兴战略下传统村落文化旅游设计》许少辉瑞博士生辉少许——2023学生开学季许多少年辉光三农

八一书《乡村振兴战略下传统村落文化旅游设计》许少辉瑞博士生辉少许——2023学生开学季许多少年辉光三农

10万单词例句表单词句子ACCESS\EXCEL数据库

原本我以为《3万5千英语句子英语例句大全ACCESS数据库》例句已经够多了&#xff0c;没想到今天遇到一个10万条英语单词例句的数据&#xff0c;非常适合与单词词典进行关联学习&#xff0c;例句多了单词的用法以及句子的掌握都更有效率。 截图下方有显示“共有记录数”&#xff…

Cesium 空间量算——面积量算

面积量算 需求分析 需求 对页面上所选内容进行面积计算 分析 其实&#xff0c;计算面积其实就是把一个面&#xff0c;拆分成一个一个的三角曲面计算然后相加得到&#xff0c;下面是计算的面积的代码 /** * description : 面积量算* author : Hukang* date : 2023-09-20 13:1…

Date类的学习笔记-超级详细

Date 的定义, 在开始研究这个之前我们首先要能够明白一点&#xff0c;这个 Date 其实本质上是一个对象&#xff0c;我们通过这个对象可以去构建变量&#xff0c;知道这个之后就可以开展后续的研究了 JDK 通用 Date 类的构造方法 测试 获取当前的时间 // 构造这个日期对象Date…

计算机毕设 opencv python 深度学习垃圾图像分类系统

文章目录 0 前言课题简介一、识别效果二、实现1.数据集2.实现原理和方法3.网络结构 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟…

Vue系列(三)之 基础语法【下篇】

一. 事件处理 在 Vue.js 中&#xff0c;v-on 指令被用于监听 DOM 事件&#xff0c;并在事件触发时执行相应的方法&#xff0c;这些方法就是事件处理器。v-on 指令有简写形式 &#xff0c;例如 click"handleClick" 会监听点击事件并执行 handleClick 方法。 事件处理…

MQ - 09 RabbitMQ的架构设计与实现

文章目录 导图概述RabbitMQ 系统架构协议和网络模块数据存储元数据存储 ---> 自带的分布式数据库 Mnesia消息数据存储 生产者和消费者HTTP 协议支持和管控操作RabbitMQ 从生产到消费的全过程总结 导图 概述 最基础的消息队列应该具备通信协议、网络模块、存储模块、生产者、…

socket() failed (24: Too many open files) while connecting to upstream, client

一、这个错误通常是因为文件句柄数目超过系统限制导致的。要解决这个问题&#xff0c;您可以尝试以下几个步骤&#xff1a; 调整系统文件句柄限制&#xff1a;您可以通过修改/etc/security/limits.conf文件中的nofile参数来增加系统文件句柄的最大数目。将nofile的值增加到更高…

zabbix监控平台部署(二)

目录 一、自定义监控 二、Nginx监控 三、监控mysql 四、钉钉告警 五、163邮箱报警 总结 zabbix5.0 一、自定义监控 zabbix-agent&#xff08;147&#xff09; agent端操作 vim /etc/zabbix/zabbix_agentd.conf 在配置未文件末尾添加 UserParametermemory_userd,free…

C++中 负数与String字符串的长度 string.size()作比较 输出错误

在刷题的时候&#xff0c;发现用 -1<t.size() 输出的是错误的值&#xff0c;如下&#xff0c;t“ABC”&#xff0c;但重新定义一个变量后又可以了&#xff0c;查阅检查后&#xff0c;发现string.size()返回的是一个无符号的整数&#xff0c;因此与有符号整数比较&#xff0c…

SpingBoot:整合Mybatis-plus+Druid+mysql

SpingBoot&#xff1a;整合Mybatis-plusDruid 一、特别说明二、创建springboot新工程三、配置3.1 配置pom.xml文件3.2 配置数据源和durid连接池3.3 编写拦截器配置类 四、自动生成代码五、测试六、附件-mysql数据库表 本文参考链接&#xff1a; [Java] Spring Boot 集成 MyBati…

免费、安全、可靠!一站式构建平台 ABS 介绍及实例演示 | 龙蜥技术

编者按&#xff1a;操作系统是一个大的软件集合&#xff0c;成百上千个软件之间有相互调用、相互依赖等各种复杂的关联关系&#xff0c;所以统一的软件包格式&#xff0c;能够更友好地管理、定义这些复杂关系。今天&#xff0c;龙蜥社区基础设施 Contributor 单凯伦带大家了解龙…

Python灰帽编程——网页信息爬取

文章目录 网页信息爬取1. 相关模块1.1 requests 模块1.1.1 模块中的请求方法1.1.2 请求方法中的参数1.1.3 响应对象中属性 1.2 RE 模块1.2.1 匹配单个字符1.2.2 匹配一组字符1.2.3 其他元字符1.2.4 核心函数 2. 网页信息爬取2.1 获取网页HTML 源代码2.2 提取图片地址2.3 下载图…

【机器学习】详解回归(Regression)

文章目录 是什么的问题案例说明 是什么的问题 回归分析&#xff08;Regression Analysis&#xff09; 是研究自变量与因变量之间数量变化关系的一种分析方法&#xff0c;它主要是通过因变量Y与影响它的自变量 X i &#xff08; i 1 , 2 , 3 … &#xff09; X_i&#xff08;i1…

鉴源论坛 · 观模丨基于应用程序编程接口(API)的自动化测试(下)

作者 | 黄杉 华东师范大学软件工程学院博士 苏亭 华东师范大学软件工程学院教授 版块 | 鉴源论坛 观模 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 上文“基于应用程序编程接口&#xff08;API&#xff09;的自动化测试&#xff08;上&#xff09;”…

阿里巴巴全店商品采集教程,阿里巴巴店铺所有商品接口(详解阿里巴巴店铺所有商品数据采集步骤方法和代码示例)

随着电商行业的快速发展&#xff0c;阿里巴巴已成为国内的电商平台之一&#xff0c;拥有着海量的商品资源。对于一些需要大量商品数据的商家或者需求方来说&#xff0c;阿里巴巴全店采集是非常必要的。本文将详细介绍阿里巴巴全店采集的步骤和技巧&#xff0c;帮助大家更好地完…