IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 【开源】libserial_parse_text:适用于单片机实现串口命令行解析的基础库 -> 正文阅读

[嵌入式]【开源】libserial_parse_text:适用于单片机实现串口命令行解析的基础库

借助五一假期,我又写了一个串口命令行解析的基础库,虽然写着适用于单片机,但实际上并不限制具体的硬件平台。

具有以下几种特点:

  • 不涉及到具体硬件, 纯软件协议,与具体硬件分离。
  • 支持不定长命令行,逐个字符解码,可以支持不定长的命令参数解析。
  • 内存空间占用可控,可使用静态内存,也可以使用动态内存,内存空间可控。
  • 分割符可灵活定义,支持自定义分割符和忽略符号,面向对象设计,可多个实例应用。

源码仓库:
GitHub - lovemengx/libserial_parse_text: 适用于单片机实现串口命令行解析的基础库, 支持动静态内存方式适用于单片机实现串口命令行解析的基础库, 支持动静态内存方式. Contribute to lovemengx/libserial_parse_text development by creating an account on GitHub.https://github.com/lovemengx/libserial_parse_textlibserial_parse_text: 适用于单片机实现串口命令行解析的基础库https://gitee.com/lovemengx/libserial_parse_text一、接口说明

// 缓存大小包含了接口内部所使用的数据结构空间
typedef struct{
	char *buf;					// 缓存地址, 用于存储解析后的字符串
	unsigned int total;			// 缓存大小, 标明该内存空间的总长度
}libserial_parse_buf_t;

/*---------------------------------------------------------------------
*	函数: 	libserial_parse_create
*	功能:	使用接口内部申请指定可用大小的空间(包含内部数据结构所用空间)
*	参数:	size: 申请可用缓冲区大小 
*	返回:	NULL: 申请内存空间失败		>0: 申请成功
*---------------------------------------------------------------------*/
libserial_parse_buf_t *libserial_parse_create(unsigned int size);

/*---------------------------------------------------------------------
*	函数: 	libserial_parse_release
*	功能:	释放接口内部申请的内存空间
*	参数:	spbuf: 由 libserial_parse_create() 创建的内存空间
*	返回:	无返回值
*---------------------------------------------------------------------*/
void libserial_parse_release(libserial_parse_buf_t *spbuf);

/*---------------------------------------------------------------------
*	函数: 	libserial_parse_internal_size
*	功能:	返回内部数据结构占用字节数
*	参数:	无需参数
*	返回:	内部数据结构占用字节数(不同字长的处理器可能不一样)
*---------------------------------------------------------------------*/
unsigned int libserial_parse_internal_size();

/*---------------------------------------------------------------------
*	函数: 	libserial_parse_init
*	功能:	使用用户提供的或创建接口的缓冲区, 初始化内部数据结构
*	参数:	spbuf: 缓冲区  size: 缓冲区大小
*	返回:	0: 不满足最小长度要求  >0: 可存储最长文本的长度 
*	备注:	默认设置忽略字符为: '\0', 默认设置分隔字符为: '\n'
*---------------------------------------------------------------------*/
unsigned int libserial_parse_init(libserial_parse_buf_t *spbuf);

/*---------------------------------------------------------------------
*	函数: 	libserial_parse_reset_buf
*	功能:	重置解析器缓冲区
*	参数:	spbuf: 缓冲区
*	返回:	无返回值
*	备注:	不影响 libserial_parse_set_divide()\libserial_parse_set_ignore()
*---------------------------------------------------------------------*/
void libserial_parse_reset_buf(libserial_parse_buf_t *spbuf);

/*---------------------------------------------------------------------
*	函数: 	libserial_parse_set_divide
*	功能:	设定分隔字符
*	参数:	splbuf: 缓冲区  divide: 分隔字符
*	返回:	无返回值
*---------------------------------------------------------------------*/
void libserial_parse_set_divide(libserial_parse_buf_t *spbuf, char divide);

/*---------------------------------------------------------------------
*	函数: 	libserial_parse_set_ignore
*	功能:	设定忽略字符, 传入 '\0' 代表不忽略任何字符
*	参数:	splbuf: 缓冲区  ignore: 忽略字符
*	返回:	无返回值
*	备注:	双引号内的字符不会受此限制
*---------------------------------------------------------------------*/
void libserial_parse_set_ignore(libserial_parse_buf_t *spbuf, char ignore);

/*---------------------------------------------------------------------
*	函数: 	libserial_parse_text
*	功能:	解析以指定符号分隔或跳过的文本
*	参数:	splbuf: 缓冲区  indata: 输入数据
*	返回:	0: 正在解析  	>0:解析完成, 返回文本长度(不包含 '\0')
*	备注:	没有设定分隔符则会一直返回0, 数据超出缓存长度会返回解析完成
*---------------------------------------------------------------------*/
unsigned int libserial_parse_text(libserial_parse_buf_t *spbuf, char indata);

/*---------------------------------------------------------------------
*	函数: 	libserial_parse_text_nl  (nl -> new line)
*	功能:	解析以换行符为终止符的文本(支持 '\n' 和 '\r\n')
*	参数:	splbuf: 缓冲区  indata: 输入数据
*	返回:	0: 正在解析  	>0:解析完成, 返回文本长度(不包含 '\0')
*	备注:	不受 libserial_parse_set_divide()\libserial_parse_set_ignore() 影响
*---------------------------------------------------------------------*/
unsigned int libserial_parse_text_nl(libserial_parse_buf_t *spbuf, char indata);

/*---------------------------------------------------------------------
*	函数: 	libserial_parse_finish
*	功能:	获取当前仍在缓冲区的字符数据
*	参数:	splbuf: 缓冲区 
*	返回:	0: 没有数据  	>0:剩余字符串长度(不包含 '\0')
*---------------------------------------------------------------------*/
unsigned int libserial_parse_text_finish(libserial_parse_buf_t *spbuf);

二、示例代码

#include <stdio.h>
#include "libserial_parse_text.h"

#define iprintf(format,...) 	printf("[inf]%s():%05d " format , __func__, __LINE__,##__VA_ARGS__)

/*---------------------------------------------------------------------
*	函数: 	dynamic_mem_newline_example
*	功能:	动态内存版本以行为分割符的示例代码
*---------------------------------------------------------------------*/
int dynamic_mem_newline_example(const char* string)
{
	libserial_parse_buf_t* spbuf = NULL;
	unsigned int len = 0x00, i = 0x00;

	// 创建缓冲区
	if ((spbuf = libserial_parse_create(512)) == NULL) {
		printf("reate parse buf failed.\n");
		return -1;
	}

	// 初始化缓冲区
	if ((len = libserial_parse_init(spbuf)) == 0x00) {
		printf("memory is too small.\n");
		libserial_parse_release(spbuf);
		return -1;
	}

	// 开始解析字符串
	printf("total:%d  len:%d\n", spbuf->total, len);
	for (i = 0; i < strlen(string); i++) {
		if ((len = libserial_parse_text_nl(spbuf, string[i])) > 0) {
			printf("[parse] : %-2d->[%s]\n", len, spbuf->buf);
		}
	}

	// 检查是否还有剩下的字符串
	if ((len = libserial_parse_text_finish(spbuf)) > 0) {
		printf("[finish]: %-2d->[%s]\n", len, spbuf->buf);
	}

	// 释放动态内存
	libserial_parse_release(spbuf);
	return 0;
}

/*---------------------------------------------------------------------
*	函数: 	static_mem_newline_example
*	功能:	静态内存版本以行为分割符的示例代码
*---------------------------------------------------------------------*/
int static_mem_newline_example(const char* string)
{
	char buff[512] = { 0 };
	libserial_parse_buf_t spbuf;
	unsigned int len = 0x00, i = 0x00;

	// 指定静态内存
	spbuf.buf = buff;
	spbuf.total = sizeof(buff);

	// 初始化缓冲区
	if ((len = libserial_parse_init(&spbuf)) == 0x00) {
		printf("memory is too small.\n");
		return -1;
	}

	// 开始解析字符串
	printf("total:%d  len:%d\n", spbuf.total, len);
	for (i = 0; i < strlen(string); i++) {
		if ((len = libserial_parse_text_nl(&spbuf, string[i])) > 0) {
			printf("[parse] : %-2d->[%s]\n", len, spbuf.buf);
		}
	}

	// 检查是否还有剩下的字符串
	if ((len = libserial_parse_text_finish(&spbuf)) > 0) {
		printf("[finish]: %-2d->[%s]\n", len, spbuf.buf);
	}

	return 0;
}

/*---------------------------------------------------------------------
*	函数: 	static_mem_divide_example
*	功能:	静态内存版本以自定义分割符的示例代码
*---------------------------------------------------------------------*/
int static_mem_divide_example(const char* string)
{
	char buff[512] = { 0 };
	libserial_parse_buf_t spbuf;
	unsigned int len = 0x00, i = 0x00;

	// 指定静态内存
	spbuf.buf = buff;
	spbuf.total = sizeof(buff);

	// 初始化缓冲区
	if ((len = libserial_parse_init(&spbuf)) == 0x00) {
		printf("memory is too small.\n");
		return -1;
	}

	// 命令格式假定:  命令名称 参数1, 参数2, 参数3
	libserial_parse_set_divide(&spbuf, ' ');	// 设置分隔字符为空格, 提取命令名称
	libserial_parse_set_ignore(&spbuf, '\0');	// 设置忽略字符为字符串结束符, 即不忽略任何字符

	// 开始解析字符串
	printf("total:%d  len:%d\n", spbuf.total, len);
	for (i = 0; i < strlen(string); i++) {
		if ((len = libserial_parse_text(&spbuf, string[i])) > 0) {
			printf("[parse] : %-2d->[%s]\n", len, spbuf.buf);
			libserial_parse_set_divide(&spbuf, ','); // 设置分隔字符为逗号, 提取参数
			libserial_parse_set_ignore(&spbuf, ' '); // 设置忽略字符为空格, 忽略参数中的空格字符
		}
	}

	// 检查是否还有剩下的字符串
	if ((len = libserial_parse_text_finish(&spbuf)) > 0) {
		printf("[finish]: %-2d->[%s]\n", len, spbuf.buf);
	}

	return 0;
}

// 解析命令
int serial_command_text(libserial_parse_buf_t* spbuf, const char* string)
{
	unsigned int i = 0x00;

	for (i = 0; i < strlen(string); i++) {
		if (libserial_parse_text(spbuf, string[i])) {
			return 1;
		}
	}

	return !!libserial_parse_text_finish(spbuf);
}

// 解析命令参数
int serial_exec_command(libserial_parse_buf_t* spbuf, const char* command, const char* paramet)
{
	unsigned int i = 0x00;

	printf("[command]: [%s]\n", command);

	for (i = 0; i < strlen(paramet); i++) {
		if (libserial_parse_text(spbuf, paramet[i])) {
			printf("[paramet]: [%s]\n", spbuf->buf);
		}
	}

	if (libserial_parse_text_finish(spbuf)) {
		printf("[paramet]: [%s]\n", spbuf->buf);
	}
	printf("\n");
	
	// 执行命令代码......

	return 0;
}

/*---------------------------------------------------------------------
*	函数: 	serial_command_parse_example
*	功能:	动态内存版本完整的命令行解析示例代码
*---------------------------------------------------------------------*/
int serial_command_parse_example(const char* string)
{
	unsigned int i = 0x00, j = 0x00;
	libserial_parse_buf_t* spbuf1 = libserial_parse_create(256);
	libserial_parse_buf_t* spbuf2 = libserial_parse_create(64);
	libserial_parse_buf_t* spbuf3 = libserial_parse_create(256);

	// 初始化缓冲区
	libserial_parse_init(spbuf1);
	libserial_parse_init(spbuf2);
	libserial_parse_init(spbuf3);

	// 命令格式假定:  命令名称 参数1,参数2,参数3
	libserial_parse_set_divide(spbuf2, ' ');	// 设置解析命令的分隔字符为空格, 提取命令名称
	libserial_parse_set_ignore(spbuf2, '\0');	// 设置解析命令的忽略字符为字符串结束符, 即不忽略任何字符
	libserial_parse_set_divide(spbuf3, ',');    // 设置解析参数的分隔字符为逗号, 提取参数
	libserial_parse_set_ignore(spbuf3, ' ');    // 设置解析参数的忽略字符为空格, 忽略参数中的空格字符

	// 模拟串口收到的数据
	for (i = 0; i < strlen(string); i++)
	{
		// 解析字符串
		if (libserial_parse_text_nl(spbuf1, string[i]) == 0) {
			continue;
		}

		// 解析命令
		printf("[parse]:   [%s]\n", spbuf1->buf);
		if (serial_command_text(spbuf2, spbuf1->buf) == 0) {
			continue;
		}

		// 解析参数并执行命令
		serial_exec_command(spbuf3, spbuf2->buf, spbuf1->buf + strlen(spbuf2->buf));
	}

	// 释放缓冲区
	libserial_parse_release(spbuf1);
	libserial_parse_release(spbuf2);
	libserial_parse_release(spbuf3);

	return 0;
}

int main(void)
{
	const char* string = "@ABCDEFGHIJKLAA@\n\nQQ:1007566569\r\nlovemengx@qq.com\n123456789#++++++.....";
	const char* strcmd = "reg_w 0x01=0x20, 0x02= 0x15, 0x03=0x56";
	const char* strcmds = "wifi \"my wifi\",12345678\nvideo udp,192.168.1.115,8000\nreg_w 0x01=0x20, 0x02= 0x15, 0x03=0x56\nreg_r 0x01,0x02,0x05,0x06\nreboot\n";

	// 静态内存解析以行分隔的字符串示例
	printf("------------------------------------\n");
	printf("static memory newline example...\n");
	printf("------------------------------------\n");
	static_mem_newline_example(string);

	// 动态内存解析以行分隔的字符串示例
	printf("------------------------------------\n");
	printf("dynamic memory newline example...\n");
	printf("------------------------------------\n");
	dynamic_mem_newline_example(string);
	printf("------------------------------------\n");

	// 动态内存解析以自定义分隔和忽略的字符串示例
	printf("------------------------------------\n");
	printf("dynamic memory divide example...\n");
	printf("------------------------------------\n");
	static_mem_divide_example(strcmd);
	printf("------------------------------------\n");

	// 解析命令、参数并执行命令的完整示例
	printf("------------------------------------\n");
	printf("command parse example...\n");
	printf("------------------------------------\n");
	serial_command_parse_example(strcmds);
	printf("------------------------------------\n");

	return 0;
}

三、执行结果

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:35:52  更:2022-05-05 11:40:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:46:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码