Funpack2-6:基于 nRF7002-DK 的蓝牙和NFC实现简单的键盘输入功能
使用 nRF7002-DK 实现一个蓝牙键盘,通过按钮可以输出预设的字符。同时,利用 nRF5340 的 NFC 虚拟出一张可读可写的 NFC tag,通过手机向标签写入数据可以修改蓝牙键盘的输出字符串。
标签
嵌入式系统
Funpack活动
开发板
topgear
更新2023-10-10
685

Funpack2-6:基于 nRF7002-DK  的蓝牙和NFC实现简单的键盘输入功能

 

一、项目描述

nRF7002 DK是nRF7002 Wi-Fi 6协同IC的开发评估板,开发板采用nRF5340多协议SoC作为主处理器,配合nRF7002 Wi-Fi协同芯片,可以同时支持低功耗蓝牙和Wi-Fi 应用的开发,并实现如 OFDMA、波束成形和目标唤醒时间等多项 Wi-Fi 6 功能。

板上的nRF5340是支持低功耗蓝牙、蓝牙Mesh、NFC、Thread和Zigbee的双核蓝牙5.3 SoC,并且蓝牙测向可实现所有到达角(AoA)和出发角(AoD)的测量功能。此外,它支持低功耗蓝牙音频,2 Mbps高吞吐量、广播扩展和长距离。像蓝牙Mesh、Thread和Zigbee这样的Mesh协议可以与低功耗蓝牙同时运行,从而使智能手机能够配网、入网、配置和控制Mesh节点。还支持NFC、ANT、802.15.4和2.4 GHz专有协议。

在本项目中,主要使用 nRF5340 实现应用,使用了芯片的蓝牙和 NFC 功能:

  • 按键:用于蓝牙配对确认
  • LED 等:用于指示蓝牙广播状态和配对状态
  • 蓝牙:实现蓝牙键盘,可以连接 PC
  • NFC:用于与手机交互通信,设置蓝牙键盘可以输出的字符串

二、设计思路

  • 板卡上电后先初初始化按键和 LED 等外设所关联的 GPIO 和 handler;
  • 注册蓝牙认证的回调函数等;
  • 初始化 HID;
  • 启用蓝牙并广播;
  • 创建 NFC 交互任务线程。

三、软件流程

Fv71gRYOdMV8-Yt_fL7DI-0PxuRe

四、开发环境的搭建

  1. 使用 nRF Connect for Desktop 安装 toolchain/sdk

    在项目初期,我使用这种方法来搭建开发环境,但是安装过程中出现了 sdk 缺失部分依赖库,导致无法编译工程。后来nordic更新了vscode的插件,可以直接通过插件来安装toolchain/sdk,所以我后来直接切换为方法2。

    如果对方法1的安装方法感兴趣,可以去下述链接了解安装说明:nRF Connect SDK - nordicsemi.com

  2. 使用 nRF Connect for VSCode 安装 toolchain/sdk
    • 安装插件

                  Fr454V1Xab1bYlco5bn4cMorZpej

    • 安装 toolchain

                  Fkmo0fyqBLNwNM2Ha9GG4cVlFBku

    • 安装 sdk

                  FqFBAkc3bHMwdJATVZpt-3SwgFKv

五、工程配置说明

  1. 通过复制 sample project,创建新工程
    • FiwJ92LKGAhb3ZRBqtx-6utyfPuw
  2. 在本项目中,我主要参考下列两个 sample project
    # Bluetooth: Peripheral HIDS keyboard
    peripheral_hids_keyboard
    
    # NFC: Writable NDEF message
    writable_ndef_msg
  3. 通过复制 peripheral_hids_keyboard,创建新工程 peripheral_hids_keyboard_with_nfctag
  4. 因为 peripheral_hids_keyboard 工程没有基于 nRF7002-DK 开发板的 build configuration,所以基于 nRF5340-DK 创建 build configuration,然后再通过 Devicetree overlay 文件来重新映射GPIO
    • FtRJt8tAKQNqJy5ZhOUR9_1wWKEH
  5. 编译工程
    • FuwPmXxRyDIHfCyZJaXmePqH5Djr
  6. 烧录固件
    • FkrH6Brv-0Benpy6HY7YcYSBCuJR

六、代码实现和功能展示

  1. bluetooth 和 hid 初始化代码
    • 参考 peripheral_hids_keyboard\src\main.c 实现:
      int main(void)
      {
      	int err;
      	int blink_status = 0;
      
      	printk("Starting Bluetooth Peripheral HIDS keyboard example\n");
      
      	configure_gpio();
      
      	err = bt_conn_auth_cb_register(&conn_auth_callbacks);
      	if (err) {
      		printk("Failed to register authorization callbacks.\n");
      		return 0;
      	}
      
      	err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
      	if (err) {
      		printk("Failed to register authorization info callbacks.\n");
      		return 0;
      	}
      
      	hid_init();
      
      	err = bt_enable(NULL);
      	if (err) {
      		printk("Bluetooth init failed (err %d)\n", err);
      		return 0;
      	}
      
      	printk("Bluetooth initialized\n");
      
      	if (IS_ENABLED(CONFIG_SETTINGS)) {
      		settings_load();
      	}
      
      	advertising_start();
      
      	k_work_init(&pairing_work, pairing_process);
      
      	for (;;) {
      		if (is_adv) {
      			dk_set_led(ADV_STATUS_LED, (++blink_status) % 2);
      		} else {
      			dk_set_led_off(ADV_STATUS_LED);
      		}
      		k_sleep(K_MSEC(ADV_LED_BLINK_INTERVAL));
      		/* Battery level simulation */
      		bas_notify();
      	}
      }
  2. NFC tag 读写任务
    • 代码参考 writable_ndef_msg\src\main.c 实现:
      int nfc_task(void)
      {
      	printk("Starting Nordic NFC Writable NDEF Message example\n");
      
      	/* Initialize NVS. */
      	if (ndef_file_setup() < 0) {
      		printk("Cannot setup NDEF file!\n");
      		goto fail;
      	}
      	/* Load NDEF message from the flash file. */
      	if (ndef_file_load(ndef_msg_buf, sizeof(ndef_msg_buf)) < 0) {
      		printk("Cannot load NDEF file!\n");
      		goto fail;
      	}
      
      	/* Initialize default key code list. */
      	nfc_str.buffer[0] = 0x08;	/* key e */
      	nfc_str.buffer[1] = 0x08;	/* key e */
      	nfc_str.buffer[2] = 0x17;	/* key t */
      	nfc_str.buffer[3] = 0x15;	/* key r */
      	nfc_str.buffer[4] = 0x08;	/* key e */
      	nfc_str.buffer[5] = 0x08;	/* key e */
      	nfc_str.buffer[6] = 0x28;	/* key Return */
      	nfc_str.size = 7;
      
      	/* Set up NFC */
      	int err = nfc_t4t_setup(nfc_callback, NULL);
      
      	if (err < 0) {
      		printk("Cannot setup t4t library!\n");
      		goto fail;
      	}
      	/* Run Read-Write mode for Type 4 Tag platform */
      	if (nfc_t4t_ndef_rwpayload_set(ndef_msg_buf,
      				       sizeof(ndef_msg_buf)) < 0) {
      		printk("Cannot set payload!\n");
      		goto fail;
      	}
      	/* Start sensing NFC field */
      	if (nfc_t4t_emulation_start() < 0) {
      		printk("Cannot start emulation!\n");
      		goto fail;
      	}
      	printk("Starting NFC Writable NDEF Message example\n");
      
      	while (true) {
      		k_sleep(K_MSEC(100));
      
      		k_cpu_atomic_idle(irq_lock());
      	}
      
      fail:
      	#if CONFIG_REBOOT
      		sys_reboot(SYS_REBOOT_COLD);
      	#endif /* CONFIG_REBOOT */
      		return -EIO;
      }
  3. 按键发送字符和NFC write msg转换为键盘 code 的代码:
    • 代码如下:
      static void button_text_changed(bool down)
      {
      	static const uint8_t *chr = nfc_str.buffer;
      
      	if (down) {
      		hid_buttons_press(chr, 1);
      	} else {
      		hid_buttons_release(chr++, 1);
      		if (chr == (nfc_str.buffer + nfc_str.size)) {
      			chr = nfc_str.buffer;
      		}
      	}
      }
      
      static void nfc_callback(void *context,
      			 nfc_t4t_event_t event,
      			 const uint8_t *data,
      			 size_t data_length,
      			 uint32_t flags)
      {
      	ARG_UNUSED(context);
      	ARG_UNUSED(data);
      	ARG_UNUSED(flags);
      
      	switch (event) {
      	case NFC_T4T_EVENT_FIELD_ON:
      		dk_set_led_on(NFC_FIELD_LED);
      		break;
      
      	case NFC_T4T_EVENT_FIELD_OFF:
      		dk_set_leds(DK_NO_LEDS_MSK);
      		break;
      
      	case NFC_T4T_EVENT_NDEF_READ:
      		dk_set_led_on(NFC_READ_LED);
      		break;
      
      	case NFC_T4T_EVENT_NDEF_UPDATED:
      		if (data_length > 0) {
      			dk_set_led_on(NFC_WRITE_LED);
      			print_nfc_message(data_length);
      
      			uint16_t valid_data_len = data_length + NFC_NDEF_FILE_NLEN_FIELD_SIZE - 9;
      			uint8_t hid;
      			uint16_t i, j;
      
      			if (valid_data_len >= 1024)
      				valid_data_len = 1023;
      
      			for (i = 0, j = 0; i < valid_data_len; i++) {
      				hid = ascii_to_hid(*(ndef_msg_buf + 9 + i));
      				if (hid) {
      					nfc_str.buffer[j++] = hid;
      					printk("hid: %02x\n", hid);
      				}
      			}
      
      			nfc_str.buffer[j++] = ascii_to_hid('\n');
      			nfc_str.size = j;
      		}
      		break;
      
      	default:
      		break;
      	}
      }

七、功能展示

  • 蓝牙键盘广播

FkArJGkAwTFi8XF6lDUjwjThCwm7

  • NFC read

FhNxE1lzeJuaMp3J9zKp34Ptly_8

FtNsvSuN7yEwVdwS92s-LB507hTo

  • NFC Write

FodWMlcrhXP3Dj4he0f7bbvgzETA

附件下载
peripheral_hids_keyboard_with_nfctag.zip
项目工程
团队介绍
在职工程师
团队成员
topgear
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号