【嵌入式项目应用】__cJSON在单片机的使用
目录
前言
一、JSON和cJson
二、cJSON是如何表示JSON数据的
三、如何封装完整的JSON数据
1. 先将串口打通,方便电脑查看log日志。
2. 增加cjson.c文件,已经在main.c中
3. 准备打包如下的JSON包
4. 代码部分,先将几个部分初始化指针
5. 创建链表
6. 我们查看添加的是否正确,可以将链表通过串口打印出来。
7. 效果如下:
四、解包
五、总结
(* ̄︶ ̄)创作不易!期待你们的 点赞、收藏和评论喔。
前言
在使用MQTT传输数据的时候,经常使用到JSON包,来进行数据的交互,这篇文章讲一下该如何使用。
一、JSON和cJson
- JSON:全称 JavaScript Object Notation,轻量级的数据格式。
- cJSON:是一个用c语言编写的JSON数据解析器,超级轻便,可以移植,单文件MIT源协议。
cJSON的源码文件只有两个:
cJSON.c
cJSON.h
下载地址可以在github下载,地址如下:
GitHub - DaveGamble/cJSON: Ultralightweight JSON parser in ANSI C
将这两个文件下载之后,添加到项目中,其它.C文件调用的时候,需要包含头文件cJSON.h即可,文件在MDK中的位置如下:
二、cJSON是如何表示JSON数据的
cJSON是用一个结构体来表示一个JSON数据,定义在cJSON.h中,查看如下源码:
/* The cJSON structure: */
typedef struct cJSON
{/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */struct cJSON *next;struct cJSON *prev;/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */struct cJSON *child;/* The type of the item, as above. */int type;/* The item's string, if type==cJSON_String and type == cJSON_Raw */char *valuestring;/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */int valueint;/* The item's number, if type==cJSON_Number */double valuedouble;/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */char *string;
} cJSON;
不是存贮整片的JSON数据,而是按照每条数据进行存储的。使用next指针和prev指针进行链表,存储整片的JSON数据。
三、如何封装完整的JSON数据
说了这么多,我们实际操作一下,找一块STM32F开发板,测试一下。
1. 先将串口打通,方便电脑查看log日志。
uart_init(115200);
2. 增加cjson.c文件,已经在main.c中
#include "cJSON.h"
3. 准备打包如下的JSON包
{"我的名字": "老刘","公众号": "数独机","年龄": 11,"性别": "男","电话": 186,"地址": "一般人不告诉","我是嵌套的cJSON": {"号码": 9527,"传真": 5510,"淘宝店": "This熏"},"我是嵌套的数组": [{"我是奇数循环": 0}, {"我是偶数循环": "12365"}, {"我是奇数循环": 2}, {"我是偶数循环": "12365"}, {"我是奇数循环": 4}]
}
4. 代码部分,先将几个部分初始化指针
cJSON* main_root = NULL;cJSON* main_m_root = NULL;cJSON* main_l_root = NULL;cJSON* obj=NULL;char* response_str = NULL;
5. 创建链表
main_root = cJSON_CreateObject();
豪横的在链表中添加节点
cJSON_AddStringToObject(main_root, "我的名字", "老刘");cJSON_AddStringToObject(main_root, "公众号", "数独机");cJSON_AddNumberToObject(main_root, "年龄", 11);cJSON_AddStringToObject(main_root, "性别", "男");cJSON_AddNumberToObject(main_root, "电话", 186);cJSON_AddStringToObject(main_root, "地址", "一般人不告诉");main_m_root = cJSON_CreateObject();cJSON_AddNumberToObject(main_m_root, "号码", 9527); cJSON_AddNumberToObject(main_m_root, "传真", 5510);cJSON_AddStringToObject(main_m_root, "淘宝店", "This熏");cJSON_AddItemToObject(main_root, "我是嵌套的cJSON", main_m_root);main_l_root=cJSON_CreateArray();cJSON_AddItemToObject(main_root,"我是嵌套的数组",main_l_root);for(i=0;i<5;i++){obj=cJSON_CreateObject();cJSON_AddItemToArray(main_l_root,obj);if(i%2 == 0) cJSON_AddNumberToObject(obj, "我是奇数循环", i);else cJSON_AddStringToObject(obj, "我是偶数循环", "12365");}
6. 我们查看添加的是否正确,可以将链表通过串口打印出来。
response_str = cJSON_Print(main_root);printf("%s\n",response_str);
7. 效果如下:
四、解包
解包的函数只有一个:
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
还是用例子进行讲解:
将串口的数据完全接收到一个大的缓冲区里面,当然这个数据也可以来自wifi或者网络。
if(GET_STOP_flag)
{for(i=0;i<(cJSON_pack_StopP-cJSON_pack_FistP)+1;i++){MessageTmp[i] =WIFI_RC_buf[cJSON_pack_FistP-1+i];}
}
GET_STOP_flag //为停止接收标志;
cJSON_pack_StopP //停止指针位置
cJSON_pack_FistP //开始指针位置
MessageTmp //临时的数组
只需要对临时的数组进行操作即可。开辟内存空间,将数组转换为字符串。
MessageStrTmp = (char *)cJSON_malloc(sizeof(char) * (sizeof(MessageTmp) + 1));
strncpy(MessageStrTmp, MessageTmp, sizeof(MessageTmp));
使用解包函数
//接收解包过程
Thisxun_root = cJSON_Parse(MessageStrTmp);
Thisxun_root_type = cJSON_GetObjectItem(hiss_root,"type")->valuestring;
if(strcmp(Thisxun_root_type,TYPE_USER_INFO_SYNC)==0)
{Thisxun_insDetail = cJSON_GetObjectItem(Thisxun_root,"insDetail");userID = cJSON_GetObjectItem(Thisxun_insDetail,"userId")->valuestring;password = cJSON_GetObjectItem(Thisxun_insDetail,"password")->valuestring;
}
五、总结
每次封包和解包结束之后,都要及时释放内存:
cJSON_Delete(Thisxun_root);
cJSON_free(MessageStrTmp);
对于单片机而言,需要修改Heap_Size
(* ̄︶ ̄)创作不易!期待你们的 点赞、收藏和评论喔。
相关文章:

【嵌入式项目应用】__cJSON在单片机的使用
目录 前言 一、JSON和cJson 二、cJSON是如何表示JSON数据的 三、如何封装完整的JSON数据 1. 先将串口打通,方便电脑查看log日志。 2. 增加cjson.c文件,已经在main.c中 3. 准备打包如下的JSON包 4. 代码部分,先将几个部分初始化指针 …...

【智能家居】
面向Apple developer学习:AirPlay | Apple Developer Documentation Airplay AirPlay允许人们将媒体内容从iOS、ipad、macOS和tvOS设备无线传输到支持AirPlay的Apple TV、HomePod以及电视和扬声器上。 网页链接的最佳实践 首选系统提供的媒体播放器。内置的媒体播…...

Android stdio 无法新建或打开AIDL文件(解决方法)
1.在gradle文件中添加如下代码 2.AIDL要求minsdk>16,并且要使aidl true(在Gradle中添加) android{ buildFeatures { aidl true } } 我们看见,可以创建AIDL文件了 3.接着,我们看到文件出现如下提示 4.在gradle…...

如何进行渗透测试以提高软件安全性?
对于各种规模的企业和组织来说,软件安全是一个至关重要的问题。随着网络攻击越来越复杂,软件中的漏洞越来越多,确保你的软件安全比以往任何时候都更重要。提高软件安全性的一个有效方法是渗透测试(penetration testing)…...

YOLOv5 添加 OTA,并使用 coco、CrowdHuman数据集进行训练。
YOLO-OTA 第一步:拉取 YOLOv5 的代码第二步:添加 ComputeLossOTA 函数第二步:修改 train 和 val 中损失函数为 ComputeLossOTA 函数1、在 train.py 中 首先添加 ComputeLossOTA 库。2、在 train.py 修改初始化的损失函数3、在 train.py 修改一…...

SpringBoot 日志
目录 1.如何使用日志 2.自定义打印日志 3.日志级别 3.1 日志从低到高级别 3.2 日志级别设置 为什么 Spring Boot 可以打印日志?并设置日志级别? 4.日志的持久化 5.lombok——更加简单的输出日志 5.1 使用slf4j 注解输出日志 5.2 lombok 执行原…...

非小米笔记本小米妙享中心安装最新教程 3.2.0.464 兼容所有Windows系统
小米妙享中心 3.2.0.464 版本帮助 : 支持音频流转、屏幕镜像、屏幕拓展、键鼠拓展、无线耳机、小米互传 目录 小米妙享中心 3.2.0.464 版本帮助 : 1.常规教程使用安装包方式安装失败 或者 1.1安装失败可使用大佬的加载补丁方法解决 补充卸载残留 1.2 截图存档 2. 本教程…...

基于大数据的社交平台数据爬虫舆情分析可视化系统 计算机竞赛
文章目录 0 前言1 课题背景2 实现效果**实现功能****可视化统计****web模块界面展示**3 LDA模型 4 情感分析方法**预处理**特征提取特征选择分类器选择实验 5 部分核心代码6 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于大数据…...
MYSQL(事务)
一、什么是事务,四大特性 事务:一组操作的集合,它是一个不可分割的单位,事务会将这些操作作为一个整体一起像系统提交,这些操作要么同时成功,要么同时失败 四大特性(ACID) 原子性&am…...
npm start启动的是什么
npm start 命令是在一个 Node.js 项目中执行的一个自定义命令,用于启动该项目。该命令是在 package.json 文件中定义的,通常被用于启动一个 Web 应用程序或服务。 具体来说,当在项目目录下执行 npm start 命令时,npm 将会在该项目…...

基于PyTorch的MNIST手写体分类实战
第2章对MNIST数据做了介绍,描述了其构成方式及其数据的特征和标签的含义等。了解这些有助于编写合适的程序来对MNIST数据集进行分析和识别。本节将使用同样的数据集完成对其进行分类的任务。 3.1.1 数据图像的获取与标签的说明 MNIST数据集的详细介绍在第2章中已…...
conda 复制系统环境
直接复制 想要通过 conda 直接复制一个已存在的环境,你可以使用 conda create 命令并配合 --clone 参数。以下是具体步骤: 查看现有的环境: 首先,你可以使用以下命令来查看所有的 conda 环境: conda env list这会给你一个环境列表…...

如何在Microsoft Visual Studio 中使用Cpp代码调用python代码
Microsoft Visual Studio中Cpp调用Python代码 本文介绍如何在Microsoft Visual Studio中,开发cpp项目时,调用python代码。 文章目录 Microsoft Visual Studio中Cpp调用Python代码前言一、Cpp生成exe文件1.1 安装python环境1.2 配置Microsoft Visual Stu…...

DAY35 435. 无重叠区间 + 763.划分字母区间 + 56. 合并区间
435. 无重叠区间 题目要求:给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。 注意: 可以认为区间的终点总是大于它的起点。 区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。 示例 1: 输入: [ […...

代码随想录算法训练营第2天| 977有序数组的平方、209长度最小的子数组。
JAVA代码编写 977. 有序数组的平方 给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。 示例 1: 输入:nums [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释&…...
微信小程序通过startLocationUpdate,onLocationChange获取当前地理位置信息,配合腾讯地图解析获取到地址
先创建个getLocation.js文件 //获取用户当前所在的位置 const getLocation () > {return new Promise((resolve, reject) > {let _locationChangeFn (res) > {resolve(res) // 回传地里位置信息wx.offLocationChange(_locationChangeFn) // 关闭实时定位wx.stopLoc…...

C/C++字符三角形 2020年12月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析
目录 C/C字符三角形 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 C/C字符三角形 2020年12月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 给定一个字符,用它构造一个底边长5个字…...

Python数据挖掘:入门、进阶与实用案例分析——基于非侵入式负荷检测与分解的电力数据挖掘
文章目录 摘要01 案例背景02 分析目标03 分析过程04 数据准备05 属性构造06 模型训练07 性能度量08 推荐阅读赠书活动 摘要 本案例将根据已收集到的电力数据,深度挖掘各电力设备的电流、电压和功率等情况,分析各电力设备的实际用电量,进而为电…...

基于 Qt控制开发板 LED和C语言控制LED渐变亮度效果
## 资源简介 在STM32开发板,板载资源上有两个可自由控制的 LED。如下图原理 图其中我们以操作 LED1 为示例,LED1 为出厂系统的心跳指示灯。 ## 应用实例 想要控制这个 LED,首先出厂内核已经默认将这个 LED 注册成了 gpio-leds类型设备。所以我们可以直接在应用层接口直接…...

Android 11.0 禁用插入耳机时弹出的保护听力对话框
1.前言 在11.0的系统开发中,在某些产品中会对耳机音量调节过高限制,在调高到最大音量的70%的时候,会弹出音量过高弹出警告,所以产品 开发的需要要求去掉这个音量弹窗警告功能 2.禁用插入耳机时弹出的保护听力对话框的核心类 frameworks\base\packages\SystemUI\src\com\and…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...