自定义用户层的灵活性串口通信协议

想不到第一次接触串口就要去写一个自定义的灵活性串口通信协议,所以在这里记录一下自己的心得,有什么不合理的地方还请大佬们指出。

先说明这里提到的灵活性其实也是相对来说的,并不是说明数据包都可以定义。

一、用户层串口通信协议

  简单的来说用户层的串口通信协议就是如何定义一个数据包格式,发送端按照规定的数据包格式发送出去,接收端按照规定的数据包格式解析出正确的数据。

  那为什么又要在用户层定义呢,其一是因为底层的通信协议不是随随便便就可以写出来的,二是因为我们在市面上买到的串口模块本身就已经有了底层通信协议,我们又何必去再自己写呢。

二、定义数据包格式

  因为是第一次接触串口,所以肯定先上网搜了搜常见的数据包模板,发现基本上数据包格式有以下元素:

    帧头  包序号  数据长度  数据  校验  帧尾

  领导并不需要数据包定义的复杂,所以决定就从以上的元素来构思我自己的数据包格式。

  首先,既然提到了灵活性,那么上面的部分元素可以存在或者不存在,存在的话又可以更换位置,之所以说部分元素是因为考虑以下几点:

    1.帧头位置固定存在,这个不需要解释;

    2.数据长度存在则必须放到数据的前面,这样更方便我们解析不定长数据;

    3.校验必须存在且放在数据后面,因为校验本身就是为了检查数据的正确性,放到前面也不便于我们解析;

  通过以上几点对各种形式的数据包排除后还剩18种,也就是说我定义的灵活性串口通信协议一共支持18种数据包(有无帧尾对半分)。

帧头 序号 数据长度 数据 校验 帧尾
帧头 数据长度 序号 数据 校验 帧尾 
帧头 数据长度 数据 序号 校验 帧尾
帧头 数据长度  数据  校验  序号  帧尾 
帧头 序号  数据  校验 帧尾   
帧头 数据  序号  校验 帧尾   
帧头 数据  校验 序号  帧尾   
帧头 数据长度  数据  校验 帧尾   
帧头 数据  校验 帧尾     

      帧头:必须存在,长度不限,但不建议太长;

      序号:可定义1-4字节,若定义1字节,序号从1-255循环;

      数据长度:可定义1-4字节;

      数据:不定长,和数据长度匹配;

      校验:1字节,暂时只考虑累加计数,用unsigned char保存;

      帧尾:可有可无,长度不限;

三、注意事项:

  1.定义的数据包发送的数据只能是字符‘0‘-‘9‘,‘a‘-‘z‘,‘A‘-‘Z‘;而帧头和帧尾的字符肯定和数据字符不同,所以不考虑数据中出现帧头或帧尾的情况;

  2.因为是系统与系统之间串口通信,所以需要考虑大小端问题,我自己定义发送为大端模式,接收端需要判断自身系统的模式来获取数据;

  3.发送和接收的频率,因为工作要求,我自考虑了发送频率比接收频率快的情况(范围有限),并且当发送和接收的频率不同时,数据包的序号不可以让程序来自动改变;

  4.还有一些代码上的特殊注意,不要用strlen来获取数据包的长度,因为会存在‘\0‘字符,比如序号大小为3字节,但序号为12,这其余两个字节为0,0就是‘\0‘;存放数据的变量类型一定要认真选择,如序号大小是0-4字节不固定,所以我们需要一个字节一个字节的进行存放和解析,那么会有情况是字节大小为3,序号为1023,如果用char一个一个去获取的话,你懂得;还有一些其他细节问题就不一一说明了。

四、API

  建议将代码封装成库,然后提供几个接口供用户使用即可,这样也方便用户切换其他串口通信协议。

  我自己是提供了三个接口:

      int GetPacketSize(stPacketFormat stPacket,int bufLen);    

      参数 :  stPacket 是从xml解析出来的数据包格式,bufLen为要发送的数据长度。
      返回值:  组装成的数据包大小;

      int CreatePacket(stPacketFormat stPacket,char **dataBuf,int bufLen);    

      参数   :  stPacket 是从xml解析出来的数据包格式,*dataBuf为根据GetPacketSize的返回值创建的数组,用来存放组装成的数据包,bufLen为发送的数据长度。

      返回值:  成功为0,非0失败;

      int ParsePacket(stPacketFormat stPacket,char **dataBuf,int *pDataLen);

      参数 :  stPacket 是从xml解析出来的数据包格式,*dataBuf传进去从串口获取到的数据,函数调用成功后,解析出来的数据也从*dataBuf获取,*pDataLen传进去*dataBuf的长度,函数调用成功后,返回实际数据*dataBuf的长度。

  

四、收发数据包

  1.先说配置数据包格式,可以采用xml文件来进行配置,程序通过解析xml来设置数据包格式;

  2.发送端调用GetPacketSize获取数据包大小,创建数组将发送的数据传给CreatePacket封装成数据包;

  3.发送端将数据包通过串口发送出去;

  4.接收端从串口接收数据,然后将数据传给ParsePacket进行解析,获取到实际需要的数据。

思路就记录到这,具体实现的代码其实不重要。

原文地址:https://www.cnblogs.com/jiangyibo/p/9026080.html

时间: 2024-10-22 09:42:06

自定义用户层的灵活性串口通信协议的相关文章

单片机: 自定义串口通信协议的实现

使用51单片机完成一个简单的串口通信协议. 要求: 一个协议帧为8个字节,其中头部两个字节,分别是0xFF,0xFE; 第3个字节代表第一个数据,第4个字节代表第二个数据(均为正数); 第5个字节如果是0,代表两个数据的和,1的话代表两个数据的差; 第6个字节为0,代表使用十进制显示,为1代表十六进制显示; 最后两个字节代表协议尾部,值分别为0xFD,0xFC. 将传输的两个数据和他们的计算结果分别显示在数码管上. 注意,如果差为负数,要将负号显示出来. 思路:使用串口中断,先接收8个字节至数组

Linux用户层直接操作GPIO

Linux用户层直接操作GPIO 在一个老手的指导下,应用层可以直接操作GPIO,具体指设置GPIO的输入输出以及输出电平高或者低.这个大大地提高了灵活性,官方的文档有GPIO Sysfs Interface for Userspace,GPIO Sysfs. 这里我记录一下使用过例子: # RK30_PIN0_PD4 # A0-7 -> 0-7 / B0-7 -> 8-15 / C0-7 -> 16-23 / D0-7 -> 24-31 echo 28 > /sys/cla

(九)ASP.NET自定义用户控件(2)

http://www.cnblogs.com/SkySoot/archive/2012/09/04/2670678.html 用户控件 在 .NET 里,可以通过两种方式把自己的控件插入到 Web 窗体框架中: 用户控件:它是一小段页面,可以包括静态 HTML 代码和 Web 服务器控件.用户控件的好处是一旦创建了它,就可以在同一个 Web 应用程序的多个页面重用它.用户控件可以加入自己的属性,事件和方法. 自定义服务器控件:它是被编译的类,它通过编程生成自己的 HTML .服务器控件总是预编译

Windows phone 在自定义用户控件(UserControl)——ColorPicker

编码前 学习Windows phone自定义用户控件,在<WPF编程宝典>学习的小例子.并根据windows phone稍微的不同,做了点修改.ColorPicker(颜色拾取器):拥有三个Slider代表颜色中的RGB的值,可以进行调节各自的值.还有一个显示颜色的区域,它的值可以设置,也可以随着三个Slider值得变化而变化.其中每个Slider值也要根据颜色区域而变化.还要提供一个能由外部看到的可注册事件. 依赖属性: 设置四个依赖属性:分别为ColorProperty,RedProper

OVS中对于用户层和datapath层的多个通道利用epoll进行控制

这里先暂时记录下代码流程,有待完善. static int construct(struct ofproto *ofproto_) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); const char *name = ofproto->up.name; int max_ports; int error; int i; error = dpif_create_and_open(name, ofproto->up.type

[原创]用户层关闭瑞星2009杀毒软件安全保护

原文链接:用户层关闭瑞星2009杀毒软件安全保护 我写这个纯粹是hacker精神,如果被滥用做病毒木马一类的邋遢东东,可跟偶没关系哦. 原理very简单,我发现瑞星监控主要在RavMonD进程中,如果打破其与内核的联系,则瑞星监控功能就无法正常工作了,怎么打破联系呢?如果是进内核的话当然有很多的办法,从而没有挑战性了,况且RavMonD会阻止用户进程去加载驱动或者动注册表的关键地方,比如run子键.下面上测试代码: 1 int main(int argc,char *argv[]) 2 { 3

ARMv7用户层发生指令异常的处理流程?是否每个进程都有一个APSR的副本?

1.用户层发生指令异常的处理流程? 用户层程序正在执行时,遇到未定义的指令(ARM不是别的指令)或者SWI软件中断指令(产生系统调用),就会产生异常,这里以未定义指令异常为例进行说明: 一旦出现未定义指令异常,CPU会自动做如下操作: (1)未定义模式(ARM其中运行模式的一种)下对应的lr(即R14)寄存器保存当前发生异常的指令下一条指令的地址.例如,在用户态有A B C 三条指令,指令A发生未定义指令异常,则指令B的地址就会由CPU保存到未定义模式下的lr寄存器中,用于异常返回. (2)CP

BAT解密:互联网技术发展之路(8)- 用户层技术剖析

互联网业务用户层技术主要包括:用户管理.消息推送.存储云.图片云. 用户管理 互联网业务的一个典型特征就是通过互联网将众多分散的用户连接起来.因此用户管理是互联网业务不可缺少的一部分. 略微大一点的互联网业务,肯定会涉及到多个子系统,这些子系统不可能每一个都自己来管理这么庞大的用户.由此引申出用户管理的第一个目标:SSO,单点登录,又叫统一登录.单点登录的技术实现手段较多,比如cookie.token等,最有名的开源方案当属CAS. 除此之外,当业务做大成为了平台后.开放成为了促进业务进一步发展

Django自定义用户认证

自定义一个用户认证 详细参考官方文档: https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#django.contrib.auth.models.PermissionsMixin.has_perms 一.创建用户的表 UserProfile():存放用户信息的表 UserProfileManager(): 用户创建用户的类方法 1.生成一个单独的Moel文件专门用来存放用户表 #!/usr/bin/env python #