【CJSON】嵌入式芯片上基于USB HOST的CJSON文件库移植与应用

  • Post author:
  • Post category:其他


一 CJSON简介

项目遇到了一个需求,就是需要通过U盘或者其他外接设备,与板子(嵌入式芯片使用的是LPC1857)进行交互。交互的形式有两种:

  1. 一种是预存在外接U盘中的配置信息CFG,接上U盘之后,嵌入式芯片需要自动读取配置文件中的内容并改写自身的运行参数(

    外接设备配置信息—->主控芯片

    )。

  1. 一种是嵌入式芯片收集自身的状态信息DATA,接上U盘之后,将收集到的数据打包发送给U盘,便于维护人员对数据进行分析(

    外接设备<—-主控芯片状态信息

现在已经准备好了一个带

USB HOST(嵌入式芯片作为USB主机处理外接设备的功能)


以及


简单的文件系统

(文件系统可以参考

【文件系统】FatFs文件系统在嵌入式芯片LPC18XX上的移植

中的FatFs,这个工程只是做一个简单的DEMO,所以没有使用FatFs)。在此基础上,准备移植一个CJSON库,作为封装上面CFG/DATA信息的数据格式。


CJSON是一个使用C语言编写的JSON数据解析器,具有超轻便,可移植,单文件的特点,使用MIT开源协议。优点就是简单轻便,易于移植,该数据格式还可以灵活适用于网络数据的传输

二 CJSON说明

  1. 数据结构

CJSON的数据结构如下所示:

  1. 基础操作

CJSON的基础操作包括创建、封装、解析、修改、删除。

关于他们的具体用法可以参考这篇文章写的非常详细:

C/C++ 使用cjson库 操作Json格式文件(创建、插入、解析、修改、删除)

(特别注意的是:上述

操作完成之后一定要释放它们返回的指针内存,否则会造成内存泄漏

三 CJSON移植

  1. 下载

  1. CJSON开源库:

    https://gitee.com/openharmony/third_party_cJSON/tree/master

  1. CJSON库下载:

    https://sourceforge.net/projects/cjson/

以上两个地址均可以下载CJSON库。

下载下来之后,拉取其中的cJSON.c/cJSON.h/test.c三个文件,其中前面两个cJSON.c/cJSON.h是库文件必要,最后一个test.c是示例非必要。

  1. 移植

keil中新建目录CJSON,并包含头文件路径:

以上,便移植完成了,就两个文件,简单吧。

四 CJSON应用

下面就是第一章里面提到的两种场景的具体应用:


  1. 外接设备配置信息(cfg.json)—->主控芯片

预存cfg.json文件的内容如下:

这边设计的逻辑就是,在外接U盘加载完毕之后,通过串口Shell命令行输入命令jsi进行文件读取,寻找名为cfg.json的文件,如果找不到,返回“找不到文件”。如果找到,则读取文件内容,并用CJSON进行数据解析,将解析得到的配置数据返回显示(

主要涉及CJSON格式的解析操作

)。

void shellAnalyseCommand(char * command, short cmdLen)  //命令行解析函数
{
    //...
    //命令1:jsi  读取U盘中的cfd.json文件并解析
    if (((key[0] == 'J') || (key[0] == 'j'))
     && ((key[1] == 'S') || (key[1] == 's'))
     && ((key[2] == 'I') || (key[2] == 'i')))
    {
        shellPrint("数据读取开始...\r\n");
        FAT_FILE_HANDLE hSrc;
        hSrc = fatFileOpen("cfg.json", FAT_FILE_OPEN_READ);
        unsigned long len_s = 0;
        
        if (hSrc == FAT_FILE_HANDLE_NULL)
        {
            shellPrint("找不到文件 \r\n");
            return;
        }
        shellPrint("正在打开文件 %d \r\n", hSrc);
        len_s = fatFileGetLen(hSrc);
        char *out_s = (char *)malloc(len_s+1);
        fatFileRead(hSrc,(unsigned char*)out_s,len_s);
        fatFileClose(hSrc);
        cJSON *cfg = cJSON_Parse(out_s);
        cJSON *item = NULL;
        cJSON *item_typ = NULL;
        cJSON *item_wid = NULL;
        if (!cfg)
        {
            shellPrint("Error before: [%s]\n", cJSON_GetErrorPtr());
            free(out_s);
            return;
        }
        free(out_s);

        item = cJSON_GetObjectItem(cfg, "format");
        item_typ = cJSON_GetObjectItem(item, "type");
        item_wid = cJSON_GetObjectItem(item, "width");
        shellPrint("数据读取完成...\r\n");
        shellPrint("type:%s\r\nwidth:%d\r\n",item_typ->valuestring, item_wid->valueint);
        return;
    }
    //...
}

测试通过命令行jsi可以正确读取:


  1. 外接设备<—-主控芯片状态信息(data.json)

这边设计的逻辑就是,在外接U盘加载完毕之后,通过串口Shell命令行输入命令jso进行数据封装,将内部的状态信息打包成CJSON格式的文件,再写入到U盘中(

主要涉及CJSON格式的封装操作

)。

void shellAnalyseCommand(char * command, short cmdLen)  //命令行解析函数
{
    //...
    //命令2:jso  往U盘中写固定内容data.json文件
    if (((key[0] == 'J') || (key[0] == 'j'))
     && ((key[1] == 'S') || (key[1] == 's'))
     && ((key[2] == 'O') || (key[2] == 'o')))
    {
        shellPrint("数据装载开始...\r\n");
        cJSON *root = NULL;
        cJSON *fmt = NULL;
        char *out = NULL;
        size_t len = 0;
        root = cJSON_CreateObject();
        cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack"));
        cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
        cJSON_AddStringToObject(fmt, "type", "rect");
        cJSON_AddNumberToObject(fmt, "width", 100);
        cJSON_AddFalseToObject (fmt, "interlace");
        out = cJSON_Print(root);
        len = strlen(out) + 5;
        shellPrint("数据装载完成...\r\n");
        
        FAT_FILE_HANDLE hDst;
        hDst = fatFileOpen("data.json", FAT_FILE_OPEN_WRITE);
        if (hDst == FAT_FILE_HANDLE_NULL)
        {
            fatMakeFile("data.json");
            hDst = fatFileOpen("data.json", FAT_FILE_OPEN_WRITE);
            shellPrint("没有该文件则新建 %d \r\n", hDst);
        }
        else
        {
            fatFileClear(hDst);
            shellPrint("打开JSON文件 %d \r\n", hDst);
        }
        shellPrint("写json文件开始...\r\n");
        fatFileAppend(hDst, (unsigned char *)out, len);
        fatFileClose(hDst);
        shellPrint("写json文件完成...\r\n");
        free(out);
        cJSON_Delete(root);
        return;
    }
    //...
}

测试通过命令行jsi可以正确读取:

同样的,实际查看U盘中也有该文件:

五 总结

形象地概括来说,

CJSON文件库相当于一件衣服,将赤裸的数据套上CJSON大衣(封装)之后出去见人,会更好看,更易识别。但是同样的,读取外部CJSON数据就是脱衣服的过程(解析),抽丝剥茧才能看到最纯粹的数据。在这个循环中,CJSON作为壳,要注意用完就释放,毕竟这件衣服是租来的,用完要还的

综上,通过USB HOST + 串口SHELL命令行 + 文件系统 + CJSON文件库,便可以实现U盘或者其他外接设备,与嵌入式芯片的JSON格式数据交互。



版权声明:本文为sinat_33408502原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。