自定义用户层的灵活性串口通信协议
先说明这里提到的灵活性其实也是相对来说的,并不是说明数据包都可以定义。
用户层串口通信协议
简单的来说用户层的串口通信协议就是如何定义一个数据包格式,发送端按照规定的数据包格式发送出去,接收端按照规定的数据包格式解析出正确的数据。
那为什么又要在用户层定义呢,其一是因为底层的通信协议不是随随便便就可以写出来的,二是因为我们在市面上买到的串口模块本身就已经有了底层通信协议,我们又何必去再自己写呢。
定义数据包格式
因为是第一次接触串口,所以肯定先上网搜了搜常见的数据包模板,发现基本上数据包格式有以下元素:
帧头 包序号 数据长度 数据 校验 帧尾
因为并不需要数据包定义的复杂,所以决定就从以上的元素来构思我自己的数据包格式。
首先,既然提到了灵活性,那么上面的部分元素可以存在或者不存在,存在的话又可以更换位置,之所以说部分元素是因为考虑以下几点:
- 帧头位置固定存在,这个不需要解释;
- 数据长度存在则必须放到数据的前面,这样更方便我们解析不定长数据;
- 校验必须存在且放在数据后面,因为校验本身就是为了检查数据的正确性,放到前面也不便于我们解析;
通过以上几点对各种形式的数据包排除后还剩18种,也就是说我定义的灵活性串口通信协议一共支持18种数据包(有无帧尾对半分)。
帧头 | 序号 | 数据长度 | 数据 | 校验 | 帧尾 |
帧头 | 数据长度 | 序号 | 数据 | 校验 | 帧尾 |
帧头 | 数据长度 | 数据 | 序号 | 校验 | 帧尾 |
帧头 | 数据长度 | 序号 | 校验 | 序号 | 帧尾 |
帧头 | 序号 | 数据 | 校验 | 帧尾 | |
帧头 | 数据 | 序号 | 校验 | 帧尾 | |
帧头 | 数据 | 校验 | 序号 | 帧尾 | |
帧头 | 数据长度 | 数据 | 校验 | 帧尾 | |
帧头 | 数据 | 校验 | 帧尾 |
- 帧头必须存在,长度不限,但不建议太长;
- 序号可定义1-4字节,若定义1字节,序号从1-255循环;
- 数据长度可定义1-4字节;
- 数据不定长,和数据长度匹配;
- 校验1字节,暂时只考虑累加计数,用unsigned char保存;
- 帧尾可有可无,长度不限;
注意事项:
- 定义的数据包发送的数据只能是字符'0'-'9','a'-'z','A'-'Z';而帧头和帧尾的字符肯定和数据字符不同,所以不考虑数据中出现帧头或帧尾的情况;
- 因为是系统与系统之间串口通信,所以需要考虑大小端问题,我自己定义发送为大端模式,接收端需要判断自身系统的模式来获取数据;
- 发送和接收的频率,因为工作要求,我自考虑了发送频率比接收频率快的情况(范围有限),并且当发送和接收的频率不同时,数据包的序号不可以让程序来自动改变;
- 还有一些代码上的特殊注意,不要用strlen来获取数据包的长度,因为会存在'\0'字符,比如序号大小为3字节,但序号为12,这其余两个字节为0,0就是'\0';存放数据的变量类型一定要认真选择,如序号大小是0-4字节不固定,所以我们需要一个字节一个字节的进行存放和解析,那么会有情况是字节大小为3,序号为1023,如果用char一个一个去获取的话,你懂得;还有一些其他细节问题就不一一说明了。
API
建议将代码封装成库,然后提供几个接口供用户使用即可,这样也方便用户切换其他串口通信协议。
我自己是提供了三个接口:
1. int GetPacketSize(stPacketFormat stPacket,int bufLen);
- 参数 : stPacket 是从xml解析出来的数据包格式,bufLen为要发送的数据长度。
- 返回值: 组装成的数据包大小;
2. int CreatePacket(stPacketFormat stPacket,char **dataBuf,int bufLen);
- 参数 : stPacket 是从xml解析出来的数据包格式,*dataBuf为根据GetPacketSize的返回值创建的数组,用来存放组装成的数据包,bufLen为发送的数据长度。
- 返回值: 成功为0,非0失败;
3. int ParsePacket(stPacketFormat stPacket,char **dataBuf,int *pDataLen);
- 参数 : stPacket 是从xml解析出来的数据包格式,dataBuf传进去从串口获取到的数据,函数调用成功后,解析出来的数据也从dataBuf获取,pDataLen传进去dataBuf的长度,函数调用成功后,返回实际数据*dataBuf的长度。
收发数据包
- 先说配置数据包格式,可以采用xml文件来进行配置,程序通过解析xml来设置数据包格式;
- 发送端调用GetPacketSize获取数据包大小,创建数组将发送的数据传给CreatePacket封装成数据包;
- 发送端将数据包通过串口发送出去;
- 接收端从串口接收数据,然后将数据传给ParsePacket进行解析,获取到实际需要的数据。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix