首页 > 其他分享 >串口HEX字节流交互协议解析库分享

串口HEX字节流交互协议解析库分享

时间:2024-10-16 11:45:35浏览次数:5  
标签:Protocol 字节 MEM HEX unsigned char 串口 POOL define

通信协议解析库说明

一、概述

用于上位机串口通讯协议解析,协议格式:AA len type id data 校验

帧头(1byte) 长度(1byte) 协议类型(1byte) 命令ID(1byte) 数据(xbyte) 校验和(1byte)
AA x x x x 异或校验和

固定帧头:0xAA

校验和:从AA到校验和之前的所有字节进行异或校验

二、头文件

#ifndef VPPROTOCOLLIB_H
#define VPPROTOCOLLIB_H

/**
 ****************************************************************************************
 *
 * @file protocol.h
 *
 * @brief Attribute Protocol
 *
 ****************************************************************************************
 * @attention
  #####Copyright (c) 2024 veis
  All rights reserved.
 *****************************************************************************************
 *************************************Instructions for use*********************************
    * Step 1: Call Protocol_Init to Initialization the lib.
    * Step 2: Define a sMsgType_t variable to bind the message and the callback function.
    * Step 3: Use the Protocol_RegisterCmdCB function to register the message and the callback function.
    * Step 4: Timely invocation of Protocol_SetPacket for data packet grouping and parsing in tasks
    *         receiving byte streams.
    * PS:
    *       (1)Can use the Protocol_GetVersion to get the lib version
    *       (2)If use dynamic memory, should use Protocol_FreeMsgPool to free memory
    *
 *****************************************************************************************
 */

#ifdef __cplusplus
extern "C" {
#endif

// 使用静态内存池
#define DYNAMIC_MEM_POOL_CONFIG 0x01
// 使用静态内存池
#define STATIC_MEM_POOL_CONFIG  0x02

// 内存池类型
#define MEM_POOL_TYPE DYNAMIC_MEM_POOL_CONFIG
// 消息内存池大小
#define MSG_POOL_SIZE   (500)

#if (MEM_POOL_TYPE != STATIC_MEM_POOL_CONFIG) && (MEM_POOL_TYPE != DYNAMIC_MEM_POOL_CONFIG)
#error "please set the MEM_POOL_TYPE into a vaild vaule!"
#endif

/**
 *  协议通用部分
 */
#define FRAME_HEAD              0xAA // 帧头
#define HEAD_INX                0    // 帧头数组下标偏移
#define DATA_LEN_IDX            1    // 长度数组下标偏移
#define PROTOCOL_ID_IDX         2    // 协议标识数组下标偏移
#define FUNC_ID_IDX             3    // 功能字数组下标偏移
#define MIN_FRAME_LEN           5    // 最小帧长度

// 消息处理回调函数类型
typedef void (*pMsgFuncHandle)(void *param, unsigned int len);

// 消息池状态码
typedef enum
{
    MSG_POOL_OK = 0,       //正常
    MSG_POOL_ERROR,        //错误
    MSG_POOL_OVERLOAD,     //已满
    MSG_POOL_REPEAT,       //重复
} MsgPoolStatus_t;

// 数据包类型
typedef struct __attribute__((aligned(4))) // 4字节对齐,加速32位操作系统下的访问
{
    unsigned char m_head;       // 协议头
    unsigned char m_len;        // 数据长度
    unsigned char m_cmdType;    // 协议标识
    unsigned char m_cmdID;      // 命令ID
    unsigned char *m_pbuf;      // 数据缓冲区地址
    unsigned char m_checksum;   // 校验和
} sDataPacketType_t;

// 消息类型
typedef struct
{
    unsigned char m_cmdType;    // 协议标识
    unsigned char m_cmdID;      // 命令ID
    pMsgFuncHandle m_cb;        // 回调函数
} sMsgType_t;


/**
 * @brief 初始化协议解析需要用到的资源
 * @return 0:操作成功,-1:操作失败
 */
int Protocol_Init(void);

/**
 * @brief 绑定注册命令和回调函数
 * @param pcb 控制块
 * @return 见@MsgPoolStatus_t
 */
int Protocol_RegisterCmdCB(sMsgType_t *pcb);

/**
 * @brief 从命令池里面删除命令,需要通过协议标识+命令ID来索引移除
 * @param cmdType 需要移除的协议标识
 * @param cmdID 需要移除的命令ID
 * @return
 */
int Protocol_RemoveCmd(unsigned char cmdType, unsigned char cmdID);

/**
 * @brief 把串口字节流转为数据包压入队列
 * @param pbuf 字节流缓冲区地址
 * @param len 字节个数
 * @return 0:操作成功,-1:操作失败
 */
int Protocol_SetPacket(unsigned char *pbuf, unsigned int len);

/**
 * @brief 释放内存池
 */
void Protocol_FreeMsgPool(void);

/**
 * @brief 获取版本
 * @return 返回版本的字符串
 */
char *Protocol_GetVersion(void);

#ifdef __cplusplus
}
#endif


#endif // VPPROTOCOLLIB_H

三、调用时序图

四、库编译说明

  • 安装Qt Creator,创建动态库工程

  • 添加vpprotocollib.cpp和vpprotocollib.h文件到工程

  • 使用qmake选择released和debug分别编译项目,生成库文件(编译输出的文件如下图所示)

五、调用示例

#include "vpprotocollib.h"
#include <windows.h>
#include <iostream>

static void test_cb(void *param, unsigned int len)
{
   std::cout << "testcb be call!" << std::endl;
}

static void test_cb1(void *param, unsigned int len)
{
   unsigned char *pdata = (unsigned char *)param;
   int i;

   for(i = 0; i < len; i++)
   {
       printf("0x%02x ", pdata[i]);
   }
   std::cout << std::endl;
   std::cout << "testcb1 be call!" << std::endl;
}

int main(int argc, char *argv[])
{
    unsigned char test_buf[] = "\xAA\x02\x9F\x80\xB7\x55\xAA\x04\x9F\x01\x02\x03\x31"; // TEST BUFFER
    sMsgType_t msg = {.m_cmdType = 0x9f, .m_cmdID = 0x80, .m_cb = test_cb};
    sMsgType_t msg2 = {.m_cmdType = 0x9f, .m_cmdID = 0x01, .m_cb = test_cb1};

    Protocol_Init();
    Protocol_RegisterCmdCB(&msg);
    Protocol_RegisterCmdCB(&msg2);

    std::cout << Protocol_GetVersion() << std::endl;

    while(true)
    {
        Protocol_SetPacket(test_buf, sizeof(test_buf));
        Sleep(1000);
    }
    return 0;
}

库源码:https://gitee.com/veis/protocol-lib

标签:Protocol,字节,MEM,HEX,unsigned,char,串口,POOL,define
From: https://www.cnblogs.com/veis/p/18469548

相关文章

  • 博客搭建之路:hexo使用next主题博客侧边栏标题点击不跳转
    hexo使用next主题博客侧边栏标题点击不跳转hexo版本5.0.2npm版本6.14.7next版本7.8.0本着我肯定不是第一个出这个问题的人,去github上找了找,果然我不是第一个好吧,也跟着改吧(修改themes/next/source/js/utils.js),找到registerSidebarTOC函数registerSidebarTOC:functio......
  • C# 实现串口通信
    usingSystem;usingSystem.IO.Ports;usingSystem.Linq;usingSystem.Text;usingSystem.Threading;namespaceDAL{publicclassAsySerialDal{privatestaticreadonlyobjectsyncRoot=newobject();constintCOMDAL_RECVBUF_SIZE......
  • 字节与字符
    字节(Byte)和字符(Character)是计算机科学中两个基本概念,它们之间有着重要的区别:字节(Byte)定义:字节是计算机存储和处理数据的基本单位,通常由8位二进制数字(比特)组成。用途:用于存储数据,如文件、图像、音频等。在内存中,字节用于表示不同类型的数据(整型、浮点型等)。范围:一个字......
  • 先到先得!字节内疯传的380页《从零开始大模型开发与微调基于PyTorch与ChatGLM》大模型
    大模型是深度学习自然语言处理皇冠上的一颗明珠,也是当前AI和NLP研究与产业中最重要的方向之一。本书使用PyTorch2.0作为学习大模型的基本框架,以ChatGLM为例详细讲解大模型的基本理论、算法、程序实现、应用实战以及微调技术,为读者揭示大模型开发技术。实战案例丰富基于Py......
  • Educoder——JAVA高级特性 字节流-输入输出
    任务描述本关任务:使用输入输出流读写文件。相关知识为了完成本关任务,你需要掌握:1.如何使用输入流;2.如何使用输出流。输入流我们通过一个示例,来看看输入流应该如何使用,首先我们在D盘下创建一个hello.txt文件。输入文本HelloJavaHelloInputStream。在main方法中加入如......
  • 超级干货!Air780E的串口通信分享
    ​  猛然发现,Air780E的串口通信还没分享,难怪已经有小伙伴提出了要求!那我们来讲解低功耗4G模组Air780E的串口通信的基本用法,小伙伴们,学起来吧!一、硬件准备  ​780E开发板一套,包括天线、USB数据线。USB转TTL工具或线(例如ch340、ft232)PC电脑,串口调试工具(例如:llcom......
  • PROFINET 转 EtherCAT, EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关
    EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关https://item.taobao.com/item.htm?ft=t&id=822721028899协议转换通信网关PROFINET转EtherCATGW系列型号 MS-GW31概述简介MS-GW31是PROFINET和EtherCAT协议转换网关,为用户提供两种不同通讯协议......
  • STM32与ESP32串口数据发送以及网页端数据实时显示和远程遥控
    目标:实现网页端速度实时显示以及可以通过点击页面按键达到对小车的位移方位控制。一、ESP32代码首先,需要让ESP32连接到WiFi,这样才能为后续的操作做准备。ssid="xxxxxx"password="xxxxxx"#WIFI连接defwifi_connect():wlan=network.WLAN(network.STA_IF)#STA模式......
  • hexo-开源框架-创建博客
    hexo-开源框架-创建博客导语现在随着计算机的飞速发展,拥有一个属于自己的博客,是一件非常平常的事。使用hexo搭建一个属于自己的个人博客,是即快捷又美观的一种方式,也是非常受到人们的喜爱的。hexo介绍Hexo是一款基于Node.js的静态博客框架,依赖少易于安装使用,可以方便的生成......
  • linux系统epoll的ET/LT模式-附串口接收代码
    LT模式下,读事件触发后,可以按需收取想要的字节数,不用把本次接收到的数据收取干净(即不用循环到recv或者read函数返回-1,错误码为EWOULDBLOCK或EAGAIN);ET模式下,读事件必须把数据收取干净,因为你不一定有下一次机会再收取数据了,即使有机会,也可能存在上次没读完的数据没有及时......