基于瑞芯微RK2206芯片+Harmony LiteOS操作系统的NFC控制案例

描述

一、简介

 

NFC英文全称Near Field Communication,近距离无线通信。是由飞利浦公司发起,由诺基亚、索尼等著名厂商联合主推的一项无线技术。NFC由非接触式射频识别(RFID)及互联互通技术整合演变而来,在单一芯片上结合感应式读卡器、感应式卡片和点对点的功能,能在短距离内与兼容设备进行识别和数据交换。这项技术最初只是RFID技术和网络技术的简单合并,现在已经演变成一种短距离无线通信技术,发展态势相当迅速。与RFID不同的是,NFC具有双向连接和识别的特点,工作于13.56MHz频率范围,作用距离10厘米左右。NFC技术在ISO 18092、ECMA 340和ETSI TS 102 190框架下推动标准化,同时也兼容应用广泛的ISO 14443 Type-A、B以及Felica标准非接触式智能卡的基础架构。

 

NFC芯片装在手机上,手机就可以实现小额电子支付和读取其他NFC设备或标签的信息。NFC的短距离交互大大简化整个认证识别过程,使电子设备间互相访问更直接、更安全和更清楚。通过NFC,电脑、数码相机、手机、PDA等多个设备之间可以很方便快捷地进行无线连接,进而实现数据交换和服务。

 

本文基于瑞芯微RK2206芯片 + Harmony LiteOS操作系统,通过i2c总线控制NFC,实现手机和开发板的互相通信功能。

 

操作系统

 

二、硬件电路设计

 

模块整体硬件电路如下图所示,电路中包含了NFC。电路比较简单,这边不对电路进行说明。

 

操作系统

图1 硬件电路图

 

三、程序设计

 

NFC是一种近距离无线通讯技术,使用NFC技术的设备(如智能手机)可以在彼此靠近的情况下进行数据交换,是通过在单一芯片上集成感应式读卡器、感应式卡片和点对点通信的功能,利用移动终端实现移动支付、门禁、移动身份识别等。

 

与以往设备配网技术相比,NFC"碰一碰"方案可以支持NFC功能的安卓手机和iOS 13.0以上系统的iPhone使用,为消费客户提供高效便捷的智慧生活无缝体验。

 

1、主程序设计

 

如图所示为NFC碰一碰主程序流程图,开机LiteOS系统初始化后,进入主程序后先初始化I2C总线,然后控制I2C总线往NFC写入一段文本信息和一段网址信息,最后拿支持NFC功能的安卓手机或iOS 13.0以上系统的iPhone靠近小凌派-RK2206开发板,就可以识别出一段文本信息和一个网址。

 

操作系统

图2 主程序流程图

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
void nfc_process(void){    unsigned int ret = 0;
    /* 初始化NFC设备 */nfc_init();
    ret = nfc_store_text(NDEFFirstPos, (uint8_t *)TEXT);    if (ret != 1) {        printf("NFC Write Text Failed: %d
", ret);}
    ret = nfc_store_uri_http(NDEFLastPos, (uint8_t *)WEB);    if (ret != 1) {        printf("NFC Write Url Failed: %d
", ret);    }        while (1) {        printf("==============NFC Example==============
");        printf("Please use the mobile phone with NFC function close to the development board!
");        printf("

");        LOS_Msleep(1000);    }}

(左右移动查看全部内容)

 

2、NFC初始化程序设计

 

NFC碰一碰初始化主要包括I2C总线初始化。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
/* NFC使用i2c的总线ID */static unsigned int NFC_I2C_PORT = 2;
/* i2c配置 */static I2cBusIo m_i2c2m0 ={    .scl =  {.gpio = GPIO0_PD6, .func = MUX_FUNC1, .type = PULL_NONE, .drv = DRIVE_KEEP, .dir = LZGPIO_DIR_KEEP, .val = LZGPIO_LEVEL_KEEP},    .sda =  {.gpio = GPIO0_PD5, .func = MUX_FUNC1, .type = PULL_NONE, .drv = DRIVE_KEEP, .dir = LZGPIO_DIR_KEEP, .val = LZGPIO_LEVEL_KEEP},    .id = FUNC_ID_I2C2,    .mode = FUNC_MODE_M0,};/* i2c的时钟频率 */static unsigned int m_i2c2_freq = 400000;
unsigned int NT3HI2cInit(){    uint32_t *pGrf = (uint32_t *)0x41050000U;    uint32_t ulValue;        ulValue = pGrf[7];    ulValue &= ~((0x7 << 8) | (0x7 << 4));    ulValue |= ((0x1 << 8) | (0x1 << 4));    pGrf[7] = ulValue | (0xFFFF << 16);    printf("%s, %d: GRF_GPIO0D_IOMUX_H(0x%x) = 0x%x
", __func__, __LINE__, &pGrf[7], pGrf[7]);        if (I2cIoInit(m_i2c2m0) != LZ_HARDWARE_SUCCESS)    {        printf("%s, %s, %d: I2cIoInit failed!
", __FILE__, __func__, __LINE__);        return __LINE__;    }    if (LzI2cInit(NFC_I2C_PORT, m_i2c2_freq) != LZ_HARDWARE_SUCCESS)    {        printf("%s, %s, %d: LzI2cInit failed!
", __FILE__, __func__, __LINE__);        return __LINE__;    }        return 0;}
unsigned int nfc_init(void){    unsigned int ret = 0;    uint32_t *pGrf = (uint32_t *)0x41050000U;    uint32_t ulValue;        if (m_nfc_is_init == 1)    {        printf("%s, %s, %d: Nfc readly init!
", __FILE__, __func__, __LINE__);        return __LINE__;    }        ret = NT3HI2cInit();    if (ret != 0)    {        printf("%s, %s, %d: NT3HI2cInit failed!
", __FILE__, __func__, __LINE__);        return __LINE__;    }        m_nfc_is_init = 1;    return 0;}

(左右移动查看全部内容)

 

3、NFC写入信息程序设计

 

向NFC芯片写入数据,但需要写入2个记录时,第2个记录的位置需要用 NDEFLastPos 来定义;当需要写入3个记录时,第2个和第3个记录的位置分别需要用 NDEFMiddlePos 和 NDEFLastPos 来定义。

 

操作系统

图3 NDEF协议格式图

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
ret = nfc_store_text(NDEFFirstPos, (uint8_t *)TEXT);if (ret != 1) {     printf("NFC Write Text Failed: %d
", ret);}
ret = nfc_store_uri_http(NDEFLastPos, (uint8_t *)WEB);if (ret != 1) {    printf("NFC Write Url Failed: %d
", ret);}

(左右移动查看全部内容)

 

其中,nfc_store_text()和nfc_store_uri_http()两个函数首先按照rtdText.h和rtdUri.h中RTD协议进行处理。然后与ndef.h中NT3HwriteRecord()进行记录写入。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
bool nfc_store_text(RecordPosEnu position, uint8_t *text){    NDEFDataStr data;        if (m_nfc_is_init == 0)    {        printf("%s, %s, %d: NFC is not init!
", __FILE__, __func__, __LINE__);        return 0;    }        prepareText(&data, position, text);    return NT3HwriteRecord(&data);}
bool nfc_store_uri_http(RecordPosEnu position, uint8_t *http){    NDEFDataStr data;        if (m_nfc_is_init == 0)    {        printf("%s, %s, %d: NFC is not init!
", __FILE__, __func__, __LINE__);        return 0;    }        prepareUrihttp(&data, position, http);    return NT3HwriteRecord(&data);

(左右移动查看全部内容)

 

NT3HwriteRecord()则负责将需要下发的信息打包成NDEF协议报文,最后由I2C总线将NDEF协议报文发送给NFC设备。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
bool NT3HwriteRecord(const NDEFDataStr *data){    uint8_t recordLength = 0, mbMe;    UncompletePageStr addPage;    addPage.page = 0;        // calculate the last used page    if (data->ndefPosition != NDEFFirstPos )    {        NT3HReadHeaderNfc(&recordLength, &mbMe);        addPage.page  = (recordLength + sizeof(NDEFHeaderStr) + 1) / NFC_PAGE_SIZE;                //remove the NDEF_END_BYTE byte because it will overwrite by the new Record        addPage.usedBytes = (recordLength + sizeof(NDEFHeaderStr) + 1) % NFC_PAGE_SIZE - 1;    }        // call the appropriate function and consider the pointer    // within the NFC_PAGE_SIZE that need to be used    int16_t payloadPtr = addFunct[data->ndefPosition](&addPage, data, data->ndefPosition);    if (payloadPtr == -1)    {        errNo = NT3HERROR_TYPE_NOT_SUPPORTED;        return false;    }        return writeUserPayload(payloadPtr, data, &addPage);}

(左右移动查看全部内容)

 

四、编译过程

 

1、搭建和下载源代码

我已将OpenHarmony源代码上传到Gitee社区中,大家可以根据以下网址下载。

https://gitee.com/Lockzhiner-Electronics/lockzhiner-rk2206-openharmony3.0lts

 

注意:编译环境可根据以下网址来操作:

https://gitee.com/Lockzhiner-Electronics/lockzhiner-rk2206-openharmony3.0lts/blob/master/vendor/lockzhiner/rk2206/README_zh.md

 

2、打开sdk下面路径的文件

/vendor/lockzhiner/rk2206/samples/b2_nfc/nfc_example.c

 

注意:Gitee上的NFC控制案例为通用案例,请大家根据上述的需求修改相关源代码。

 

3、修改编译脚本

修改 vendor/lockzhiner/rk2206/sample 路径下 BUILD.gn 文件,指定 nfc_example 参与编译。

  •  
"./b2_nfc:nfc_example",

(左右移动查看全部内容)

 

修改 device/lockzhiner/rk2206/sdk_liteos 路径下 Makefile 文件,添加 -lnfc_example 参与编译。

  •  
hardware_LIBS = -lhal_iothardware -lhardware -lnfc_example

(左右移动查看全部内容)

 

4、编译固件

  •  
  •  
  •  
hb set -root .hb sethb build -f

(左右移动查看全部内容)

 

5、烧写固件

请参考Gitee网址的说明手册(“烧录打印”章节):

https://gitee.com/Lockzhiner-Electronics/lockzhiner-rk2206-openharmony3.0lts/blob/master/device/rockchip/README_zh.md

 

五、实验结果

 

程序编译烧写到开发板后,按下开发板的RESET按键,通过串口软件查看日志如下:

  •  
  •  
  •  
  •  
  •  
==============NFC Example==============Please use the mobile phone with NFC function close to the development board!==============NFC Example==============Please use the mobile phone with NFC function close to the development board!......

(左右移动查看全部内容)

 

原文标题:小凌派-RK2206开发板:NFC控制案例

文章出处:【微信公众号:HarmonyOS官方合作社区】欢迎添加关注!文章转载请注明出处。

 
审核编辑:汤梓红
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分