Funpack2-6 基于nRF7002开发板的自定义NFC标签
本项目使用Nordic的nRF7002开发板,实现了自定义NFC标签功能,可以通过按键切换NFC功能,指示灯显示NFC工作状态
标签
嵌入式系统
Funpack活动
开发板
NFC
不爱胡萝卜的仓鼠
更新2023-10-08
439

一.项目介绍

本项目使用Funpack2-6活动的开发板,来自Nordic的nRF7002DK。

本项目制作的是活动预设的任务三:“使用板卡的NFC功能,模拟出一个自定义功能的卡片,使用手机靠近并能读取卡片信息”。

我在该题目的基础上增加了按键控制NFC切换卡片、启动停止NFC的功能。

板卡上电默认处于NFC文本模式且关闭NFC使能。button1用于切换NFC工作模式(文本、打开B站个人主页),button2用于启动/停止NFC工作,LED1用于指示NFC是否正在通讯,LED2用于指示NFC是否正在工作

二.设计思路

按照活动任务三的要求,板卡上电后用手机靠近,能读取到NFC信息即为完成。 

那么首先第一步就是需要搭建开发环境,我参考了Nordic的官方文档(https://www.nordicsemi.cn/tools/nrfconnectsdk/)、硬禾学堂的直播课程(https://class.eetree.cn/live_pc/l_647d47a9e4b0cf39e6d3d397)以及网上其他人分享的教程

搭建完成开发环境后跑官方的NFC Demo,一共有7个,官方SDK也有这些demo的说明(https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.1/nrf/samples/nfc.html),让我可以更快的熟悉Demo,跑完所有Demo后就开始阅读代码和各个函数的说明,理解其中的运行逻辑和函数各个参数的含义。

其实运行完Demo就基本可以完成任务要求了,但是我还是希望在当前板卡硬件的基础上增加一些内容,于是我使用了板卡自带的2个button和LED灯。用于实现NFC切换卡片、启动停止NFC、LED指示NFC是否处于运行状态。

现在我需要做的就是学习一下如何在现有工程中如何添加GPIO以及GPIO相关函数如何使用。由于没有找到现成的demo,于是我把所有的历程代码都导入vscode,直接查询哪些demo使用了按键和LED,参考他们的代码。再使用到自己的工程中

三.代码解析

 本项目的代码主要有以下几个文件main.c、nfc_openApp.c、nfc_openApp.h、nfc_text.c、nfc_text.h。其中main.c存放main函数和切换NFC、启停NFC的代码。我将NFC的具体业务放到了nfc_xxx中。

首先 我们来看一下main函数,流程图如下

FmhGrHplDFoYxEQ81knXSRXIIoop

int main(void)
{
	int ret = -1;
	
	/* 初始化LED灯 */
	if (dk_leds_init() < 0) {
		printk("Cannot init LEDs!\n");
		goto fail;
	}

	/* 初始化按钮 */
	if (dk_buttons_init(button_handler)) {
		printk("Cannot init buttons\n");
		goto fail;
	}

	return 0;

fail:
#if CONFIG_REBOOT
	sys_reboot(SYS_REBOOT_COLD);
#endif /* CONFIG_REBOOT */

	return -EIO;
}

mian对LED和button做了初始化,如果任一初始化失败,系统将重启。在初始化button时注册了回调函数button_handler

button_handler流程图及代码如下
Fhn6LBj4XIucBnxhswyWfehUR3q6
static void button_handler(uint32_t button_state, uint32_t has_changed)
{
	int ret = -1;

	uint32_t button = button_state & has_changed;

	if (button & DK_BTN1_MSK) 
	{
		if (nfcMode == NFC_MODE_TEXT)
		{
			printk("switch nfc mode to open app\r\n");
			nfcMode = NFC_MODE_OPEN_APP;
		}
		else
		{
			printk("switch nfc mode to text\r\n");
			nfcMode = NFC_MODE_TEXT;
		}
	}
	if (button & DK_BTN2_MSK) 
	{
		if (nfcWorkState == true)
		{
			
			ret = nfc_t2t_emulation_stop();
			if (ret != 0)
			{
				printk("nfc_t2t_emulation_stop ret = %d\r\n", ret);
				return;
			}
			ret = nfc_t2t_done();
			if (ret != 0)
			{
				printk("nfc_t2t_done ret = %d\r\n", ret);
				return;
			}
			printk("nfc deinit success\r\n");
			nfcWorkState = false;
			dk_set_led_off(DK_LED2);
		}
		else
		{
			switch (nfcMode)
			{
			case NFC_MODE_TEXT:
				/* 设置NFC为一个文本 */
				ret = set_nfc_as_text_record();
				if (ret == -1)
				{
					printk("set_nfc_as_text_record fail\r\n");
				}
				break;
			
			case NFC_MODE_OPEN_APP:
				/* 设置NFC为打开一个APP */
				ret = set_nfc_as_open_app();
				if (ret == -1)
				{
					printk("set_nfc_as_open_app fail\r\n");
				}
				break;
			}
			printk("nfc start work\r\n");
			nfcWorkState = true;
			dk_set_led_on(DK_LED2);
		}
	}
}
当button被按下后,会进入button_handler,我可以在这里获取是哪个按键被按下。我设置里2个变量nfcMode和nfcWorkState,来表示NFC的工作模式和是否处于工作状态,配合按键信息,我就可以实现切换NFC、启停NFC的逻辑。在对应的逻辑中调用停止NFC的接口以及我自己实现的启动指定NFC功能的函数
这里以设置NFC为显示一个文本函数(set_nfc_as_text_record)为例,讲一下NFC初始化和启动的流程,打开APP的NFC函数也是大同小异。
/**
 * @brief		设置NFC为一个文本
 * @param[in]	none
 * @return      err	0:正常;-1:异常
 */
int set_nfc_as_text_record()
{
	uint32_t len = sizeof(temp_ndef_msg_buffer);

	/* 设置NFC为T2T,注册回调 */
	if (nfc_t2t_setup(nfc_callback, NULL) < 0) {
		printk("Cannot setup NFC T2T library!\n");
		return -1;
	}

	/* 根据文本信息,组装成NDEF格式数据 */
	if (text_msg_encode(temp_ndef_msg_buffer, &len) < 0) {
		printk("Cannot encode message!\n");
		return -1;
	}

	/* 将组装好的NEDF数据载入NFC payload */
	if (nfc_t2t_payload_set(temp_ndef_msg_buffer, len) < 0) {
		printk("Cannot set payload!\n");
		return -1;
	}

	/* 启动NFC */
	if (nfc_t2t_emulation_start() < 0) {
		printk("Cannot start emulation!\n");
		return -1;
	}
	printk("NFC configuration done\n");

	return 0;
}

设置一个NFC大致分为以下几步,

1.初始化NFC模式,我这边使用的T2T,还有T4T等,他们有什么区别我这边就不赘述了,有兴趣的可以上网学习一下。

2.组装NDEF数据,什么是NDEF数据,有兴趣的也可以去自学一下,不过不理解也没关系,官方SDK都有对应的函数,我们可以参考demo直接使用

3.将刚才组装好的数据加载到NFC

4.启动NFC

 

在初始化NFC模式时,还要注册一个回调函数nfc_callback,当NFC有事件时可以进入回调函数

/**
 * @brief		NFC回调函数
 * @param[in]	context:回调执行的应用程序上下文
 * @param[in]	event: 是什么事件触发的回调
 * @param[in]	data: 要发送到app的数据(特定于事件)
 * @param[in]	data_length: data的长度
 * @return      err	0:正常;-1:异常
 */
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) {
	/* 检测到有外部NFC */
	case NFC_T2T_EVENT_FIELD_ON:
		/* 点亮LED1 */
		dk_set_led_on(DK_LED1);
		break;
	/* 检测到外部NFC已移除 */
	case NFC_T2T_EVENT_FIELD_OFF:
		/* 熄灭LED1 */
		dk_set_led_off(DK_LED1);
		break;
	default:
		break;
	}
}

这里的回调函数我没有修改 ,直接复用demo的,实现的功能是当有NFC设备于开发板通讯时,LED1亮起,结束通讯时,LED1熄灭

组装一个文本NDEF函数如下

/**
 * @brief		组装文本数据为NDEF数据
 * @param[out]	buffer:存放组装好的NDEF数据
 * @param[out]	len:组装好的NDEF数据的长度
 * @return      err	0:正常;-1:异常
 */
static int text_msg_encode(uint8_t *buffer, uint32_t *len)
{
	int err;

	/* 创建一个 NFC NDEF 文本 */
	NFC_NDEF_TEXT_RECORD_DESC_DEF(nfc_text_rec,
				      UTF_8,
				      text_code,
				      sizeof(text_code),
				      text_payload,
				      sizeof(text_payload));

	/* 创建 NFC NDEF 描述 */
	NFC_NDEF_MSG_DEF(nfc_text_msg, MAX_REC_COUNT);

	/* 新增一条文本信息到NFC NDEF信息中 */
	err = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_text_msg),
				   &NFC_NDEF_TEXT_RECORD_DESC(nfc_text_rec));
	if (err < 0) {
		printk("Cannot add first record!\n");
		return err;
	}

	/* 最终输出结果 */
	err = nfc_ndef_msg_encode(&NFC_NDEF_MSG(nfc_text_msg),
				      buffer,
				      len);
	if (err < 0) {
		printk("Cannot encode message!\n");
	}

	return err;
}

这里的函数基本参考demo中的代码,将一条文本信息组装成NDEF数据

如何组装打开APP的NDEF数据我就不再赘述了,见附件代码即可,大同小异

 

四.功能展示

 LED2亮起,指示NFC正在工作中

FvDRNkAR5cT9FII_nZ2lfyH12m3u

手机扫描FNC读取文本信息

FhEwdd2oNSvBDPoR-tTmTp6LKFk3

停止NFC,切换NFC为“打开B站个人主页”模式

FpgPeeOKNCexw6cvdcdKX7b2sWWC

手机扫描NFC,打开B站个人主页

Fhx-QNdCrbsFUV_0-M-GGI19K0UK

 

五.心得体会

 这是我第一次学习使用nordic的新SDK,之前在52832上学习BLE时还是用的Keil环境,也有卖家写好的全套教程,按部就班的学。这次活动让我自己摸索,看官方文档,找其他人的分享,自己一步一步,从环境搭建,到编译成功,到实现功能,其中踩了很多坑,也学习到了很多新的东西,这一个多月的自学时光,让我收获颇丰。非常感谢硬禾学堂举办的funpack活动,让大家免费玩到各种各样的开发板。

附件下载
NFC_Project.hex
烧录文件
NFC_Project.rar
源码
团队介绍
个人
团队成员
不爱胡萝卜的仓鼠
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号