【鸿蒙开发】Hi3861学习笔记- NFC

00. 目录

文章目录

    • [00. 目录](#00. 目录)
    • [01. NFC简介](#01. NFC简介)
    • [02. NT3H1101](#02. NT3H1101)
    • [03. 硬件设计](#03. 硬件设计)
    • [04. 软件设计](#04. 软件设计)
    • [05. 实验现象](#05. 实验现象)
    • [06. 附录](#06. 附录)

01. NFC简介

什么是NFC

NFC(Near Field Communication,近场通信)是一种基于无线射频识别(RFID)的短距离通信技术,允许电子设备在10厘米左右的范围内进行非接触式数据传输。其特点是快速配对、低功耗和高安全性,常用于移动支付、身份识别等场景。

工作原理

  • 频率与距离:工作在13.56MHz频段,传输距离通常小于10厘米,需设备贴近或轻触。
  • 工作模式
    • 主动模式:双方设备均有电源,交替发送信号(如文件传输)。
    • 被动模式:一方无电源(如NFC标签),由主动设备供电读取数据(如扫描智能海报)。
    • 卡模拟模式:设备模拟成IC卡(如手机变公交卡)。

核心特点

  • 便捷性:无需手动配对,触碰即连接。
  • 低功耗:适合小型设备(如智能手表)。
  • 高兼容性:兼容传统RFID标准(如公交卡、门禁)。
  • 安全性:短距离降低窃听风险,支持加密通信(如SE安全芯片)。

应用场景

  • 移动支付:Apple Pay、支付宝等触碰支付。
  • 交通出行:手机NFC模拟公交卡、地铁闸机刷卡。
  • 智能家居:触碰连接音箱、快速配对蓝牙设备。
  • 信息交换:轻触手机传输联系人、照片(Android Beam)。
  • 身份识别:电子护照、企业门禁卡。
  • 营销互动:扫描NFC标签获取产品信息或优惠券。

安全性

  • 短距离防护:需极近距离通信,难以远程拦截。
  • 硬件加密:支付类应用依赖SE安全芯片存储敏感数据。
  • 风险提示:警惕恶意NFC标签诱导连接(如强制打开钓鱼网站)。

与其他技术对比

  • VS蓝牙:NFC连接更快(0.1秒)、无需配对,但传输速度慢(424kbps vs 蓝牙5.0的2Mbps),适合小数据量场景。
  • VS RFID:NFC是RFID的子集,专为双向交互设计,而RFID多为单向读取(如仓储物流)。

02. NT3H1101

NT3H1101W0FHKH(通常简称为 NT3H1101)是一款由 NXP(恩智浦)半导体公司生产的射频卡芯片,该芯片属于 NTAG I²C 系列,特

别适用于需要 NFC(近场通信)功能的各种应用场景。

03. 硬件设计

从上图可知,板载 NFC 均连接到指定 IO。

04. 软件设计

bsp_nfc.h

c 复制代码
#ifndef BSP_NFC_H
#define BSP_NFC_H

#include "cmsis_os2.h"
#include "hi_io.h"
#include "hi_gpio.h"



#define NDEF_HEADER_SIZE 0x2 // NDEF协议的头部大小

#define NDEF_PROTOCOL_HEADER_OFFSET 0           // NDEF协议头(固定)
#define NDEF_PROTOCOL_LENGTH_OFFSET 1           // NDEF协议数据的总长度位
#define NDEF_PROTOCOL_MEG_CONFIG_OFFSET 2       // 标签的控制字节位
#define NDEF_PROTOCOL_DATA_TYPE_LENGTH_OFFSET 3 // 标签数据类型的长度位
#define NDEF_PROTOCOL_DATA_LENGTH_OFFSET 4      // 标签的数据长度位
#define NDEF_PROTOCOL_DATA_TYPE_OFFSET 6        // 标签的数据类型位
#define NDEF_PROTOCOL_VALID_DATA_OFFSET 20      // 有效数据位


//函数声明
uint32_t get_NDEFDataPackage(uint8_t *dataBuff, const uint16_t dataBuff_MaxSize);
uint32_t nfc_init(void);

#endif

bsp_nfc.c

c 复制代码
#include "bsp_nfc.h"
#include "hi_errno.h"
#include "hi_i2c.h"
#include "NT3H.h"
#include <stdlib.h>
#include <string.h>


/**
 * @brief  从Page页中组成NDEF协议的包裹
 * @note
 * @param  *dataBuff: 最终的内容
 * @param  dataBuff_MaxSize: 存储缓冲区的长度
 * @retval
 */
uint32_t get_NDEFDataPackage(uint8_t *dataBuff, const uint16_t dataBuff_MaxSize)
{
    if (dataBuff == NULL || dataBuff_MaxSize <= 0) 
    {
        printf("dataBuff==NULL or dataBuff_MaxSize<=0\r\n");
        return HI_ERR_FAILURE;
    }

    uint8_t userMemoryPageNum = 0; // 用户的数据操作页数

    // 算出要取多少页
    if (dataBuff_MaxSize <= NFC_PAGE_SIZE) 
    {
        userMemoryPageNum = 1; // 1页
    } 
    else 
    {
        // 需要访问多少页
        userMemoryPageNum = (dataBuff_MaxSize / NFC_PAGE_SIZE) + \
                            ((dataBuff_MaxSize % NFC_PAGE_SIZE) >= 0 ? 1 : 0);
    }

    // 内存拷贝
    uint8_t *p_buff = (uint8_t *)malloc(userMemoryPageNum * NFC_PAGE_SIZE);
    if (p_buff == NULL) 
    {
        printf("p_buff == NULL.\r\n");
        return HI_ERR_FAILURE;
    }

    // 读取数据
    for (int i = 0; i < userMemoryPageNum; i++) 
    {
        if (NT3HReadUserData(i) == true) 
        {
            memcpy_s(p_buff + i * NFC_PAGE_SIZE, userMemoryPageNum * NFC_PAGE_SIZE,
                     nfcPageBuffer, NFC_PAGE_SIZE);
        }
    }

    memcpy_s(dataBuff, dataBuff_MaxSize, p_buff, dataBuff_MaxSize);

    free(p_buff);
    p_buff = NULL;

    return HI_ERR_SUCCESS;
}

//NFC初始化
uint32_t nfc_init(void)
{
    uint32_t result;

    // gpio_9 复用为 I2C_SCL
    hi_io_set_pull(HI_IO_NAME_GPIO_9, HI_IO_PULL_UP);
    hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_I2C0_SCL);
    // gpio_10 复用为 I2C_SDA
    hi_io_set_pull(HI_IO_NAME_GPIO_10, HI_IO_PULL_UP);
    hi_io_set_func(HI_IO_NAME_GPIO_10, HI_IO_FUNC_GPIO_10_I2C0_SDA);

    result = hi_i2c_init(HI_I2C_IDX_0, I2C_RATE_DEFAULT);
    if (result != HI_ERR_SUCCESS) 
    {
        printf("I2C nfc Init status is 0x%x!!!\r\n", result);
        return result;
    }
    printf("I2C nfc Init is succeeded!!!\r\n");

    return true;
}

template.c

c 复制代码
#include <stdio.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"

#include "bsp_led.h"
#include "bsp_nfc.h"


//LED任务
osThreadId_t LED_Task_ID; //led任务ID

void LED_Task(void)
{
    led_init();//LED初始化

    while (1) 
    {
        LED(1); 
        usleep(200*1000); //200ms
        LED(0);
        usleep(200*1000); //200ms
    }
}
//LED任务创建
void led_task_create(void)
{
    osThreadAttr_t taskOptions;
    taskOptions.name = "LEDTask";            // 任务的名字
    taskOptions.attr_bits = 0;               // 属性位
    taskOptions.cb_mem = NULL;               // 堆空间地址
    taskOptions.cb_size = 0;                 // 堆空间大小
    taskOptions.stack_mem = NULL;            // 栈空间地址
    taskOptions.stack_size = 1024;           // 栈空间大小 单位:字节
    taskOptions.priority = osPriorityNormal; // 任务的优先级

    LED_Task_ID = osThreadNew((osThreadFunc_t)LED_Task, NULL, &taskOptions); // 创建任务1
    if (LED_Task_ID != NULL)
    {
        printf("ID = %d, Create LED_Task_ID is OK!\n", LED_Task_ID);
    }
}

//控制任务
osThreadId_t NFC_Task_ID; //任务ID

void NFC_Task(void)
{
    uint8_t ret, num = 0;
    uint8_t ndefLen = 0;      // ndef包的长度
    uint8_t ndef_Header = 0;  // ndef消息开始标志位-用不到
    uint32_t result_code = 0; // 函数的返回值
    uint8_t i=0;
    
    nfc_init();

    // 读整个数据的包头部分,读出整个数据的长度
    if (result_code = NT3HReadHeaderNfc(&ndefLen, &ndef_Header) != true) 
    {
        printf("NT3HReadHeaderNfc is failed. result_code = %d\r\n", result_code);
        return;
    }

    ndefLen += NDEF_HEADER_SIZE; // 加上头部字节
    if (ndefLen <= NDEF_HEADER_SIZE) 
    {
        printf("ndefLen <= 2\r\n");
        return;
    }
    uint8_t *ndefBuff = (uint8_t *)malloc(ndefLen + 1);
    if (ndefBuff == NULL) 
    {
        printf("ndefBuff malloc is Falied!\r\n");
        return;
    }

    if (result_code = get_NDEFDataPackage(ndefBuff, ndefLen) != HI_ERR_SUCCESS) 
    {
        printf("get_NDEFDataPackage is failed. result_code = %d\r\n", result_code);
        return;
    }

    printf("start print ndefBuff.\r\n");
    for (i = 0; i < ndefLen; i++) 
    {
        printf("0x%x ", ndefBuff[i]);
    }
    
    while (1) 
    {
        usleep(10*1000); //10ms
    }
}
//任务创建
void nfc_task_create(void)
{
    osThreadAttr_t taskOptions;
    taskOptions.name = "nfcTask";       // 任务的名字
    taskOptions.attr_bits = 0;               // 属性位
    taskOptions.cb_mem = NULL;               // 堆空间地址
    taskOptions.cb_size = 0;                 // 堆空间大小
    taskOptions.stack_mem = NULL;            // 栈空间地址
    taskOptions.stack_size = 1024*5;           // 栈空间大小 单位:字节
    taskOptions.priority = osPriorityNormal; // 任务的优先级

    NFC_Task_ID = osThreadNew((osThreadFunc_t)NFC_Task, NULL, &taskOptions); // 创建任务
    if (NFC_Task_ID != NULL)
    {
        printf("ID = %d, NFC_Task_ID Create OK!\n", NFC_Task_ID);
    }
}

/**
 * @description: 初始化并创建任务
 * @param {*}
 * @return {*}
 */
static void template_demo(void)
{
    printf("-Hi3861开发板--NFC实验\r\n");
    led_task_create();
    nfc_task_create();//任务创建
}
SYS_RUN(template_demo);

05. 实验现象

实验现象:通过手机 NFC 标签助手 APP 向 NFC 标签中写入数据,并且读取 NFC 标签中的数据,通过串口助手输出。

06. 附录

相关推荐
whysqwhw24 分钟前
鸿蒙AVSession Kit
harmonyos
whysqwhw2 小时前
鸿蒙各种生命周期
harmonyos
whysqwhw3 小时前
鸿蒙音频编码
harmonyos
whysqwhw3 小时前
鸿蒙音频解码
harmonyos
whysqwhw3 小时前
鸿蒙视频解码
harmonyos
whysqwhw3 小时前
鸿蒙视频编码
harmonyos
ajassi20004 小时前
开源 Arkts 鸿蒙应用 开发(十八)通讯--Ble低功耗蓝牙服务器
华为·开源·harmonyos
前端世界5 小时前
在鸿蒙应用中快速接入地图功能:从配置到实战案例全解析
华为·harmonyos
江拥羡橙6 小时前
【基础-判断】HarmonyOS提供了基础的应用加固安全能力,包括混淆、加密和代码签名能力
安全·华为·typescript·harmonyos
森之鸟17 小时前
DevEco Studio 6.0.0 元服务页面跳转失败
鸿蒙