通信协议解析库说明
一、概述
用于上位机串口通讯协议解析,协议格式: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