# serial-private-protocol **Repository Path**: davidxu1993/serial-private-protocol ## Basic Information - **Project Name**: serial-private-protocol - **Description**: 一个简单的串行协议框架。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2025-07-03 - **Last Updated**: 2025-07-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 使用说明 **C语言版本** 请使能C99 **头文件路径** 配置IDE,将项目顶层目录配置到编译链接头文件查找路径下,注意,不是把`inc`,而是`inc`的所在的目录。 **自定义框架配置文件** 定义`pp_custom_config.h`文件,并且配置到编译链接查找目录下。可以参考`example/pp_custom_config.h`文件。 **调用接口头文件** 源文件只需要包含`inc/pp_template.h`即可。 ```c #include "inc/pp_template.h" ``` **pp_get_time_tick** 必须实现获取时刻的函数 ```c uint32_t pp_get_time_tick(void) { return thread_tick; } ``` **hw_send_cb** 需要实现串行发送回调函数,框架会调用这个函数把打包的报文发送出去。 ```c /* 函数指针类型 */ typedef int (*hw_send_cb)(const uint8_t *data, uint16_t len); static int my_hw_send_cb(const uint8_t *data, uint16_t len) { /* Use USB,UART,TCP etc. to send data */ // 伪代码 rt_hw_uart_send(data, len); return len; /* !!!若发送成功必须返回len,若发送失败不得返回len */ } ``` **notify_cb** 框架上报事件到应用层的回调函数。 ```c /* 函数指针类型 */ typedef void (*notify_cb)(struct pp_handle *h, uint8_t evt, const void *param); static void my_notify_cb(struct pp_handle *h, uint8_t evt, const void *param) { switch (evt) { /* 从机收到的事件 */ case EVT_SET_SPEED: ... break; ... default: LOG_D("unkown event.\n"); break; } } ``` **定义协议句柄并初始化** ```c struct pp_template_handle *h_template = NULL; int main(void) { h_template = pp_template_handle_new(); if (!h_template) { printf("create template handle fail."); exit(-1); } pp_template_handle_init(h_template, my_hw_send_cb, my_notify_cb); while (1) { pp_poll((struct pp_handle *)h_template); } pp_template_handle_delete(h_template); exit(0); } ``` **pp_poll** 循环调用该函数。可以死循环中调用,若线程优先级比较高可以适当自己增加延时。否则,无需加延时,因为框架在检测到接收缓存空的时候会调用PP_DELAY。 **最后** 主机想发送功能时,可以调用定义的API。 ```c /* master req slave APIs */ pp_err_t pp_template_set_speed(struct pp_template_handle *h, const param_of_notify_set_speed_t *param); pp_err_t pp_template_req_temperature(struct pp_template_handle *h, const param_of_notify_req_temperature_t *param); pp_err_t pp_template_set_temperature(struct pp_template_handle *h, const param_of_notify_set_temperature_t *param); ``` 然后主机只需要关注notify_cb函数中的事件即可。 具体请参考`example`文件夹。 ## 添加新的协议 请参考`inc/pp_template.h`和`inc/pp_template.c`文件,和`doc/通讯协议(模板).docx`。此处指的是自定义payload和功能码,若报文格式需要修改,则请修改`pp.c`。 **定义功能码** ```c /* master to slave function code 主机功能码 */ #define FUNC_SET_SPEED (0x01) #define FUNC_REQ_TEMPERATURE (0x04) #define FUNC_SET_TEMPERATURE (0x06) ``` image-20250703173057090 请求报文码 = 功能码 & 0xEF 应答报文码 = 功能码 | 0x80 **请求报文参数类型** ```c typedef struct { uint16_t frame_index; /* 报文序号,必须有且放结构体开始。 */ double speed; } param_of_notify_set_speed_t; ``` **应答报文参数类型** ```c typedef struct { result_t result; /* 应答结果,必须有且放结构体开始。 */ double speed; } param_of_notify_resp_of_set_speed_t; ``` **句柄及初始化函数** ```c /* 前置声明user句柄,具体定义隐藏在.c文件中了 */ struct pp_template_handle; /* 动态分配句柄空间 */ struct pp_template_handle *pp_template_handle_new(void); /* 释放分配的内存 */ pp_err_t pp_template_handle_delete(struct pp_template_handle *h); /* 将两个重要的回调函数与框架建立连接 */ pp_err_t pp_template_handle_init(struct pp_template_handle *h, hw_send_cb send, notify_cb notify); ``` **不同功能码对应的解析函数** ```c static const func_and_cb_t g_user_func_and_cb_list[] = { {EVT_SET_SPEED, set_speed_cb }, {EVT_REQ_TEMPERATURE, req_temperature_cb }, {EVT_SET_TEMPERATURE, set_temperature_cb }, {EVT_RESP_OF_SET_SPEED, resp_of_set_speed_cb }, {EVT_RESP_OF_REQ_TEMPERATURE, resp_of_req_temperature_cb}, {EVT_RESP_OF_SET_TEMPERATURE, resp_of_set_temperature_cb}, {0x00, NULL } /* Must be the last one */ }; ``` 原理很简单 ```c /* search for func, and call it's cb function */ if (h->func_and_cb_list) { const func_and_cb_t *pos = h->func_and_cb_list; while (pos->cb) { if (pos->func == frame.func) /* 检测功能码相同 */ { ... pos->cb(h, &frame); /* 执行相应解析函数 */ break; } else { pos++; } } } ``` 其他说明请参考`inc/pp_template.h`和`inc/pp_template.c`文件,和`doc/通讯协议(模板).docx`。